diff --git a/build/package.json b/build/package.json index 6b7cb2206c2..3170776b039 100644 --- a/build/package.json +++ b/build/package.json @@ -24,7 +24,7 @@ "@types/minimist": "^1.2.1", "@types/mkdirp": "^1.0.1", "@types/mocha": "^8.2.0", - "@types/node": "^14.14.37", + "@types/node": "14.x", "@types/p-limit": "^2.2.0", "@types/plist": "^3.0.2", "@types/pump": "^1.0.1", diff --git a/build/yarn.lock b/build/yarn.lock index 01f0fc51ce6..db121457ccc 100644 --- a/build/yarn.lock +++ b/build/yarn.lock @@ -371,16 +371,16 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-8.0.51.tgz#b31d716fb8d58eeb95c068a039b9b6292817d5fb" integrity sha512-El3+WJk2D/ppWNd2X05aiP5l2k4EwF7KwheknQZls+I26eSICoWRhRIJ56jGgw2dqNGQ5LtNajmBU2ajS28EvQ== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== + "@types/node@^14.14.21": version "14.14.22" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" integrity sha512-g+f/qj/cNcqKkc3tFqlXOYjrmZA+jNBiDzbP3kH+B+otKFqAdPgVTGP1IeKRdMml/aE69as5S4FqtxAbl+LaMw== -"@types/node@^14.14.37": - version "14.14.37" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e" - integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw== - "@types/p-limit@^2.2.0": version "2.2.0" resolved "https://registry.yarnpkg.com/@types/p-limit/-/p-limit-2.2.0.tgz#94a608e9b258a6c6156a13d1a14fd720dba70b97" diff --git a/extensions/bat/cgmanifest.json b/extensions/bat/cgmanifest.json index 5bc3e285f0c..7e0426c1387 100644 --- a/extensions/bat/cgmanifest.json +++ b/extensions/bat/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "mmims/language-batchfile", "repositoryUrl": "https://github.com/mmims/language-batchfile", - "commitHash": "95ea8c699f7a8296b15767069868532d52631c46" + "commitHash": "6154ae25a24e01ac9329e7bcf958e093cd8733a9" } }, "license": "MIT", - "version": "0.7.5" + "version": "0.7.6" } ], "version": 1 diff --git a/extensions/bat/syntaxes/batchfile.tmLanguage.json b/extensions/bat/syntaxes/batchfile.tmLanguage.json index 9eff3c9de2b..85e03dbc85b 100644 --- a/extensions/bat/syntaxes/batchfile.tmLanguage.json +++ b/extensions/bat/syntaxes/batchfile.tmLanguage.json @@ -4,9 +4,18 @@ "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/mmims/language-batchfile/commit/95ea8c699f7a8296b15767069868532d52631c46", + "version": "https://github.com/mmims/language-batchfile/commit/6154ae25a24e01ac9329e7bcf958e093cd8733a9", "name": "Batch File", "scopeName": "source.batchfile", + "injections": { + "L:meta.block.repeat.batchfile": { + "patterns": [ + { + "include": "#repeatParameter" + } + ] + } + }, "patterns": [ { "include": "#commands" @@ -46,7 +55,7 @@ "commands": { "patterns": [ { - "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|scp|sc|schtasks|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|shadow|shift|showmount|shutdown|sort|ssh|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|mic|wscript|xcopy)(?=$|\\s)", + "match": "(?<=^|[\\s@])(?i:adprep|append|arp|assoc|at|atmadm|attrib|auditpol|autochk|autoconv|autofmt|bcdboot|bcdedit|bdehdcfg|bitsadmin|bootcfg|brea|cacls|cd|certreq|certutil|change|chcp|chdir|chglogon|chgport|chgusr|chkdsk|chkntfs|choice|cipher|clip|cls|clscluadmin|cluster|cmd|cmdkey|cmstp|color|comp|compact|convert|copy|cprofile|cscript|csvde|date|dcdiag|dcgpofix|dcpromo|defra|del|dfscmd|dfsdiag|dfsrmig|diantz|dir|dirquota|diskcomp|diskcopy|diskpart|diskperf|diskraid|diskshadow|dispdiag|doin|dnscmd|doskey|driverquery|dsacls|dsadd|dsamain|dsdbutil|dsget|dsmgmt|dsmod|dsmove|dsquery|dsrm|edit|endlocal|eraseesentutl|eventcreate|eventquery|eventtriggers|evntcmd|expand|extract|fc|filescrn|find|findstr|finger|flattemp|fonde|forfiles|format|freedisk|fsutil|ftp|ftype|fveupdate|getmac|gettype|gpfixup|gpresult|gpupdate|graftabl|hashgen|hep|helpctr|hostname|icacls|iisreset|inuse|ipconfig|ipxroute|irftp|ismserv|jetpack|klist|ksetup|ktmutil|ktpass|label|ldifd|ldp|lodctr|logman|logoff|lpq|lpr|macfile|makecab|manage-bde|mapadmin|md|mkdir|mklink|mmc|mode|more|mount|mountvol|move|mqbup|mqsvc|mqtgsvc|msdt|msg|msiexec|msinfo32|mstsc|nbtstat|net computer|net group|net localgroup|net print|net session|net share|net start|net stop|net use|net user|net view|net|netcfg|netdiag|netdom|netsh|netstat|nfsadmin|nfsshare|nfsstat|nlb|nlbmgr|nltest|nslookup|ntackup|ntcmdprompt|ntdsutil|ntfrsutl|openfiles|pagefileconfig|path|pathping|pause|pbadmin|pentnt|perfmon|ping|pnpunatten|pnputil|popd|powercfg|powershell|powershell_ise|print|prncnfg|prndrvr|prnjobs|prnmngr|prnport|prnqctl|prompt|pubprn|pushd|pushprinterconnections|pwlauncher|qappsrv|qprocess|query|quser|qwinsta|rasdial|rcp|rd|rdpsign|regentc|recover|redircmp|redirusr|reg|regini|regsvr32|relog|ren|rename|rendom|repadmin|repair-bde|replace|reset session|rxec|risetup|rmdir|robocopy|route|rpcinfo|rpcping|rsh|runas|rundll32|rwinsta|sc|schtasks|scp|scwcmd|secedit|serverceipoptin|servrmanagercmd|serverweroptin|setspn|setx|sfc|sftp|shadow|shift|showmount|shutdown|sort|ssh|ssh-add|ssh-agent|ssh-keygen|ssh-keyscan|start|storrept|subst|sxstrace|ysocmgr|systeminfo|takeown|tapicfg|taskkill|tasklist|tcmsetup|telnet|tftp|time|timeout|title|tlntadmn|tpmvscmgr|tpmvscmgr|tacerpt|tracert|tree|tscon|tsdiscon|tsecimp|tskill|tsprof|type|typeperf|tzutil|uddiconfig|umount|unlodctr|ver|verifier|verif|vol|vssadmin|w32tm|waitfor|wbadmin|wdsutil|wecutil|wevtutil|where|whoami|winnt|winnt32|winpop|winrm|winrs|winsat|wlbs|wmic|wscript|wsl|xcopy)(?=$|\\s)", "name": "keyword.command.batchfile" }, { @@ -285,7 +294,7 @@ "name": "keyword.operator.logical.batchfile" }, { - "match": "([^ ][^=]*)(=)", + "match": "([^ =]*)(=)", "captures": { "1": { "name": "variable.other.readwrite.batchfile" @@ -420,8 +429,38 @@ "name": "keyword.control.conditional.batchfile" }, { - "match": "(?<=^|\\s)(?i)for(?=\\s)", - "name": "keyword.control.repeat.batchfile" + "begin": "(?<=^|[\\s(&^])(?i)for(?=\\s)", + "beginCaptures": { + "0": { + "name": "keyword.control.repeat.batchfile" + } + }, + "name": "meta.block.repeat.batchfile", + "end": "\\n", + "patterns": [ + { + "begin": "(?<=[\\s^])(?i)in(?=\\s)", + "beginCaptures": { + "0": { + "name": "keyword.control.repeat.in.batchfile" + } + }, + "end": "(?<=[\\s)^])(?i)do(?=\\s)|\\n", + "endCaptures": { + "0": { + "name": "keyword.control.repeat.do.batchfile" + } + }, + "patterns": [ + { + "include": "$self" + } + ] + }, + { + "include": "$self" + } + ] } ] }, @@ -436,7 +475,7 @@ "labels": { "patterns": [ { - "match": "(?i)(?:^\\s*|(?<=goto)\\s*)(:)([^+=,;:\\s].*)$", + "match": "(?i)(?:^\\s*|(?<=call|goto)\\s*)(:)([^+=,;:\\s]\\S*)", "captures": { "1": { "name": "punctuation.separator.batchfile" @@ -512,6 +551,19 @@ } ] }, + "repeatParameter": { + "patterns": [ + { + "match": "(%%)(?:(?i:~[fdpnxsatz]*(?:\\$PATH:)?)?[a-zA-Z])", + "captures": { + "1": { + "name": "punctuation.definition.variable.batchfile" + } + }, + "name": "variable.parameter.repeat.batchfile" + } + ] + }, "strings": { "patterns": [ { @@ -546,15 +598,13 @@ "variables": { "patterns": [ { - "match": "(%)((~([fdpnxsatz]|\\$PATH:)*)?\\d|\\*)", + "match": "(%)(?:(?i:~[fdpnxsatz]*(?:\\$PATH:)?)?\\d|\\*)", "captures": { "1": { "name": "punctuation.definition.variable.batchfile" - }, - "2": { - "name": "variable.parameter.batchfile" } - } + }, + "name": "variable.parameter.batchfile" }, { "include": "#variable" diff --git a/extensions/configuration-editing/package.json b/extensions/configuration-editing/package.json index 324e0c80607..80e627e5f93 100644 --- a/extensions/configuration-editing/package.json +++ b/extensions/configuration-editing/package.json @@ -139,7 +139,7 @@ ] }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/configuration-editing/yarn.lock b/extensions/configuration-editing/yarn.lock index ebfaa046da4..d7215349a93 100644 --- a/extensions/configuration-editing/yarn.lock +++ b/extensions/configuration-editing/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== jsonc-parser@^2.2.1: version "2.2.1" diff --git a/extensions/css-language-features/package.json b/extensions/css-language-features/package.json index 7d80d751223..207041a6094 100644 --- a/extensions/css-language-features/package.json +++ b/extensions/css-language-features/package.json @@ -853,7 +853,7 @@ "vscode-uri": "^3.0.2" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/css-language-features/server/package.json b/extensions/css-language-features/server/package.json index ce3020c21a4..f7023548ad6 100644 --- a/extensions/css-language-features/server/package.json +++ b/extensions/css-language-features/server/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "scripts": { "compile": "gulp compile-extension:css-language-features-server", diff --git a/extensions/css-language-features/server/src/test/completion.test.ts b/extensions/css-language-features/server/src/test/completion.test.ts index 55eb64d9789..ec336448a50 100644 --- a/extensions/css-language-features/server/src/test/completion.test.ts +++ b/extensions/css-language-features/server/src/test/completion.test.ts @@ -24,10 +24,10 @@ suite('Completions', () => { return completion.label === expected.label; }); - assert.equal(matches.length, 1, `${expected.label} should only existing once: Actual: ${completions.items.map(c => c.label).join(', ')}`); + assert.strictEqual(matches.length, 1, `${expected.label} should only existing once: Actual: ${completions.items.map(c => c.label).join(', ')}`); let match = matches[0]; if (expected.resultText && TextEdit.is(match.textEdit)) { - assert.equal(TextDocument.applyEdits(document, [match.textEdit]), expected.resultText); + assert.strictEqual(TextDocument.applyEdits(document, [match.textEdit]), expected.resultText); } }; @@ -50,7 +50,7 @@ suite('Completions', () => { let list = await cssLanguageService.doComplete2(document, position, stylesheet, context); if (expected.count) { - assert.equal(list.items.length, expected.count); + assert.strictEqual(list.items.length, expected.count); } if (expected.items) { for (let item of expected.items) { diff --git a/extensions/css-language-features/server/src/test/links.test.ts b/extensions/css-language-features/server/src/test/links.test.ts index f67b5e92f25..bc4c6db6477 100644 --- a/extensions/css-language-features/server/src/test/links.test.ts +++ b/extensions/css-language-features/server/src/test/links.test.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import 'mocha'; import * as assert from 'assert'; -import { URI } from 'vscode-uri'; +import { URI } from 'vscode-uri'; import { resolve } from 'path'; import { TextDocument, DocumentLink } from 'vscode-languageserver-types'; import { WorkspaceFolder } from 'vscode-languageserver-protocol'; @@ -26,10 +26,10 @@ suite('Links', () => { return document.offsetAt(link.range.start) === expected.offset; }); - assert.equal(matches.length, 1, `${expected.offset} should only existing once: Actual: ${links.map(l => document.offsetAt(l.range.start)).join(', ')}`); + assert.strictEqual(matches.length, 1, `${expected.offset} should only existing once: Actual: ${links.map(l => document.offsetAt(l.range.start)).join(', ')}`); let match = matches[0]; - assert.equal(document.getText(match.range), expected.value); - assert.equal(match.target, expected.target); + assert.strictEqual(document.getText(match.range), expected.value); + assert.strictEqual(match.target, expected.target); }; async function assertLinks(value: string, expected: ItemDescription[], testUri: string, workspaceFolders?: WorkspaceFolder[], lang: string = 'css'): Promise { @@ -47,7 +47,7 @@ suite('Links', () => { const stylesheet = cssLanguageService.parseStylesheet(document); let links = await cssLanguageService.findDocumentLinks2(document, stylesheet, context)!; - assert.equal(links.length, expected.length); + assert.strictEqual(links.length, expected.length); for (let item of expected) { assertLink(links, item, document); diff --git a/extensions/css-language-features/server/yarn.lock b/extensions/css-language-features/server/yarn.lock index 3ff39d282f6..d4840eeb900 100644 --- a/extensions/css-language-features/server/yarn.lock +++ b/extensions/css-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-css-languageservice@^5.1.1: version "5.1.1" diff --git a/extensions/css-language-features/yarn.lock b/extensions/css-language-features/yarn.lock index eec3195c3f7..2e524319229 100644 --- a/extensions/css-language-features/yarn.lock +++ b/extensions/css-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== balanced-match@^1.0.0: version "1.0.0" diff --git a/extensions/debug-auto-launch/package.json b/extensions/debug-auto-launch/package.json index 8535f3f8b37..b0c765fa2cc 100644 --- a/extensions/debug-auto-launch/package.json +++ b/extensions/debug-auto-launch/package.json @@ -36,7 +36,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "prettier": { "printWidth": 100, diff --git a/extensions/debug-auto-launch/yarn.lock b/extensions/debug-auto-launch/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/debug-auto-launch/yarn.lock +++ b/extensions/debug-auto-launch/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/debug-server-ready/package.json b/extensions/debug-server-ready/package.json index 6b8a0be9ea5..7c85fef2cff 100644 --- a/extensions/debug-server-ready/package.json +++ b/extensions/debug-server-ready/package.json @@ -147,7 +147,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/debug-server-ready/yarn.lock b/extensions/debug-server-ready/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/debug-server-ready/yarn.lock +++ b/extensions/debug-server-ready/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/emmet/package.json b/extensions/emmet/package.json index fe82d0eed41..0af69221a29 100644 --- a/extensions/emmet/package.json +++ b/extensions/emmet/package.json @@ -444,7 +444,7 @@ "deps": "yarn add vscode-emmet-helper" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "dependencies": { "@emmetio/abbreviation": "^2.2.0", diff --git a/extensions/emmet/yarn.lock b/extensions/emmet/yarn.lock index 3578363bdc5..b9d9785a550 100644 --- a/extensions/emmet/yarn.lock +++ b/extensions/emmet/yarn.lock @@ -53,10 +53,10 @@ resolved "https://registry.yarnpkg.com/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz#46cffea119a0a003312a21c2d9b5628cb5fcd442" integrity sha1-Rs/+oRmgoAMxKiHC2bVijLX81EI= -"@types/node@^12.19.9": - version "12.20.7" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.7.tgz#1cb61fd0c85cb87e728c43107b5fd82b69bc9ef8" - integrity sha512-gWL8VUkg8VRaCAUgG9WmhefMqHmMblxe2rVpMF86nZY/+ZysU+BkAp+3cz03AixWDSSz0ks5WX59yAhv/cDwFA== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== emmet@^2.3.0: version "2.3.4" diff --git a/extensions/extension-editing/package.json b/extensions/extension-editing/package.json index d60c8420514..710f3d7be70 100644 --- a/extensions/extension-editing/package.json +++ b/extensions/extension-editing/package.json @@ -69,7 +69,7 @@ }, "devDependencies": { "@types/markdown-it": "0.0.2", - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/extension-editing/yarn.lock b/extensions/extension-editing/yarn.lock index 3275b1f2ad6..01c08624126 100644 --- a/extensions/extension-editing/yarn.lock +++ b/extensions/extension-editing/yarn.lock @@ -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@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/node@^6.0.46": version "6.0.78" diff --git a/extensions/git/package.json b/extensions/git/package.json index 7d5e81b2551..55f83ea6a89 100644 --- a/extensions/git/package.json +++ b/extensions/git/package.json @@ -2385,7 +2385,7 @@ "@types/byline": "4.2.31", "@types/file-type": "^5.2.1", "@types/mocha": "^8.2.0", - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/which": "^1.0.28" }, "repository": { diff --git a/extensions/git/src/test/git.test.ts b/extensions/git/src/test/git.test.ts index 4c74e26321b..c0d0d2003c9 100644 --- a/extensions/git/src/test/git.test.ts +++ b/extensions/git/src/test/git.test.ts @@ -12,19 +12,19 @@ suite('git', () => { suite('GitStatusParser', () => { test('empty parser', () => { const parser = new GitStatusParser(); - assert.deepEqual(parser.status, []); + assert.deepStrictEqual(parser.status, []); }); test('empty parser 2', () => { const parser = new GitStatusParser(); parser.update(''); - assert.deepEqual(parser.status, []); + assert.deepStrictEqual(parser.status, []); }); test('simple', () => { const parser = new GitStatusParser(); parser.update('?? file.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' } ]); }); @@ -34,7 +34,7 @@ suite('git', () => { parser.update('?? file.txt\0'); parser.update('?? file2.txt\0'); parser.update('?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -51,7 +51,7 @@ suite('git', () => { parser.update(''); parser.update('?? file3.txt\0'); parser.update(''); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -61,7 +61,7 @@ suite('git', () => { test('combined', () => { const parser = new GitStatusParser(); parser.update('?? file.txt\0?? file2.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -72,7 +72,7 @@ suite('git', () => { const parser = new GitStatusParser(); parser.update('?? file.txt\0?? file2'); parser.update('.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -83,7 +83,7 @@ suite('git', () => { const parser = new GitStatusParser(); parser.update('?? file.txt'); parser.update('\0?? file2.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -94,7 +94,7 @@ suite('git', () => { const parser = new GitStatusParser(); parser.update('?? file.txt\0?? file2.txt\0?? file3.txt'); parser.update('\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: undefined, x: '?', y: '?' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -104,7 +104,7 @@ suite('git', () => { test('rename', () => { const parser = new GitStatusParser(); parser.update('R newfile.txt\0file.txt\0?? file2.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: 'newfile.txt', x: 'R', y: ' ' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -115,7 +115,7 @@ suite('git', () => { const parser = new GitStatusParser(); parser.update('R newfile.txt\0fil'); parser.update('e.txt\0?? file2.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file.txt', rename: 'newfile.txt', x: 'R', y: ' ' }, { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -127,7 +127,7 @@ suite('git', () => { parser.update('?? file2.txt\0R new'); parser.update('file.txt\0fil'); parser.update('e.txt\0?? file3.txt\0'); - assert.deepEqual(parser.status, [ + assert.deepStrictEqual(parser.status, [ { path: 'file2.txt', rename: undefined, x: '?', y: '?' }, { path: 'file.txt', rename: 'newfile.txt', x: 'R', y: ' ' }, { path: 'file3.txt', rename: undefined, x: '?', y: '?' } @@ -137,7 +137,7 @@ suite('git', () => { suite('parseGitmodules', () => { test('empty', () => { - assert.deepEqual(parseGitmodules(''), []); + assert.deepStrictEqual(parseGitmodules(''), []); }); test('sample', () => { @@ -146,7 +146,7 @@ suite('git', () => { url = https://github.com/gabime/spdlog.git `; - assert.deepEqual(parseGitmodules(sample), [ + assert.deepStrictEqual(parseGitmodules(sample), [ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' } ]); }); @@ -166,7 +166,7 @@ suite('git', () => { url = https://github.com/gabime/spdlog4.git `; - assert.deepEqual(parseGitmodules(sample), [ + assert.deepStrictEqual(parseGitmodules(sample), [ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' }, { name: 'deps/spdlog2', path: 'deps/spdlog2', url: 'https://github.com/gabime/spdlog.git' }, { name: 'deps/spdlog3', path: 'deps/spdlog3', url: 'https://github.com/gabime/spdlog.git' }, @@ -180,7 +180,7 @@ suite('git', () => { url = https://github.com/gabime/spdlog.git `; - assert.deepEqual(parseGitmodules(sample), [ + assert.deepStrictEqual(parseGitmodules(sample), [ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' } ]); }); @@ -191,7 +191,7 @@ suite('git', () => { url=https://github.com/gabime/spdlog.git `; - assert.deepEqual(parseGitmodules(sample), [ + assert.deepStrictEqual(parseGitmodules(sample), [ { name: 'deps/spdlog', path: 'deps/spdlog', url: 'https://github.com/gabime/spdlog.git' } ]); }); @@ -207,7 +207,7 @@ john.doe@mail.com 8e5a374372b8393906c7e380dbb09349c5385554 This is a commit message.\x00`; - assert.deepEqual(parseGitCommits(GIT_OUTPUT_SINGLE_PARENT), [{ + assert.deepStrictEqual(parseGitCommits(GIT_OUTPUT_SINGLE_PARENT), [{ hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', parents: ['8e5a374372b8393906c7e380dbb09349c5385554'], @@ -227,7 +227,7 @@ john.doe@mail.com 8e5a374372b8393906c7e380dbb09349c5385554 df27d8c75b129ab9b178b386077da2822101b217 This is a commit message.\x00`; - assert.deepEqual(parseGitCommits(GIT_OUTPUT_MULTIPLE_PARENTS), [{ + assert.deepStrictEqual(parseGitCommits(GIT_OUTPUT_MULTIPLE_PARENTS), [{ hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', parents: ['8e5a374372b8393906c7e380dbb09349c5385554', 'df27d8c75b129ab9b178b386077da2822101b217'], @@ -247,7 +247,7 @@ john.doe@mail.com This is a commit message.\x00`; - assert.deepEqual(parseGitCommits(GIT_OUTPUT_NO_PARENTS), [{ + assert.deepStrictEqual(parseGitCommits(GIT_OUTPUT_NO_PARENTS), [{ hash: '52c293a05038d865604c2284aa8698bd087915a1', message: 'This is a commit message.', parents: [], @@ -275,7 +275,7 @@ This is a commit message.\x00`; const output = parseLsTree(input); - assert.deepEqual(output, [ + assert.deepStrictEqual(output, [ { mode: '040000', type: 'tree', object: '0274a81f8ee9ca3669295dc40f510bd2021d0043', size: '-', file: '.vscode' }, { mode: '100644', type: 'blob', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', size: '491570', file: 'Screen Shot 2018-06-01 at 14.48.05.png' }, { mode: '100644', type: 'blob', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', size: '764420', file: 'Screen Shot 2018-06-07 at 20.04.59.png' }, @@ -307,7 +307,7 @@ This is a commit message.\x00`; const output = parseLsFiles(input); - assert.deepEqual(output, [ + assert.deepStrictEqual(output, [ { mode: '100644', object: '7a73a41bfdf76d6f793007240d80983a52f15f97', stage: '0', file: '.vscode/settings.json' }, { mode: '100644', object: '1d487c1817262e4f20efbfa1d04c18f51b0046f6', stage: '0', file: 'Screen Shot 2018-06-01 at 14.48.05.png' }, { mode: '100644', object: '686c16e4f019b734655a2576ce8b98749a9ffdb9', stage: '0', file: 'Screen Shot 2018-06-07 at 20.04.59.png' }, @@ -325,72 +325,72 @@ This is a commit message.\x00`; suite('splitInChunks', () => { test('unit tests', function () { - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 6)], [['hello'], ['there'], ['cool'], ['stuff']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 10)], [['hello', 'there'], ['cool', 'stuff']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 12)], [['hello', 'there'], ['cool', 'stuff']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 14)], [['hello', 'there', 'cool'], ['stuff']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['hello', 'there', 'cool', 'stuff'], 2000)], [['hello', 'there', 'cool', 'stuff']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 1)], [['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 2)], [['0'], ['01'], ['012'], ['0'], ['01'], ['012'], ['0'], ['01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 3)], [['0', '01'], ['012'], ['0', '01'], ['012'], ['0', '01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 4)], [['0', '01'], ['012', '0'], ['01'], ['012', '0'], ['01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 5)], [['0', '01'], ['012', '0'], ['01', '012'], ['0', '01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 6)], [['0', '01', '012'], ['0', '01', '012'], ['0', '01', '012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 7)], [['0', '01', '012', '0'], ['01', '012', '0'], ['01', '012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 8)], [['0', '01', '012', '0'], ['01', '012', '0', '01'], ['012']] ); - assert.deepEqual( + assert.deepStrictEqual( [...splitInChunks(['0', '01', '012', '0', '01', '012', '0', '01', '012'], 9)], [['0', '01', '012', '0', '01'], ['012', '0', '01', '012']] ); diff --git a/extensions/git/src/test/smoke.test.ts b/extensions/git/src/test/smoke.test.ts index ed6a5d504a6..2ba3da99aa6 100644 --- a/extensions/git/src/test/smoke.test.ts +++ b/extensions/git/src/test/smoke.test.ts @@ -59,8 +59,8 @@ suite('git smoke test', function () { await eventToPromise(git.onDidOpenRepository); } - assert.equal(git.repositories.length, 1); - assert.equal(fs.realpathSync(git.repositories[0].rootUri.fsPath), cwd); + assert.strictEqual(git.repositories.length, 1); + assert.strictEqual(fs.realpathSync(git.repositories[0].rootUri.fsPath), cwd); repository = git.repositories[0]; }); @@ -72,7 +72,7 @@ suite('git smoke test', function () { await type(appjs, ' world'); await appjs.save(); await repository.status(); - assert.equal(repository.state.workingTreeChanges.length, 1); + assert.strictEqual(repository.state.workingTreeChanges.length, 1); repository.state.workingTreeChanges.some(r => r.uri.path === appjs.uri.path && r.status === Status.MODIFIED); fs.writeFileSync(file('newfile.txt'), ''); @@ -80,7 +80,7 @@ suite('git smoke test', function () { await type(newfile, 'hey there'); await newfile.save(); await repository.status(); - assert.equal(repository.state.workingTreeChanges.length, 2); + assert.strictEqual(repository.state.workingTreeChanges.length, 2); repository.state.workingTreeChanges.some(r => r.uri.path === appjs.uri.path && r.status === Status.MODIFIED); repository.state.workingTreeChanges.some(r => r.uri.path === newfile.uri.path && r.status === Status.UNTRACKED); }); @@ -90,7 +90,7 @@ suite('git smoke test', function () { await commands.executeCommand('git.openChange', appjs); assert(window.activeTextEditor); - assert.equal(window.activeTextEditor!.document.uri.path, appjs.path); + assert.strictEqual(window.activeTextEditor!.document.uri.path, appjs.path); // TODO: how do we really know this is a diff editor? }); @@ -100,13 +100,13 @@ suite('git smoke test', function () { const newfile = uri('newfile.txt'); await commands.executeCommand('git.stage', appjs); - assert.equal(repository.state.workingTreeChanges.length, 1); + assert.strictEqual(repository.state.workingTreeChanges.length, 1); repository.state.workingTreeChanges.some(r => r.uri.path === newfile.path && r.status === Status.UNTRACKED); - assert.equal(repository.state.indexChanges.length, 1); + assert.strictEqual(repository.state.indexChanges.length, 1); repository.state.indexChanges.some(r => r.uri.path === appjs.path && r.status === Status.INDEX_MODIFIED); await commands.executeCommand('git.unstage', appjs); - assert.equal(repository.state.workingTreeChanges.length, 2); + assert.strictEqual(repository.state.workingTreeChanges.length, 2); repository.state.workingTreeChanges.some(r => r.uri.path === appjs.path && r.status === Status.MODIFIED); repository.state.workingTreeChanges.some(r => r.uri.path === newfile.path && r.status === Status.UNTRACKED); }); @@ -117,14 +117,14 @@ suite('git smoke test', function () { await commands.executeCommand('git.stage', appjs); await repository.commit('second commit'); - assert.equal(repository.state.workingTreeChanges.length, 1); + assert.strictEqual(repository.state.workingTreeChanges.length, 1); repository.state.workingTreeChanges.some(r => r.uri.path === newfile.path && r.status === Status.UNTRACKED); - assert.equal(repository.state.indexChanges.length, 0); + assert.strictEqual(repository.state.indexChanges.length, 0); await commands.executeCommand('git.stageAll', appjs); await repository.commit('third commit'); - assert.equal(repository.state.workingTreeChanges.length, 0); - assert.equal(repository.state.indexChanges.length, 0); + assert.strictEqual(repository.state.workingTreeChanges.length, 0); + assert.strictEqual(repository.state.indexChanges.length, 0); }); test('rename/delete conflict', async function () { diff --git a/extensions/git/yarn.lock b/extensions/git/yarn.lock index c964f284a3a..3853a2d2c04 100644 --- a/extensions/git/yarn.lock +++ b/extensions/git/yarn.lock @@ -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@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/which@^1.0.28": version "1.0.28" diff --git a/extensions/github-authentication/package.json b/extensions/github-authentication/package.json index 4a18a5bd0a8..a37a55e8a1f 100644 --- a/extensions/github-authentication/package.json +++ b/extensions/github-authentication/package.json @@ -67,7 +67,7 @@ "vscode-tas-client": "^0.1.22" }, "devDependencies": { - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/node-fetch": "^2.5.7", "@types/uuid": "8.0.0" }, diff --git a/extensions/github-authentication/yarn.lock b/extensions/github-authentication/yarn.lock index 8095e574523..090dc94dcb7 100644 --- a/extensions/github-authentication/yarn.lock +++ b/extensions/github-authentication/yarn.lock @@ -15,10 +15,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.5.tgz#3d03acd3b3414cf67faf999aed11682ed121f22b" integrity sha512-90hiq6/VqtQgX8Sp0EzeIsv3r+ellbGj4URKj5j30tLlZvRUpnAe9YbYnjl3pJM93GyXU0tghHhvXHq+5rnCKA== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/uuid@8.0.0": version "8.0.0" diff --git a/extensions/github/package.json b/extensions/github/package.json index 8f67314b459..f21080ab6f1 100644 --- a/extensions/github/package.json +++ b/extensions/github/package.json @@ -70,7 +70,7 @@ "vscode-nls": "^4.1.2" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/github/yarn.lock b/extensions/github/yarn.lock index 05a0b4cf6f9..94f7a26da9d 100644 --- a/extensions/github/yarn.lock +++ b/extensions/github/yarn.lock @@ -99,16 +99,16 @@ dependencies: "@types/node" ">= 8" +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== + "@types/node@>= 8": version "14.0.23" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== - before-after-hook@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" diff --git a/extensions/grunt/package.json b/extensions/grunt/package.json index d7fbd50e57a..c966fbe1c8d 100644 --- a/extensions/grunt/package.json +++ b/extensions/grunt/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/grunt/yarn.lock b/extensions/grunt/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/grunt/yarn.lock +++ b/extensions/grunt/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/gulp/package.json b/extensions/gulp/package.json index 2fb8d583123..7cbf852116b 100644 --- a/extensions/gulp/package.json +++ b/extensions/gulp/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/gulp/yarn.lock b/extensions/gulp/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/gulp/yarn.lock +++ b/extensions/gulp/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index 9fa6bc314e5..3c6a539c079 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -245,7 +245,7 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/html-language-features/server/package.json b/extensions/html-language-features/server/package.json index fdb29285313..12c541668d9 100644 --- a/extensions/html-language-features/server/package.json +++ b/extensions/html-language-features/server/package.json @@ -18,7 +18,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "scripts": { "compile": "npx gulp compile-extension:html-language-features-server", diff --git a/extensions/html-language-features/server/src/test/completions.test.ts b/extensions/html-language-features/server/src/test/completions.test.ts index 0371a2f74cd..aaf3cb5ec6b 100644 --- a/extensions/html-language-features/server/src/test/completions.test.ts +++ b/extensions/html-language-features/server/src/test/completions.test.ts @@ -23,24 +23,24 @@ export function assertCompletion(completions: CompletionList, expected: ItemDesc return completion.label === expected.label; }); if (expected.notAvailable) { - assert.equal(matches.length, 0, `${expected.label} should not existing is results`); + assert.strictEqual(matches.length, 0, `${expected.label} should not existing is results`); return; } - assert.equal(matches.length, 1, `${expected.label} should only existing once: Actual: ${completions.items.map(c => c.label).join(', ')}`); + assert.strictEqual(matches.length, 1, `${expected.label} should only existing once: Actual: ${completions.items.map(c => c.label).join(', ')}`); let match = matches[0]; if (expected.documentation) { - assert.equal(match.documentation, expected.documentation); + assert.strictEqual(match.documentation, expected.documentation); } if (expected.kind) { - assert.equal(match.kind, expected.kind); + assert.strictEqual(match.kind, expected.kind); } if (expected.resultText && match.textEdit) { const edit = TextEdit.is(match.textEdit) ? match.textEdit : TextEdit.replace(match.textEdit.replace, match.textEdit.newText); - assert.equal(TextDocument.applyEdits(document, [edit]), expected.resultText); + assert.strictEqual(TextDocument.applyEdits(document, [edit]), expected.resultText); } if (expected.command) { - assert.deepEqual(match.command, expected.command); + assert.deepStrictEqual(match.command, expected.command); } } @@ -65,7 +65,7 @@ export async function testCompletionFor(value: string, expected: { count?: numbe let list = await mode.doComplete!(document, position, context); if (expected.count) { - assert.equal(list.items.length, expected.count); + assert.strictEqual(list.items.length, expected.count); } if (expected.items) { for (let item of expected.items) { diff --git a/extensions/html-language-features/server/src/test/documentContext.test.ts b/extensions/html-language-features/server/src/test/documentContext.test.ts index 612c0063c05..29ba6880972 100644 --- a/extensions/html-language-features/server/src/test/documentContext.test.ts +++ b/extensions/html-language-features/server/src/test/documentContext.test.ts @@ -12,9 +12,9 @@ suite('HTML Document Context', () => { const rootFolders = [{ name: '', uri: 'file:///users/test/' }]; let context = getDocumentContext(docURI, rootFolders); - assert.equal(context.resolveReference('/', docURI), 'file:///users/test/'); - assert.equal(context.resolveReference('/message.html', docURI), 'file:///users/test/message.html'); - assert.equal(context.resolveReference('message.html', docURI), 'file:///users/test/folder/message.html'); - assert.equal(context.resolveReference('message.html', 'file:///users/test/'), 'file:///users/test/message.html'); + assert.strictEqual(context.resolveReference('/', docURI), 'file:///users/test/'); + assert.strictEqual(context.resolveReference('/message.html', docURI), 'file:///users/test/message.html'); + assert.strictEqual(context.resolveReference('message.html', docURI), 'file:///users/test/folder/message.html'); + assert.strictEqual(context.resolveReference('message.html', 'file:///users/test/'), 'file:///users/test/message.html'); }); -}); \ No newline at end of file +}); diff --git a/extensions/html-language-features/server/src/test/embedded.test.ts b/extensions/html-language-features/server/src/test/embedded.test.ts index 525d5a59c11..005ecf0864c 100644 --- a/extensions/html-language-features/server/src/test/embedded.test.ts +++ b/extensions/html-language-features/server/src/test/embedded.test.ts @@ -23,7 +23,7 @@ suite('HTML Embedded Support', () => { const docRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document); const languageId = docRegions.getLanguageAtPosition(position); - assert.equal(languageId, expectedLanguageId); + assert.strictEqual(languageId, expectedLanguageId); } function assertEmbeddedLanguageContent(value: string, languageId: string, expectedContent: string): void { @@ -31,7 +31,7 @@ suite('HTML Embedded Support', () => { const docRegions = embeddedSupport.getDocumentRegions(htmlLanguageService, document); const content = docRegions.getEmbeddedDocument(languageId); - assert.equal(content.getText(), expectedContent); + assert.strictEqual(content.getText(), expectedContent); } test('Styles', function (): any { diff --git a/extensions/html-language-features/server/src/test/folding.test.ts b/extensions/html-language-features/server/src/test/folding.test.ts index 693a74420f0..7bf90bb10d5 100644 --- a/extensions/html-language-features/server/src/test/folding.test.ts +++ b/extensions/html-language-features/server/src/test/folding.test.ts @@ -30,7 +30,7 @@ async function assertRanges(lines: string[], expected: ExpectedIndentRange[], me actualRanges[i] = r(actual[i].startLine, actual[i].endLine, actual[i].kind); } actualRanges = actualRanges.sort((r1, r2) => r1.startLine - r2.startLine); - assert.deepEqual(actualRanges, expected, message); + assert.deepStrictEqual(actualRanges, expected, message); } function r(startLine: number, endLine: number, kind?: string): ExpectedIndentRange { diff --git a/extensions/html-language-features/server/src/test/formatting.test.ts b/extensions/html-language-features/server/src/test/formatting.test.ts index d7c922c736a..107001c7c00 100644 --- a/extensions/html-language-features/server/src/test/formatting.test.ts +++ b/extensions/html-language-features/server/src/test/formatting.test.ts @@ -41,7 +41,7 @@ suite('HTML Embedded Formatting', () => { let result = await format(languageModes, document, range, formatOptions, undefined, { css: true, javascript: true }); let actual = TextDocument.applyEdits(document, result); - assert.equal(actual, expected, message); + assert.strictEqual(actual, expected, message); } async function assertFormatWithFixture(fixtureName: string, expectedPath: string, options?: any, formatOptions?: FormattingOptions): Promise { diff --git a/extensions/html-language-features/server/src/test/rename.test.ts b/extensions/html-language-features/server/src/test/rename.test.ts index 2705b56fdf8..edebe68d7b2 100644 --- a/extensions/html-language-features/server/src/test/rename.test.ts +++ b/extensions/html-language-features/server/src/test/rename.test.ts @@ -34,7 +34,7 @@ async function testRename(value: string, newName: string, expectedDocContent: st } const newDocContent = TextDocument.applyEdits(document, edits); - assert.equal(newDocContent, expectedDocContent, `Expected: ${expectedDocContent}\nActual: ${newDocContent}`); + assert.strictEqual(newDocContent, expectedDocContent, `Expected: ${expectedDocContent}\nActual: ${newDocContent}`); } else { assert.fail('should have javascriptMode but no') } diff --git a/extensions/html-language-features/server/src/test/selectionRanges.test.ts b/extensions/html-language-features/server/src/test/selectionRanges.test.ts index 9f9937bcaf7..c5166c7bb45 100644 --- a/extensions/html-language-features/server/src/test/selectionRanges.test.ts +++ b/extensions/html-language-features/server/src/test/selectionRanges.test.ts @@ -5,7 +5,7 @@ import 'mocha'; import * as assert from 'assert'; -import { getLanguageModes, ClientCapabilities, TextDocument, SelectionRange} from '../modes/languageModes'; +import { getLanguageModes, ClientCapabilities, TextDocument, SelectionRange } from '../modes/languageModes'; import { getSelectionRanges } from '../modes/selectionRanges'; import { getNodeFSRequestService } from '../node/nodeFs'; @@ -23,7 +23,7 @@ async function assertRanges(content: string, expected: (number | string)[][]): P const document = TextDocument.create('test://foo.html', 'html', 1, content); const actualRanges = await getSelectionRanges(languageModes, document, [document.positionAt(offset)]); - assert.equal(actualRanges.length, 1); + assert.strictEqual(actualRanges.length, 1); const offsetPairs: [number, string][] = []; let curr: SelectionRange | undefined = actualRanges[0]; while (curr) { @@ -32,7 +32,7 @@ async function assertRanges(content: string, expected: (number | string)[][]): P } message += `${JSON.stringify(offsetPairs)}\n but should give:\n${JSON.stringify(expected)}\n`; - assert.deepEqual(offsetPairs, expected, message); + assert.deepStrictEqual(offsetPairs, expected, message); } suite('HTML SelectionRange', () => { diff --git a/extensions/html-language-features/server/src/test/semanticTokens.test.ts b/extensions/html-language-features/server/src/test/semanticTokens.test.ts index 548ce7d8458..3cf242df18f 100644 --- a/extensions/html-language-features/server/src/test/semanticTokens.test.ts +++ b/extensions/html-language-features/server/src/test/semanticTokens.test.ts @@ -40,7 +40,7 @@ async function assertTokens(lines: string[], expected: ExpectedToken[], ranges?: lastLine = line; lastCharacter = character; } - assert.deepEqual(actualRanges, expected, message); + assert.deepStrictEqual(actualRanges, expected, message); } function t(startLine: number, character: number, length: number, tokenClassifiction: string): ExpectedToken { diff --git a/extensions/html-language-features/server/src/test/words.test.ts b/extensions/html-language-features/server/src/test/words.test.ts index e094bfb4251..f86ae969c66 100644 --- a/extensions/html-language-features/server/src/test/words.test.ts +++ b/extensions/html-language-features/server/src/test/words.test.ts @@ -16,7 +16,7 @@ suite('HTML Words', () => { let actualRange = words.getWordAtText(value, offset, wordRegex); assert(actualRange.start <= offset); assert(actualRange.start + actualRange.length >= offset); - assert.equal(value.substr(actualRange.start, actualRange.length), expected); + assert.strictEqual(value.substr(actualRange.start, actualRange.length), expected); } @@ -41,4 +41,4 @@ suite('HTML Words', () => { assertWord('console.log("hello");\n\r |var x1 = new F(a, b);', 'var'); }); -}); \ No newline at end of file +}); diff --git a/extensions/html-language-features/server/yarn.lock b/extensions/html-language-features/server/yarn.lock index ca035d1c79b..28929c57d81 100644 --- a/extensions/html-language-features/server/yarn.lock +++ b/extensions/html-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-css-languageservice@^5.1.1: version "5.1.1" diff --git a/extensions/html-language-features/yarn.lock b/extensions/html-language-features/yarn.lock index f538d16e7d4..d14954d241f 100644 --- a/extensions/html-language-features/yarn.lock +++ b/extensions/html-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== applicationinsights@1.7.4: version "1.7.4" diff --git a/extensions/jake/package.json b/extensions/jake/package.json index ce19974e105..0c3edeeed66 100644 --- a/extensions/jake/package.json +++ b/extensions/jake/package.json @@ -20,7 +20,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "main": "./out/main", "activationEvents": [ diff --git a/extensions/jake/yarn.lock b/extensions/jake/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/jake/yarn.lock +++ b/extensions/jake/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/json-language-features/package.json b/extensions/json-language-features/package.json index e854c07569a..4b832e4ebb6 100644 --- a/extensions/json-language-features/package.json +++ b/extensions/json-language-features/package.json @@ -140,7 +140,7 @@ "vscode-nls": "^5.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/json-language-features/server/package.json b/extensions/json-language-features/server/package.json index e1051c4ee81..9d734c1a2ba 100644 --- a/extensions/json-language-features/server/package.json +++ b/extensions/json-language-features/server/package.json @@ -14,13 +14,13 @@ "dependencies": { "jsonc-parser": "^3.0.0", "request-light": "^0.4.0", - "vscode-json-languageservice": "^4.1.2", + "vscode-json-languageservice": "^4.1.3", "vscode-languageserver": "^7.0.0", "vscode-uri": "^3.0.2" }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "scripts": { "prepublishOnly": "npm run clean && npm run compile", diff --git a/extensions/json-language-features/server/yarn.lock b/extensions/json-language-features/server/yarn.lock index 5c6a160f8c3..c8ec27e9d1d 100644 --- a/extensions/json-language-features/server/yarn.lock +++ b/extensions/json-language-features/server/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== agent-base@4: version "4.1.2" @@ -105,10 +105,10 @@ request-light@^0.4.0: https-proxy-agent "^2.2.4" vscode-nls "^4.1.2" -vscode-json-languageservice@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.2.tgz#c3873f791e23488a8b373e02c85c232bd625e27a" - integrity sha512-atAz6m4UZCslB7yk03Qb3/MKn1E5l07063syAEUfKRcVKTVN3t1+/KDlGu1nVCRUFAgz5+18gKidQvO4PVPLdg== +vscode-json-languageservice@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/vscode-json-languageservice/-/vscode-json-languageservice-4.1.3.tgz#851564e529e649c13b844f10a80ea1d9095591a9" + integrity sha512-m/wUEt4zgCNUcvGmPr1ELo+ROQNKBgASpdOOAEpcSMwYE/6GzULZ1KfBhbX9or7qnC4E0oX+wwW+lrN3EUWCgw== dependencies: jsonc-parser "^3.0.0" minimatch "^3.0.4" diff --git a/extensions/json-language-features/yarn.lock b/extensions/json-language-features/yarn.lock index a4533a6e53c..4ba9b7b6301 100644 --- a/extensions/json-language-features/yarn.lock +++ b/extensions/json-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== agent-base@4: version "4.2.1" diff --git a/extensions/markdown-language-features/package.json b/extensions/markdown-language-features/package.json index 19d1354c206..b9184c3c3dd 100644 --- a/extensions/markdown-language-features/package.json +++ b/extensions/markdown-language-features/package.json @@ -361,7 +361,7 @@ "@types/highlight.js": "10.1.0", "@types/lodash.throttle": "^4.1.3", "@types/markdown-it": "0.0.2", - "@types/node": "^12.19.9", + "@types/node": "14.x", "lodash.throttle": "^4.1.1" }, "repository": { diff --git a/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts b/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts index e74d3b592bc..d66cbf198b2 100644 --- a/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts +++ b/extensions/markdown-language-features/src/test/workspaceSymbolProvider.test.ts @@ -18,7 +18,7 @@ suite('markdown.WorkspaceSymbolProvider', () => { test('Should not return anything for empty workspace', async () => { const provider = new MarkdownWorkspaceSymbolProvider(symbolProvider, new InMemoryWorkspaceMarkdownDocumentProvider([])); - assert.deepEqual(await provider.provideWorkspaceSymbols(''), []); + assert.deepStrictEqual(await provider.provideWorkspaceSymbols(''), []); }); test('Should return symbols from workspace with one markdown file', async () => { diff --git a/extensions/markdown-language-features/yarn.lock b/extensions/markdown-language-features/yarn.lock index 216abe3066b..19a53c4a2bc 100644 --- a/extensions/markdown-language-features/yarn.lock +++ b/extensions/markdown-language-features/yarn.lock @@ -26,10 +26,10 @@ resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.2.tgz#5d9ad19e6e6508cdd2f2596df86fd0aade598660" integrity sha1-XZrRnm5lCM3S8llt+G/Qqt5ZhmA= -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== applicationinsights@1.7.4: version "1.7.4" diff --git a/extensions/merge-conflict/package.json b/extensions/merge-conflict/package.json index 74f7b848fa8..2c4719f4b71 100644 --- a/extensions/merge-conflict/package.json +++ b/extensions/merge-conflict/package.json @@ -159,7 +159,7 @@ "vscode-nls": "^4.0.0" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/merge-conflict/yarn.lock b/extensions/merge-conflict/yarn.lock index 687f15f481e..f7a30098ef4 100644 --- a/extensions/merge-conflict/yarn.lock +++ b/extensions/merge-conflict/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== vscode-nls@^4.0.0: version "4.0.0" diff --git a/extensions/microsoft-authentication/package.json b/extensions/microsoft-authentication/package.json index 7b47354df0f..148b5c3625c 100644 --- a/extensions/microsoft-authentication/package.json +++ b/extensions/microsoft-authentication/package.json @@ -46,7 +46,7 @@ "watch-web": "npx webpack-cli --config extension-browser.webpack.config --mode none --watch --info-verbosity verbose" }, "devDependencies": { - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/node-fetch": "^2.5.7", "@types/randombytes": "^2.0.0", "@types/sha.js": "^2.4.0", diff --git a/extensions/microsoft-authentication/yarn.lock b/extensions/microsoft-authentication/yarn.lock index fada1d6e8bf..54025e55a21 100644 --- a/extensions/microsoft-authentication/yarn.lock +++ b/extensions/microsoft-authentication/yarn.lock @@ -15,10 +15,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/randombytes@^2.0.0": version "2.0.0" diff --git a/extensions/npm/package.json b/extensions/npm/package.json index ab75bdf34eb..038f091b78e 100644 --- a/extensions/npm/package.json +++ b/extensions/npm/package.json @@ -29,7 +29,7 @@ }, "devDependencies": { "@types/minimatch": "^3.0.3", - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/which": "^2.0.0" }, "resolutions": { diff --git a/extensions/npm/yarn.lock b/extensions/npm/yarn.lock index 6b653dec9d9..29712f0dcc0 100644 --- a/extensions/npm/yarn.lock +++ b/extensions/npm/yarn.lock @@ -7,10 +7,10 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/which@^2.0.0": version "2.0.0" diff --git a/extensions/php-language-features/package.json b/extensions/php-language-features/package.json index 3763949d647..79ae4095476 100644 --- a/extensions/php-language-features/package.json +++ b/extensions/php-language-features/package.json @@ -94,7 +94,7 @@ "which": "^2.0.2" }, "devDependencies": { - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/which": "^2.0.0" }, "repository": { diff --git a/extensions/php-language-features/src/features/validationProvider.ts b/extensions/php-language-features/src/features/validationProvider.ts index acc6beaf2b5..162efdaa787 100644 --- a/extensions/php-language-features/src/features/validationProvider.ts +++ b/extensions/php-language-features/src/features/validationProvider.ts @@ -23,7 +23,7 @@ export class LineDecoder { private stringDecoder: StringDecoder; private remaining: string | null; - constructor(encoding: string = 'utf8') { + constructor(encoding: BufferEncoding = 'utf8') { this.stringDecoder = new StringDecoder(encoding); this.remaining = null; } diff --git a/extensions/php-language-features/yarn.lock b/extensions/php-language-features/yarn.lock index b0fa5625a6d..09b31c80123 100644 --- a/extensions/php-language-features/yarn.lock +++ b/extensions/php-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/which@^2.0.0": version "2.0.0" diff --git a/extensions/php/cgmanifest.json b/extensions/php/cgmanifest.json index 15b73aeaf6c..e9abbe63e63 100644 --- a/extensions/php/cgmanifest.json +++ b/extensions/php/cgmanifest.json @@ -6,11 +6,11 @@ "git": { "name": "language-php", "repositoryUrl": "https://github.com/atom/language-php", - "commitHash": "72739e6341b1b4bf4aa185e928932983baca449e" + "commitHash": "2bf736a814e1a58aa63470c1a29590bd02e924e7" } }, "license": "MIT", - "version": "0.46.0" + "version": "0.46.2" } ], "version": 1 diff --git a/extensions/php/language-configuration.json b/extensions/php/language-configuration.json index 9c24c7b724b..b785c0092ab 100644 --- a/extensions/php/language-configuration.json +++ b/extensions/php/language-configuration.json @@ -26,7 +26,7 @@ ], "indentationRules": { "increaseIndentPattern": "({(?!.*}).*|\\(|\\[|((else(\\s)?)?if|else|for(each)?|while|switch|case).*:)\\s*((/[/*].*|)?$|\\?>)", - "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\][;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" + "decreaseIndentPattern": "^(.*\\*\\/)?\\s*((\\})|(\\)+[;,])|(\\]\\)*[;,])|\\b(else:)|\\b((end(if|for(each)?|while|switch));))" }, "folding": { "markers": { diff --git a/extensions/php/syntaxes/html.tmLanguage.json b/extensions/php/syntaxes/html.tmLanguage.json index 4bf15294159..a8dff09d0a0 100644 --- a/extensions/php/syntaxes/html.tmLanguage.json +++ b/extensions/php/syntaxes/html.tmLanguage.json @@ -4,111 +4,10 @@ "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/atom/language-php/commit/b6c5e83016b52311cdc622c2579462861ee91587", + "version": "https://github.com/atom/language-php/commit/2bf736a814e1a58aa63470c1a29590bd02e924e7", "name": "PHP", "scopeName": "text.html.php", "injections": { - "L:source.php string.quoted.single.sql.php source.sql.embedded.php": { - "patterns": [ - { - "match": "(#)(\\\\'|[^'])*(?='|$)", - "name": "comment.line.number-sign.sql", - "captures": { - "1": { - "name": "punctuation.definition.comment.sql" - } - } - }, - { - "match": "(--)(\\\\'|[^'])*(?='|$)", - "name": "comment.line.double-dash.sql", - "captures": { - "1": { - "name": "punctuation.definition.comment.sql" - } - } - }, - { - "match": "\\\\[\\\\'`\"]", - "name": "constant.character.escape.php" - }, - { - "match": "\"(?=((\\\\\")|[^\"'])*('|$))", - "name": "string.quoted.double.unclosed.sql" - } - ] - }, - "L:source.php string.quoted.double.sql.php source.sql.embedded.php": { - "patterns": [ - { - "match": "(#)(\\\\\"|[^\"])*(?=\"|$)", - "name": "comment.line.number-sign.sql", - "captures": { - "1": { - "name": "punctuation.definition.comment.sql" - } - } - }, - { - "match": "(--)(\\\\\"|[^\"])*(?=\"|$)", - "name": "comment.line.double-dash.sql", - "captures": { - "1": { - "name": "punctuation.definition.comment.sql" - } - } - }, - { - "match": "\\\\[\\\\'`\"]", - "name": "constant.character.escape.php" - }, - { - "match": "(')([^'\\\\]*)(')", - "name": "string.quoted.single.sql", - "captures": { - "1": { - "name": "punctuation.definition.string.begin.sql" - }, - "2": { - "patterns": [ - { - "include": "source.php#interpolation_double_quoted" - } - ] - }, - "3": { - "name": "punctuation.definition.string.end.sql" - } - } - }, - { - "match": "(`)([^`\\\\]*)(`)", - "name": "string.quoted.other.backtick.sql", - "captures": { - "1": { - "name": "punctuation.definition.string.begin.sql" - }, - "2": { - "patterns": [ - { - "include": "source.php#interpolation_double_quoted" - } - ] - }, - "3": { - "name": "punctuation.definition.string.end.sql" - } - } - }, - { - "match": "'(?=((\\\\')|[^'\"])*(\"|$))", - "name": "string.quoted.single.unclosed.sql" - }, - { - "include": "source.php#interpolation_double_quoted" - } - ] - }, "text.html.php - (meta.embedded | meta.tag), L:((text.html.php meta.tag) - (meta.embedded.block.php | meta.embedded.line.php)), L:(source.js - (meta.embedded.block.php | meta.embedded.line.php)), L:(source.css - (meta.embedded.block.php | meta.embedded.line.php))": { "patterns": [ { diff --git a/extensions/php/syntaxes/php.tmLanguage.json b/extensions/php/syntaxes/php.tmLanguage.json index 0dcfc8295c9..d8d7e067384 100644 --- a/extensions/php/syntaxes/php.tmLanguage.json +++ b/extensions/php/syntaxes/php.tmLanguage.json @@ -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/atom/language-php/commit/5fae657cf989701e9594912772daff33249839b3", + "version": "https://github.com/atom/language-php/commit/2bf736a814e1a58aa63470c1a29590bd02e924e7", "scopeName": "source.php", "patterns": [ { @@ -2824,6 +2824,59 @@ }, "name": "string.quoted.double.sql.php", "patterns": [ + { + "match": "(#)(\\\\\"|[^\"])*(?=\"|$)", + "name": "comment.line.number-sign.sql", + "captures": { + "1": { + "name": "punctuation.definition.comment.sql" + } + } + }, + { + "match": "(--)(\\\\\"|[^\"])*(?=\"|$)", + "name": "comment.line.double-dash.sql", + "captures": { + "1": { + "name": "punctuation.definition.comment.sql" + } + } + }, + { + "match": "\\\\[\\\\\"`']", + "name": "constant.character.escape.php" + }, + { + "match": "'(?=((\\\\')|[^'\"])*(\"|$))", + "name": "string.quoted.single.unclosed.sql" + }, + { + "match": "`(?=((\\\\`)|[^`\"])*(\"|$))", + "name": "string.quoted.other.backtick.unclosed.sql" + }, + { + "begin": "'", + "end": "'", + "name": "string.quoted.single.sql", + "patterns": [ + { + "include": "#interpolation_double_quoted" + } + ] + }, + { + "begin": "`", + "end": "`", + "name": "string.quoted.other.backtick.sql", + "patterns": [ + { + "include": "#interpolation_double_quoted" + } + ] + }, + { + "include": "#interpolation_double_quoted" + }, { "include": "source.sql" } @@ -2845,6 +2898,36 @@ }, "name": "string.quoted.single.sql.php", "patterns": [ + { + "match": "(#)(\\\\'|[^'])*(?='|$)", + "name": "comment.line.number-sign.sql", + "captures": { + "1": { + "name": "punctuation.definition.comment.sql" + } + } + }, + { + "match": "(--)(\\\\'|[^'])*(?='|$)", + "name": "comment.line.double-dash.sql", + "captures": { + "1": { + "name": "punctuation.definition.comment.sql" + } + } + }, + { + "match": "\\\\[\\\\'`\"]", + "name": "constant.character.escape.php" + }, + { + "match": "`(?=((\\\\`)|[^`'])*('|$))", + "name": "string.quoted.other.backtick.unclosed.sql" + }, + { + "match": "\"(?=((\\\\\")|[^\"'])*('|$))", + "name": "string.quoted.double.unclosed.sql" + }, { "include": "source.sql" } @@ -3685,4 +3768,4 @@ "name": "keyword.operator.null-coalescing.php" } } -} +} \ No newline at end of file diff --git a/extensions/scss/cgmanifest.json b/extensions/scss/cgmanifest.json index a67a4f54609..12247769ce2 100644 --- a/extensions/scss/cgmanifest.json +++ b/extensions/scss/cgmanifest.json @@ -6,12 +6,12 @@ "git": { "name": "atom/language-sass", "repositoryUrl": "https://github.com/atom/language-sass", - "commitHash": "303bbf0c250fe380b9e57375598cfd916110758b" + "commitHash": "f52ab12f7f9346cc2568129d8c4419bd3d506b47" } }, "license": "MIT", "description": "The file syntaxes/scss.json was derived from the Atom package https://github.com/atom/language-sass which was originally converted from the TextMate bundle https://github.com/alexsancho/SASS.tmbundle.", - "version": "0.61.4" + "version": "0.62.1" } ], "version": 1 diff --git a/extensions/simple-browser/package.json b/extensions/simple-browser/package.json index 5fd030b186a..c05c204c5cf 100644 --- a/extensions/simple-browser/package.json +++ b/extensions/simple-browser/package.json @@ -71,7 +71,7 @@ }, "devDependencies": { "vscode-codicons": "^0.0.14", - "@types/node": "^12.11.7" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/simple-browser/yarn.lock b/extensions/simple-browser/yarn.lock index 804f85a68ae..ec7bd12ab20 100644 --- a/extensions/simple-browser/yarn.lock +++ b/extensions/simple-browser/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.11.7": - version "12.12.69" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.69.tgz#7cb6a3aa0d16664bf2dcd1450ccb8477464fbd79" - integrity sha512-2F2VQRSFmzqgUEXw75L51MgnnZqc6bKWVSUPfrDPzp6mzGGibeVwyQcpvZvBr5RnsoMRHmC8EcBQiobSeqeJxg== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== applicationinsights@1.7.4: version "1.7.4" diff --git a/extensions/swift/syntaxes/swift.tmLanguage.json b/extensions/swift/syntaxes/swift.tmLanguage.json index 3396ff07de9..be1b132172e 100644 --- a/extensions/swift/syntaxes/swift.tmLanguage.json +++ b/extensions/swift/syntaxes/swift.tmLanguage.json @@ -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/textmate/swift.tmbundle/commit/2ee3d7c63f7dd2c769167278b48e3716d1b60b26", + "version": "https://github.com/textmate/swift.tmbundle/commit/8c7672d74c1baa4e6944a05ac6c57a623532f18b", "name": "Swift", "scopeName": "source.swift", "comment": "See swift.tmbundle/grammar-test.swift for test cases.", @@ -1280,7 +1280,7 @@ "name": "meta.import.swift", "patterns": [ { - "begin": "\\G(?!;|$|//|/\\*)(?:(typealias|struct|class|enum|protocol|var|func)\\s+)?", + "begin": "\\G(?!;|$|//|/\\*)(?:(typealias|struct|class|actor|enum|protocol|var|func)\\s+)?", "beginCaptures": { "1": { "name": "storage.modifier.swift" @@ -1908,7 +1908,7 @@ "type": { "patterns": [ { - "begin": "\\b(class(?!\\s+(?:func|var|let)\\b)|struct)\\s+((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k))", + "begin": "\\b(class(?!\\s+(?:func|var|let)\\b)|struct|actor)\\s+((?`?)[\\p{L}_][\\p{L}_\\p{N}\\p{M}]*(\\k))", "beginCaptures": { "1": { "name": "storage.type.$1.swift" @@ -2337,7 +2337,7 @@ ], "repository": { "availability-condition": { - "begin": "\\B(#available)(\\()", + "begin": "\\B(#(?:un)?available)(\\()", "beginCaptures": { "1": { "name": "support.function.availability-condition.swift" @@ -2645,7 +2645,7 @@ "name": "keyword.other.declaration-specifier.swift" }, { - "match": "(?= 0) { const expectedCursorPos = editor.document.positionAt(cursorIndex); - assert.deepEqual( + assert.deepStrictEqual( { line: editor.selection.active.line, character: editor.selection.active.line }, { line: expectedCursorPos.line, character: expectedCursorPos.line }, 'Cursor position' diff --git a/extensions/typescript-language-features/yarn.lock b/extensions/typescript-language-features/yarn.lock index 5ac428c1065..a94f34e248e 100644 --- a/extensions/typescript-language-features/yarn.lock +++ b/extensions/typescript-language-features/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/semver@^5.5.0": version "5.5.0" diff --git a/extensions/vscode-api-tests/package.json b/extensions/vscode-api-tests/package.json index e1c16dace63..db9279b43fc 100644 --- a/extensions/vscode-api-tests/package.json +++ b/extensions/vscode-api-tests/package.json @@ -154,7 +154,7 @@ }, "devDependencies": { "@types/mocha": "^8.2.0", - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "repository": { "type": "git", diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts index f9f971bdbda..7c906ba0fe4 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/commands.test.ts @@ -52,8 +52,8 @@ suite('vscode API - commands', () => { await commands.executeCommand('t1', 'start'); registration.dispose(); assert.ok(args!); - assert.equal(args!.length, 1); - assert.equal(args![0], 'start'); + assert.strictEqual(args!.length, 1); + assert.strictEqual(args![0], 'start'); }); test('editorCommand with extra args', function () { @@ -68,7 +68,7 @@ suite('vscode API - commands', () => { return commands.executeCommand('t1', 12345, commands); }).then(() => { assert.ok(args); - assert.equal(args.length, 4); + assert.strictEqual(args.length, 4); assert.ok(args[2] === 12345); assert.ok(args[3] === commands); registration.dispose(); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts index 0a9ddf7aa2d..9c7fa1acff5 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/configuration.test.ts @@ -15,7 +15,7 @@ suite('vscode API - configuration', () => { test('configurations, language defaults', function () { const defaultLanguageSettings = vscode.workspace.getConfiguration().get('[abcLang]'); - assert.deepEqual(defaultLanguageSettings, { + assert.deepStrictEqual(defaultLanguageSettings, { 'editor.lineNumbers': 'off', 'editor.tabSize': 2 }); @@ -25,25 +25,25 @@ suite('vscode API - configuration', () => { const config = vscode.workspace.getConfiguration('farboo'); assert.ok(config.has('config0')); - assert.equal(config.get('config0'), true); - assert.equal(config.get('config4'), ''); - assert.equal(config['config0'], true); - assert.equal(config['config4'], ''); + assert.strictEqual(config.get('config0'), true); + assert.strictEqual(config.get('config4'), ''); + assert.strictEqual(config['config0'], true); + assert.strictEqual(config['config4'], ''); assert.throws(() => (config)['config4'] = 'valuevalue'); assert.ok(config.has('nested.config1')); - assert.equal(config.get('nested.config1'), 42); + assert.strictEqual(config.get('nested.config1'), 42); assert.ok(config.has('nested.config2')); - assert.equal(config.get('nested.config2'), 'Das Pferd frisst kein Reis.'); + assert.strictEqual(config.get('nested.config2'), 'Das Pferd frisst kein Reis.'); }); test('configuration, name vs property', () => { const config = vscode.workspace.getConfiguration('farboo'); assert.ok(config.has('get')); - assert.equal(config.get('get'), 'get-prop'); - assert.deepEqual(config['get'], config.get); + assert.strictEqual(config.get('get'), 'get-prop'); + assert.deepStrictEqual(config['get'], config.get); assert.throws(() => config['get'] = 'get-prop'); }); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts index 145c2ee3bce..f79a2000cb3 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/debug.test.ts @@ -13,7 +13,7 @@ suite('vscode API - debug', function () { teardown(assertNoRpc); test('breakpoints', async function () { - assert.equal(debug.breakpoints.length, 0); + assert.strictEqual(debug.breakpoints.length, 0); let onDidChangeBreakpointsCounter = 0; const toDispose: Disposable[] = []; @@ -22,19 +22,19 @@ suite('vscode API - debug', function () { })); debug.addBreakpoints([{ id: '1', enabled: true }, { id: '2', enabled: false, condition: '2 < 5' }]); - assert.equal(onDidChangeBreakpointsCounter, 1); - assert.equal(debug.breakpoints.length, 2); - assert.equal(debug.breakpoints[0].id, '1'); - assert.equal(debug.breakpoints[1].id, '2'); - assert.equal(debug.breakpoints[1].condition, '2 < 5'); + assert.strictEqual(onDidChangeBreakpointsCounter, 1); + assert.strictEqual(debug.breakpoints.length, 2); + assert.strictEqual(debug.breakpoints[0].id, '1'); + assert.strictEqual(debug.breakpoints[1].id, '2'); + assert.strictEqual(debug.breakpoints[1].condition, '2 < 5'); debug.removeBreakpoints([{ id: '1', enabled: true }]); - assert.equal(onDidChangeBreakpointsCounter, 2); - assert.equal(debug.breakpoints.length, 1); + assert.strictEqual(onDidChangeBreakpointsCounter, 2); + assert.strictEqual(debug.breakpoints.length, 1); debug.removeBreakpoints([{ id: '2', enabled: false }]); - assert.equal(onDidChangeBreakpointsCounter, 3); - assert.equal(debug.breakpoints.length, 0); + assert.strictEqual(onDidChangeBreakpointsCounter, 3); + assert.strictEqual(debug.breakpoints.length, 0); disposeAll(toDispose); }); @@ -79,36 +79,36 @@ suite('vscode API - debug', function () { const initializedPromise = new Promise(resolve => initializedReceived = resolve); const configurationDonePromise = new Promise(resolve => configurationDoneReceived = resolve); const success = await debug.startDebugging(workspace.workspaceFolders![0], 'Launch debug.js'); - assert.equal(success, true); + assert.strictEqual(success, true); await initializedPromise; await configurationDonePromise; await firstVariablesRetrieved; - assert.notEqual(debug.activeDebugSession, undefined); - assert.equal(stoppedEvents, 1); + assert.notStrictEqual(debug.activeDebugSession, undefined); + assert.strictEqual(stoppedEvents, 1); const secondVariablesRetrieved = new Promise(resolve => variablesReceived = resolve); await commands.executeCommand('workbench.action.debug.stepOver'); await secondVariablesRetrieved; - assert.equal(stoppedEvents, 2); + assert.strictEqual(stoppedEvents, 2); const editor = window.activeTextEditor; - assert.notEqual(editor, undefined); - assert.equal(basename(editor!.document.fileName), 'debug.js'); + assert.notStrictEqual(editor, undefined); + assert.strictEqual(basename(editor!.document.fileName), 'debug.js'); const thirdVariablesRetrieved = new Promise(resolve => variablesReceived = resolve); await commands.executeCommand('workbench.action.debug.stepOver'); await thirdVariablesRetrieved; - assert.equal(stoppedEvents, 3); + assert.strictEqual(stoppedEvents, 3); const fourthVariablesRetrieved = new Promise(resolve => variablesReceived = resolve); await commands.executeCommand('workbench.action.debug.stepInto'); await fourthVariablesRetrieved; - assert.equal(stoppedEvents, 4); + assert.strictEqual(stoppedEvents, 4); const fifthVariablesRetrieved = new Promise(resolve => variablesReceived = resolve); await commands.executeCommand('workbench.action.debug.stepOut'); await fifthVariablesRetrieved; - assert.equal(stoppedEvents, 5); + assert.strictEqual(stoppedEvents, 5); let sessionTerminated: () => void; toDispose.push(debug.onDidTerminateDebugSession(() => { @@ -127,6 +127,6 @@ suite('vscode API - debug', function () { } catch (e) { errorCount++; } - assert.equal(errorCount, 1); + assert.strictEqual(errorCount, 1); }); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts index ef16bbe1c61..faf2f7d8013 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/editor.test.ts @@ -44,7 +44,7 @@ suite('vscode API - editors', () => { return withRandomFileEditor('', (editor, doc) => { return editor.insertSnippet(snippetString).then(inserted => { assert.ok(inserted); - assert.equal(doc.getText(), 'This is a placeholder snippet'); + assert.strictEqual(doc.getText(), 'This is a placeholder snippet'); assert.ok(doc.isDirty); }); }); @@ -69,7 +69,7 @@ suite('vscode API - editors', () => { await withRandomFileEditor('', async (editor, doc) => { const inserted = await editor.insertSnippet(snippetString); assert.ok(inserted); - assert.equal(doc.getText(), 'running: INTEGRATION-TESTS'); + assert.strictEqual(doc.getText(), 'running: INTEGRATION-TESTS'); assert.ok(doc.isDirty); }); @@ -88,7 +88,7 @@ suite('vscode API - editors', () => { return editor.insertSnippet(snippetString).then(inserted => { assert.ok(inserted); - assert.equal(doc.getText(), 'This has been replaced'); + assert.strictEqual(doc.getText(), 'This has been replaced'); assert.ok(doc.isDirty); }); }); @@ -106,7 +106,7 @@ suite('vscode API - editors', () => { return editor.insertSnippet(snippetString, selection).then(inserted => { assert.ok(inserted); - assert.equal(doc.getText(), 'This has been replaced'); + assert.strictEqual(doc.getText(), 'This has been replaced'); assert.ok(doc.isDirty); }); }); @@ -118,7 +118,7 @@ suite('vscode API - editors', () => { builder.insert(new Position(0, 0), 'Hello World'); }).then(applied => { assert.ok(applied); - assert.equal(doc.getText(), 'Hello World'); + assert.strictEqual(doc.getText(), 'Hello World'); assert.ok(doc.isDirty); }); }); @@ -130,7 +130,7 @@ suite('vscode API - editors', () => { builder.replace(new Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE), 'new'); }).then(applied => { assert.ok(applied); - assert.equal(doc.getText(), 'new'); + assert.strictEqual(doc.getText(), 'new'); assert.ok(doc.isDirty); }); }); @@ -146,12 +146,12 @@ suite('vscode API - editors', () => { return withRandomFileEditor('Hello world!', async (editor, doc) => { const applied1 = await executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false); assert.ok(applied1); - assert.equal(doc.getText(), 'hello world!'); + assert.strictEqual(doc.getText(), 'hello world!'); assert.ok(doc.isDirty); const applied2 = await executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', false, false); assert.ok(applied2); - assert.equal(doc.getText(), 'hELLO world!'); + assert.strictEqual(doc.getText(), 'hELLO world!'); assert.ok(doc.isDirty); await commands.executeCommand('undo'); @@ -161,7 +161,7 @@ suite('vscode API - editors', () => { // it is unclear why this happens, but it can happen for a multitude of reasons await commands.executeCommand('undo'); } - assert.equal(doc.getText(), 'Hello world!'); + assert.strictEqual(doc.getText(), 'Hello world!'); }); }); @@ -169,16 +169,16 @@ suite('vscode API - editors', () => { return withRandomFileEditor('Hello world!', (editor, doc) => { return executeReplace(editor, new Range(0, 0, 0, 1), 'h', false, false).then(applied => { assert.ok(applied); - assert.equal(doc.getText(), 'hello world!'); + assert.strictEqual(doc.getText(), 'hello world!'); assert.ok(doc.isDirty); return executeReplace(editor, new Range(0, 1, 0, 5), 'ELLO', true, false); }).then(applied => { assert.ok(applied); - assert.equal(doc.getText(), 'hELLO world!'); + assert.strictEqual(doc.getText(), 'hELLO world!'); assert.ok(doc.isDirty); return commands.executeCommand('undo'); }).then(_ => { - assert.equal(doc.getText(), 'hello world!'); + assert.strictEqual(doc.getText(), 'hello world!'); }); }); }); @@ -186,26 +186,26 @@ suite('vscode API - editors', () => { test('issue #16573: Extension API: insertSpaces and tabSize are undefined', () => { return withRandomFileEditor('Hello world!\n\tHello world!', (editor, _doc) => { - assert.equal(editor.options.tabSize, 4); - assert.equal(editor.options.insertSpaces, false); - assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line); - assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); + assert.strictEqual(editor.options.tabSize, 4); + assert.strictEqual(editor.options.insertSpaces, false); + assert.strictEqual(editor.options.cursorStyle, TextEditorCursorStyle.Line); + assert.strictEqual(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); editor.options = { tabSize: 2 }; - assert.equal(editor.options.tabSize, 2); - assert.equal(editor.options.insertSpaces, false); - assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line); - assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); + assert.strictEqual(editor.options.tabSize, 2); + assert.strictEqual(editor.options.insertSpaces, false); + assert.strictEqual(editor.options.cursorStyle, TextEditorCursorStyle.Line); + assert.strictEqual(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); editor.options.tabSize = 'invalid'; - assert.equal(editor.options.tabSize, 2); - assert.equal(editor.options.insertSpaces, false); - assert.equal(editor.options.cursorStyle, TextEditorCursorStyle.Line); - assert.equal(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); + assert.strictEqual(editor.options.tabSize, 2); + assert.strictEqual(editor.options.insertSpaces, false); + assert.strictEqual(editor.options.cursorStyle, TextEditorCursorStyle.Line); + assert.strictEqual(editor.options.lineNumbers, TextEditorLineNumbersStyle.On); return Promise.resolve(); }); @@ -262,6 +262,6 @@ suite('vscode API - editors', () => { const file = Uri.parse(root.toString() + relativePath); const document = await workspace.openTextDocument(file); - assert.equal(document.getText(), Buffer.from(await workspace.fs.readFile(file)).toString()); + assert.strictEqual(document.getText(), Buffer.from(await workspace.fs.readFile(file)).toString()); } }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts index 42e25bafddd..73b79952591 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/env.test.ts @@ -12,12 +12,12 @@ suite('vscode API - env', () => { teardown(assertNoRpc); test('env is set', function () { - assert.equal(typeof env.language, 'string'); - assert.equal(typeof env.appRoot, 'string'); - assert.equal(typeof env.appName, 'string'); - assert.equal(typeof env.machineId, 'string'); - assert.equal(typeof env.sessionId, 'string'); - assert.equal(typeof env.shell, 'string'); + assert.strictEqual(typeof env.language, 'string'); + assert.strictEqual(typeof env.appRoot, 'string'); + assert.strictEqual(typeof env.appName, 'string'); + assert.strictEqual(typeof env.machineId, 'string'); + assert.strictEqual(typeof env.sessionId, 'string'); + assert.strictEqual(typeof env.shell, 'string'); }); test('env is readonly', function () { @@ -37,7 +37,7 @@ suite('vscode API - env', () => { // not running in remote, so we expect both extensions assert.ok(knownWorkspaceExtension); assert.ok(knownUiAndWorkspaceExtension); - assert.equal(ExtensionKind.UI, knownUiAndWorkspaceExtension!.extensionKind); + assert.strictEqual(ExtensionKind.UI, knownUiAndWorkspaceExtension!.extensionKind); } else if (typeof remoteName === 'string') { // running in remote, so we only expect workspace extensions assert.ok(knownWorkspaceExtension); @@ -46,7 +46,7 @@ suite('vscode API - env', () => { } else { assert.ok(knownUiAndWorkspaceExtension); } - assert.equal(ExtensionKind.Workspace, knownWorkspaceExtension!.extensionKind); + assert.strictEqual(ExtensionKind.Workspace, knownWorkspaceExtension!.extensionKind); } else { assert.fail(); } @@ -58,9 +58,9 @@ suite('vscode API - env', () => { const kind = env.uiKind; if (result.scheme === 'http' || result.scheme === 'https') { - assert.equal(kind, UIKind.Web); + assert.strictEqual(kind, UIKind.Web); } else { - assert.equal(kind, UIKind.Desktop); + assert.strictEqual(kind, UIKind.Desktop); } }); @@ -70,9 +70,9 @@ suite('vscode API - env', () => { assert.ok(result); if (env.uiKind === UIKind.Desktop) { - assert.equal(uri.scheme, result.scheme); - assert.equal(uri.authority, result.authority); - assert.equal(uri.path, result.path); + assert.strictEqual(uri.scheme, result.scheme); + assert.strictEqual(uri.authority, result.authority); + assert.strictEqual(uri.path, result.path); } else { assert.ok(result.scheme === 'http' || result.scheme === 'https'); } diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts index 0553a4444db..ed75f597dc5 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/languages.test.ts @@ -23,7 +23,7 @@ suite('vscode API - languages', () => { } function assertEqualRange(actual: vscode.Range, expected: vscode.Range, message?: string) { - assert.equal(rangeToString(actual), rangeToString(expected), message); + assert.strictEqual(rangeToString(actual), rangeToString(expected), message); } test('setTextDocumentLanguage -> close/open event', async function () { @@ -36,8 +36,8 @@ suite('vscode API - languages', () => { let close = new Promise(resolve => { disposables.push(vscode.workspace.onDidCloseTextDocument(e => { if (e === doc) { - assert.equal(doc.languageId, langIdNow); - assert.equal(clock, 0); + assert.strictEqual(doc.languageId, langIdNow); + assert.strictEqual(clock, 0); clock += 1; resolve(); } @@ -46,8 +46,8 @@ suite('vscode API - languages', () => { let open = new Promise(resolve => { disposables.push(vscode.workspace.onDidOpenTextDocument(e => { if (e === doc) { // same instance! - assert.equal(doc.languageId, 'json'); - assert.equal(clock, 1); + assert.strictEqual(doc.languageId, 'json'); + assert.strictEqual(clock, 1); clock += 1; resolve(); } @@ -55,8 +55,8 @@ suite('vscode API - languages', () => { }); let change = vscode.languages.setTextDocumentLanguage(doc, 'json'); await Promise.all([change, close, open]); - assert.equal(clock, 2); - assert.equal(doc.languageId, 'json'); + assert.strictEqual(clock, 2); + assert.strictEqual(doc.languageId, 'json'); disposables.forEach(disposable => disposable.dispose()); disposables.length = 0; }); @@ -82,7 +82,7 @@ suite('vscode API - languages', () => { col2.set(uri, [new vscode.Diagnostic(new vscode.Range(0, 0, 0, 12), 'error1')]); let diag = vscode.languages.getDiagnostics(uri); - assert.equal(diag.length, 2); + assert.strictEqual(diag.length, 2); let tuples = vscode.languages.getDiagnostics(); let found = false; @@ -111,13 +111,13 @@ suite('vscode API - languages', () => { vscode.languages.registerDocumentLinkProvider({ language: 'java', scheme: testFs.scheme }, linkProvider); const links = await vscode.commands.executeCommand('vscode.executeLinkProvider', doc.uri); - assert.equal(2, links && links.length); + assert.strictEqual(2, links && links.length); let [link1, link2] = links!.sort((l1, l2) => l1.range.start.compareTo(l2.range.start)); - assert.equal(target.toString(), link1.target && link1.target.toString()); + assert.strictEqual(target.toString(), link1.target && link1.target.toString()); assertEqualRange(range, link1.range); - assert.equal('http://a.com/', link2.target && link2.target.toString()); + assert.strictEqual('http://a.com/', link2.target && link2.target.toString()); assertEqualRange(new vscode.Range(new vscode.Position(0, 13), new vscode.Position(0, 25)), link2.range); }); @@ -139,7 +139,7 @@ suite('vscode API - languages', () => { let r1 = vscode.languages.registerCodeActionsProvider({ pattern: '*.far', scheme: 'ttt' }, { provideCodeActions(_document, _range, ctx): vscode.Command[] { - assert.equal(ctx.diagnostics.length, 2); + assert.strictEqual(ctx.diagnostics.length, 2); let [first, second] = ctx.diagnostics; assert.ok(first === diag1); assert.ok(second === diag2); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts index 4c66477b78e..45144e66c97 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/notebook.test.ts @@ -522,7 +522,7 @@ suite('Notebook API tests', function () { await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); const activeCell = getFocusedCell(vscode.window.activeNotebookEditor); - assert.notEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined); + assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined); assert.strictEqual(activeCell!.document.getText(), ''); assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4); assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1); @@ -545,7 +545,7 @@ suite('Notebook API tests', function () { // ---- insert cell above and focus ---- // await vscode.commands.executeCommand('notebook.cell.insertCodeCellAbove'); let activeCell = getFocusedCell(vscode.window.activeNotebookEditor); - assert.notEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined); + assert.notStrictEqual(getFocusedCell(vscode.window.activeNotebookEditor), undefined); assert.strictEqual(activeCell!.document.getText(), ''); assert.strictEqual(vscode.window.activeNotebookEditor!.document.cellCount, 4); assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().indexOf(activeCell!), 1); @@ -1049,7 +1049,7 @@ suite('Notebook API tests', function () { assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.getText(), 'test'); assert.strictEqual(getFocusedCell(vscode.window.activeNotebookEditor!)?.document.languageId, 'typescript'); - assert.notEqual(firstNotebookEditor, secondNotebookEditor); + assert.notStrictEqual(firstNotebookEditor, secondNotebookEditor); assert.strictEqual(firstNotebookEditor?.document, secondNotebookEditor?.document, 'split notebook editors share the same document'); await saveAllFilesAndCloseAll(resource); @@ -1151,15 +1151,15 @@ suite('Notebook API tests', function () { // now it's dirty, open the resource with notebook editor should open a new one await vscode.commands.executeCommand('vscode.openWith', resource, 'notebookCoreTest'); - assert.notEqual(vscode.window.activeNotebookEditor, undefined, 'notebook first'); - // assert.notEqual(vscode.window.activeTextEditor, undefined); + assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'notebook first'); + // assert.notStrictEqual(vscode.window.activeTextEditor, undefined); await closeAllEditors(); }); test('#102411 - untitled notebook creation failed', async function () { await vscode.commands.executeCommand('workbench.action.files.newUntitledFile', { viewType: 'notebookCoreTest' }); - assert.notEqual(vscode.window.activeNotebookEditor, undefined, 'untitled notebook editor is not undefined'); + assert.notStrictEqual(vscode.window.activeNotebookEditor, undefined, 'untitled notebook editor is not undefined'); await closeAllEditors(); }); @@ -1182,7 +1182,7 @@ suite('Notebook API tests', function () { await vscode.workspace.applyEdit(edit); assert.strictEqual(vscode.window.activeNotebookEditor!.document.getCells().length, 3); - assert.notEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText()); + assert.notStrictEqual(vscode.window.activeNotebookEditor!.document.cellAt(0).document.getText(), vscode.window.activeNotebookEditor!.document.cellAt(1).document.getText()); await closeAllEditors(); }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts index 701c947426b..0b3b4e92102 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/quickInput.test.ts @@ -216,10 +216,10 @@ function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, } try { eventIndex++; - assert.equal('active', expected.events.shift(), `onDidChangeActive (event ${eventIndex})`); + assert.strictEqual('active', expected.events.shift(), `onDidChangeActive (event ${eventIndex})`); const expectedItems = expected.activeItems.shift(); - assert.deepEqual(items.map(item => item.label), expectedItems, `onDidChangeActive event items (event ${eventIndex})`); - assert.deepEqual(quickPick.activeItems.map(item => item.label), expectedItems, `onDidChangeActive active items (event ${eventIndex})`); + assert.deepStrictEqual(items.map(item => item.label), expectedItems, `onDidChangeActive event items (event ${eventIndex})`); + assert.deepStrictEqual(quickPick.activeItems.map(item => item.label), expectedItems, `onDidChangeActive active items (event ${eventIndex})`); } catch (err) { done(err); } @@ -231,10 +231,10 @@ function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, } try { eventIndex++; - assert.equal('selection', expected.events.shift(), `onDidChangeSelection (event ${eventIndex})`); + assert.strictEqual('selection', expected.events.shift(), `onDidChangeSelection (event ${eventIndex})`); const expectedItems = expected.selectionItems.shift(); - assert.deepEqual(items.map(item => item.label), expectedItems, `onDidChangeSelection event items (event ${eventIndex})`); - assert.deepEqual(quickPick.selectedItems.map(item => item.label), expectedItems, `onDidChangeSelection selected items (event ${eventIndex})`); + assert.deepStrictEqual(items.map(item => item.label), expectedItems, `onDidChangeSelection event items (event ${eventIndex})`); + assert.deepStrictEqual(quickPick.selectedItems.map(item => item.label), expectedItems, `onDidChangeSelection selected items (event ${eventIndex})`); } catch (err) { done(err); } @@ -246,11 +246,11 @@ function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, } try { eventIndex++; - assert.equal('accept', expected.events.shift(), `onDidAccept (event ${eventIndex})`); + assert.strictEqual('accept', expected.events.shift(), `onDidAccept (event ${eventIndex})`); const expectedActive = expected.acceptedItems.active.shift(); - assert.deepEqual(quickPick.activeItems.map(item => item.label), expectedActive, `onDidAccept active items (event ${eventIndex})`); + assert.deepStrictEqual(quickPick.activeItems.map(item => item.label), expectedActive, `onDidAccept active items (event ${eventIndex})`); const expectedSelection = expected.acceptedItems.selection.shift(); - assert.deepEqual(quickPick.selectedItems.map(item => item.label), expectedSelection, `onDidAccept selected items (event ${eventIndex})`); + assert.deepStrictEqual(quickPick.selectedItems.map(item => item.label), expectedSelection, `onDidAccept selected items (event ${eventIndex})`); if (expected.acceptedItems.dispose.shift()) { quickPick.dispose(); } @@ -265,7 +265,7 @@ function createQuickPick(expected: QuickPickExpected, done: (err?: any) => void, return; } try { - assert.equal('hide', expected.events.shift()); + assert.strictEqual('hide', expected.events.shift()); done(); } catch (err) { done(err); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts index a23d3e55c73..da2da9499fc 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/terminal.test.ts @@ -504,6 +504,41 @@ import { assertNoRpc } from '../utils'; const terminal = window.createTerminal({ name: 'foo', pty }); }); + test('should change terminal name', (done) => { + disposables.push(window.onDidOpenTerminal(term => { + try { + equal(terminal, term); + equal(terminal.name, 'foo'); + } catch (e) { + done(e); + return; + } + disposables.push(window.onDidCloseTerminal(t => { + try { + equal(terminal, t); + equal(terminal.name, 'bar'); + } catch (e) { + done(e); + return; + } + done(); + })); + })); + const changeNameEmitter = new EventEmitter(); + const closeEmitter = new EventEmitter(); + const pty: Pseudoterminal = { + onDidWrite: new EventEmitter().event, + onDidChangeName: changeNameEmitter.event, + onDidClose: closeEmitter.event, + open: () => { + changeNameEmitter.fire('bar'); + closeEmitter.fire(undefined); + }, + close: () => { } + }; + const terminal = window.createTerminal({ name: 'foo', pty }); + }); + test('exitStatus.code should be set to the exit code (undefined)', (done) => { disposables.push(window.onDidOpenTerminal(term => { try { diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts index c30ab513837..b672c7705ac 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/window.test.ts @@ -34,20 +34,20 @@ suite('vscode API - window', () => { }); // test('editor, UN-active text editor', () => { - // assert.equal(window.visibleTextEditors.length, 0); + // assert.strictEqual(window.visibleTextEditors.length, 0); // assert.ok(window.activeTextEditor === undefined); // }); test('editor, assign and check view columns', async () => { const doc = await workspace.openTextDocument(join(workspace.rootPath || '', './far.js')); let p1 = window.showTextDocument(doc, ViewColumn.One).then(editor => { - assert.equal(editor.viewColumn, ViewColumn.One); + assert.strictEqual(editor.viewColumn, ViewColumn.One); }); let p2 = window.showTextDocument(doc, ViewColumn.Two).then(editor_1 => { - assert.equal(editor_1.viewColumn, ViewColumn.Two); + assert.strictEqual(editor_1.viewColumn, ViewColumn.Two); }); let p3 = window.showTextDocument(doc, ViewColumn.Three).then(editor_2 => { - assert.equal(editor_2.viewColumn, ViewColumn.Three); + assert.strictEqual(editor_2.viewColumn, ViewColumn.Three); }); return Promise.all([p1, p2, p3]); }); @@ -60,13 +60,13 @@ suite('vscode API - window', () => { const doc = await workspace.openTextDocument(join(workspace.rootPath || '', './far.js')); await window.showTextDocument(doc, ViewColumn.One); - assert.equal(eventCounter, 1); + assert.strictEqual(eventCounter, 1); await window.showTextDocument(doc, ViewColumn.Two); - assert.equal(eventCounter, 2); + assert.strictEqual(eventCounter, 2); await window.showTextDocument(doc, ViewColumn.Three); - assert.equal(eventCounter, 3); + assert.strictEqual(eventCounter, 3); reg.dispose(); }); @@ -138,10 +138,10 @@ suite('vscode API - window', () => { return commands.executeCommand('workbench.action.moveActiveEditorGroupLeft'); }).then(() => { - assert.equal(actualEvents.length, 2); + assert.strictEqual(actualEvents.length, 2); for (const event of actualEvents) { - assert.equal(event.viewColumn, event.textEditor.viewColumn); + assert.strictEqual(event.viewColumn, event.textEditor.viewColumn); } registration1.dispose(); @@ -202,7 +202,7 @@ suite('vscode API - window', () => { assert.ok(window.activeTextEditor); assert.ok(window.activeTextEditor!.document === docB); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Two); const editor = await window.showTextDocument(docC); assert.ok( @@ -210,7 +210,7 @@ suite('vscode API - window', () => { `wanted fileName:${editor.document.fileName}/viewColumn:${editor.viewColumn} but got fileName:${window.activeTextEditor!.document.fileName}/viewColumn:${window.activeTextEditor!.viewColumn}. a:${docA.fileName}, b:${docB.fileName}, c:${docC.fileName}` ); assert.ok(window.activeTextEditor!.document === docC); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Two); }); test('showTextDocument ViewColumn.BESIDE', async () => { @@ -225,12 +225,12 @@ suite('vscode API - window', () => { assert.ok(window.activeTextEditor); assert.ok(window.activeTextEditor!.document === docB); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Two); await window.showTextDocument(docC, ViewColumn.Beside); assert.ok(window.activeTextEditor!.document === docC); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Three); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Three); }); test('showTextDocument ViewColumn is always defined (even when opening > ViewColumn.Nine)', async () => { @@ -260,7 +260,7 @@ suite('vscode API - window', () => { assert.ok(window.activeTextEditor); assert.ok(window.activeTextEditor!.document === doc10); - assert.equal(window.activeTextEditor!.viewColumn, 10); + assert.strictEqual(window.activeTextEditor!.viewColumn, 10); }); test('issue #27408 - showTextDocument & vscode.diff always default to ViewColumn.One', async () => { @@ -275,12 +275,12 @@ suite('vscode API - window', () => { assert.ok(window.activeTextEditor); assert.ok(window.activeTextEditor!.document === docB); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Two); await window.showTextDocument(docC, ViewColumn.Active); assert.ok(window.activeTextEditor!.document === docC); - assert.equal(window.activeTextEditor!.viewColumn, ViewColumn.Two); + assert.strictEqual(window.activeTextEditor!.viewColumn, ViewColumn.Two); }); test('issue #5362 - Incorrect TextEditor passed by onDidChangeTextEditorSelection', (done) => { @@ -359,7 +359,7 @@ suite('vscode API - window', () => { const p = window.showInputBox(undefined, source.token); source.cancel(); const value = await p; - assert.equal(value, undefined); + assert.strictEqual(value, undefined); }); test('showInputBox - cancel early', async function () { @@ -367,21 +367,21 @@ suite('vscode API - window', () => { source.cancel(); const p = window.showInputBox(undefined, source.token); const value = await p; - assert.equal(value, undefined); + assert.strictEqual(value, undefined); }); test('showInputBox - \'\' on Enter', function () { const p = window.showInputBox(); return Promise.all([ commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'), - p.then(value => assert.equal(value, '')) + p.then(value => assert.strictEqual(value, '')) ]); }); test('showInputBox - default value on Enter', function () { const p = window.showInputBox({ value: 'farboo' }); return Promise.all([ - p.then(value => assert.equal(value, 'farboo')), + p.then(value => assert.strictEqual(value, 'farboo')), commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'), ]); }); @@ -390,7 +390,7 @@ suite('vscode API - window', () => { const p = window.showInputBox(); return Promise.all([ commands.executeCommand('workbench.action.closeQuickOpen'), - p.then(value => assert.equal(value, undefined)) + p.then(value => assert.strictEqual(value, undefined)) ]); }); @@ -398,17 +398,17 @@ suite('vscode API - window', () => { const p = window.showInputBox({ value: 'farboo' }); return Promise.all([ commands.executeCommand('workbench.action.closeQuickOpen'), - p.then(value => assert.equal(value, undefined)) + p.then(value => assert.strictEqual(value, undefined)) ]); }); test('showInputBox - value not empty on second try', async function () { const one = window.showInputBox({ value: 'notempty' }); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.equal(await one, 'notempty'); + assert.strictEqual(await one, 'notempty'); const two = window.showInputBox({ value: 'notempty' }); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.equal(await two, 'notempty'); + assert.strictEqual(await two, 'notempty'); }); test('showQuickPick, accept first', async function () { @@ -417,9 +417,9 @@ suite('vscode API - window', () => { const pick = window.showQuickPick(['eins', 'zwei', 'drei'], { onDidSelectItem: tracker.onDidSelectItem }); - assert.equal(await first, 'eins'); + assert.strictEqual(await first, 'eins'); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.equal(await pick, 'eins'); + assert.strictEqual(await pick, 'eins'); return tracker.done(); }); @@ -429,12 +429,12 @@ suite('vscode API - window', () => { const pick = window.showQuickPick(['eins', 'zwei', 'drei'], { onDidSelectItem: tracker.onDidSelectItem }); - assert.equal(await first, 'eins'); + assert.strictEqual(await first, 'eins'); const second = tracker.nextItem(); await commands.executeCommand('workbench.action.quickOpenSelectNext'); - assert.equal(await second, 'zwei'); + assert.strictEqual(await second, 'zwei'); await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); - assert.equal(await pick, 'zwei'); + assert.strictEqual(await pick, 'zwei'); return tracker.done(); }); @@ -457,14 +457,14 @@ suite('vscode API - window', () => { // console.log(`${label}: ${++i}`); await commands.executeCommand('workbench.action.quickOpenSelectNext'); // console.log(`${label}: ${++i}`); - assert.equal(await first, 'eins'); + assert.strictEqual(await first, 'eins'); // console.log(`${label}: ${++i}`); await commands.executeCommand('workbench.action.quickPickManyToggle'); // console.log(`${label}: ${++i}`); const second = new Promise(resolve => resolves.push(resolve)); await commands.executeCommand('workbench.action.quickOpenSelectNext'); // console.log(`${label}: ${++i}`); - assert.equal(await second, 'zwei'); + assert.strictEqual(await second, 'zwei'); // console.log(`${label}: ${++i}`); await commands.executeCommand('workbench.action.quickPickManyToggle'); // console.log(`${label}: ${++i}`); @@ -503,7 +503,7 @@ suite('vscode API - window', () => { const p = window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token); source.cancel(); return p.then(value => { - assert.equal(value, undefined); + assert.strictEqual(value, undefined); }); }); @@ -512,7 +512,7 @@ suite('vscode API - window', () => { source.cancel(); const p = window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token); return p.then(value => { - assert.equal(value, undefined); + assert.strictEqual(value, undefined); }); }); @@ -522,7 +522,7 @@ suite('vscode API - window', () => { const result = window.showQuickPick(['eins', 'zwei', 'drei'], { ignoreFocusOut: true }).then(result => { source.cancel(); - assert.equal(result, undefined); + assert.strictEqual(result, undefined); }); window.showQuickPick(['eins', 'zwei', 'drei'], undefined, source.token); @@ -533,7 +533,7 @@ suite('vscode API - window', () => { test('showQuickPick, canceled by input', function () { const result = window.showQuickPick(['eins', 'zwei', 'drei'], { ignoreFocusOut: true }).then(result => { - assert.equal(result, undefined); + assert.strictEqual(result, undefined); }); const source = new CancellationTokenSource(); @@ -553,7 +553,7 @@ suite('vscode API - window', () => { const result = window.showQuickPick(data, undefined, source.token); source.cancel(); const value_1 = await result; - assert.equal(value_1, undefined); + assert.strictEqual(value_1, undefined); }); test('showQuickPick, never resolve promise and cancel - #22453', function () { @@ -561,7 +561,7 @@ suite('vscode API - window', () => { const result = window.showQuickPick(new Promise(_resolve => { })); const a = result.then(value => { - assert.equal(value, undefined); + assert.strictEqual(value, undefined); }); const b = commands.executeCommand('workbench.action.closeQuickOpen'); return Promise.all([a, b]); @@ -598,7 +598,7 @@ suite('vscode API - window', () => { await commands.executeCommand('workbench.action.acceptSelectedQuickOpenItem'); await commands.executeCommand('workbench.action.closeQuickOpen'); - assert.equal(await result, undefined); + assert.strictEqual(await result, undefined); }); function createQuickPickTracker() { @@ -627,7 +627,7 @@ suite('vscode API - window', () => { let subscription = window.onDidChangeTextEditorSelection(e => { assert.ok(e.textEditor === editor); - assert.equal(e.kind, TextEditorSelectionChangeKind.Command); + assert.strictEqual(e.kind, TextEditorSelectionChangeKind.Command); subscription.dispose(); resolve(); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.event.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.event.test.ts index 10ef9563c87..cdb2217512b 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.event.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.event.test.ts @@ -35,12 +35,12 @@ suite('vscode API - workspace events', () => { assert.ok(success); assert.ok(onWillCreate); - assert.equal(onWillCreate?.files.length, 1); - assert.equal(onWillCreate?.files[0].toString(), newUri.toString()); + assert.strictEqual(onWillCreate?.files.length, 1); + assert.strictEqual(onWillCreate?.files[0].toString(), newUri.toString()); assert.ok(onDidCreate); - assert.equal(onDidCreate?.files.length, 1); - assert.equal(onDidCreate?.files[0].toString(), newUri.toString()); + assert.strictEqual(onDidCreate?.files.length, 1); + assert.strictEqual(onDidCreate?.files[0].toString(), newUri.toString()); })); test('onWillCreate/onDidCreate, make changes, edit another file', withLogDisabled(async function () { @@ -62,7 +62,7 @@ suite('vscode API - workspace events', () => { const success = await vscode.workspace.applyEdit(edit); assert.ok(success); - assert.equal(baseDoc.getText(), 'HALLO_NEW'); + assert.strictEqual(baseDoc.getText(), 'HALLO_NEW'); })); test('onWillCreate/onDidCreate, make changes, edit new file fails', withLogDisabled(async function () { @@ -83,8 +83,8 @@ suite('vscode API - workspace events', () => { const success = await vscode.workspace.applyEdit(edit); assert.ok(success); - assert.equal((await vscode.workspace.fs.readFile(newUri)).toString(), ''); - assert.equal((await vscode.workspace.openTextDocument(newUri)).getText(), ''); + assert.strictEqual((await vscode.workspace.fs.readFile(newUri)).toString(), ''); + assert.strictEqual((await vscode.workspace.openTextDocument(newUri)).getText(), ''); })); test('onWillDelete/onDidDelete', withLogDisabled(async function () { @@ -104,12 +104,12 @@ suite('vscode API - workspace events', () => { assert.ok(success); assert.ok(onWilldelete); - assert.equal(onWilldelete?.files.length, 1); - assert.equal(onWilldelete?.files[0].toString(), base.toString()); + assert.strictEqual(onWilldelete?.files.length, 1); + assert.strictEqual(onWilldelete?.files[0].toString(), base.toString()); assert.ok(onDiddelete); - assert.equal(onDiddelete?.files.length, 1); - assert.equal(onDiddelete?.files[0].toString(), base.toString()); + assert.strictEqual(onDiddelete?.files.length, 1); + assert.strictEqual(onDiddelete?.files[0].toString(), base.toString()); })); test('onWillDelete/onDidDelete, make changes', withLogDisabled(async function () { @@ -190,14 +190,14 @@ suite('vscode API - workspace events', () => { assert.ok(success); assert.ok(onWillRename); - assert.equal(onWillRename?.files.length, 1); - assert.equal(onWillRename?.files[0].oldUri.toString(), oldUri.toString()); - assert.equal(onWillRename?.files[0].newUri.toString(), newUri.toString()); + assert.strictEqual(onWillRename?.files.length, 1); + assert.strictEqual(onWillRename?.files[0].oldUri.toString(), oldUri.toString()); + assert.strictEqual(onWillRename?.files[0].newUri.toString(), newUri.toString()); assert.ok(onDidRename); - assert.equal(onDidRename?.files.length, 1); - assert.equal(onDidRename?.files[0].oldUri.toString(), oldUri.toString()); - assert.equal(onDidRename?.files[0].newUri.toString(), newUri.toString()); + assert.strictEqual(onDidRename?.files.length, 1); + assert.strictEqual(onDidRename?.files[0].oldUri.toString(), oldUri.toString()); + assert.strictEqual(onDidRename?.files[0].newUri.toString(), newUri.toString()); })); test('onWillRename - make changes (saved file)', withLogDisabled(function () { @@ -244,15 +244,15 @@ suite('vscode API - workspace events', () => { assert.ok(success); assert.ok(onWillRename); - assert.equal(onWillRename?.files.length, 1); - assert.equal(onWillRename?.files[0].oldUri.toString(), oldUri.toString()); - assert.equal(onWillRename?.files[0].newUri.toString(), newUri.toString()); + assert.strictEqual(onWillRename?.files.length, 1); + assert.strictEqual(onWillRename?.files[0].oldUri.toString(), oldUri.toString()); + assert.strictEqual(onWillRename?.files[0].newUri.toString(), newUri.toString()); const newDocument = await vscode.workspace.openTextDocument(newUri); const anotherDocument = await vscode.workspace.openTextDocument(anotherFile); - assert.equal(newDocument.getText(), withDirtyFile ? 'FOOBARBAR' : 'FOOBAR'); - assert.equal(anotherDocument.getText(), 'FARBOO'); + assert.strictEqual(newDocument.getText(), withDirtyFile ? 'FOOBARBAR' : 'FOOBAR'); + assert.strictEqual(anotherDocument.getText(), 'FARBOO'); assert.ok(newDocument.isDirty); assert.ok(anotherDocument.isDirty); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts index 193ab54be61..a59c0f85fc1 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.fs.test.ts @@ -20,11 +20,11 @@ suite('vscode API - workspace-fs', () => { test('fs.stat', async function () { const stat = await vscode.workspace.fs.stat(root); - assert.equal(stat.type, vscode.FileType.Directory); + assert.strictEqual(stat.type, vscode.FileType.Directory); - assert.equal(typeof stat.size, 'number'); - assert.equal(typeof stat.mtime, 'number'); - assert.equal(typeof stat.ctime, 'number'); + assert.strictEqual(typeof stat.size, 'number'); + assert.strictEqual(typeof stat.mtime, 'number'); + assert.strictEqual(typeof stat.ctime, 'number'); assert.ok(stat.mtime > 0); assert.ok(stat.ctime > 0); @@ -35,8 +35,8 @@ suite('vscode API - workspace-fs', () => { // find far.js const tuple = entries.find(tuple => tuple[0] === 'far.js')!; assert.ok(tuple); - assert.equal(tuple[0], 'far.js'); - assert.equal(tuple[1], vscode.FileType.File); + assert.strictEqual(tuple[0], 'far.js'); + assert.strictEqual(tuple[1], vscode.FileType.File); }); test('fs.stat - bad scheme', async function () { @@ -63,7 +63,7 @@ suite('vscode API - workspace-fs', () => { await vscode.workspace.fs.writeFile(uri, Buffer.from('HELLO')); const stat = await vscode.workspace.fs.stat(uri); - assert.equal(stat.type, vscode.FileType.File); + assert.strictEqual(stat.type, vscode.FileType.File); await vscode.workspace.fs.delete(uri); @@ -129,7 +129,7 @@ suite('vscode API - workspace-fs', () => { assert.ok(false); } catch (e) { assert.ok(e instanceof vscode.FileSystemError); - assert.equal(e.name, vscode.FileSystemError.FileNotFound().name); + assert.strictEqual(e.name, vscode.FileSystemError.FileNotFound().name); } }); @@ -140,7 +140,7 @@ suite('vscode API - workspace-fs', () => { assert.ok(false); } catch (e) { assert.ok(e instanceof vscode.FileSystemError); - assert.equal(e.name, vscode.FileSystemError.Unavailable().name); + assert.strictEqual(e.name, vscode.FileSystemError.Unavailable().name); } }); diff --git a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts index e60998c24be..b17ebdbd5c6 100644 --- a/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/singlefolder-tests/workspace.test.ts @@ -19,17 +19,17 @@ suite('vscode API - workspace', () => { test('MarkdownString', function () { let md = new vscode.MarkdownString(); - assert.equal(md.value, ''); - assert.equal(md.isTrusted, undefined); + assert.strictEqual(md.value, ''); + assert.strictEqual(md.isTrusted, undefined); md = new vscode.MarkdownString('**bold**'); - assert.equal(md.value, '**bold**'); + assert.strictEqual(md.value, '**bold**'); md.appendText('**bold?**'); - assert.equal(md.value, '**bold**\\*\\*bold?\\*\\*'); + assert.strictEqual(md.value, '**bold**\\*\\*bold?\\*\\*'); md.appendMarkdown('**bold**'); - assert.equal(md.value, '**bold**\\*\\*bold?\\*\\***bold**'); + assert.strictEqual(md.value, '**bold**\\*\\*bold?\\*\\***bold**'); }); @@ -49,7 +49,7 @@ suite('vscode API - workspace', () => { test('workspaceFolders', () => { if (vscode.workspace.workspaceFolders) { - assert.equal(vscode.workspace.workspaceFolders.length, 1); + assert.strictEqual(vscode.workspace.workspaceFolders.length, 1); assert.ok(pathEquals(vscode.workspace.workspaceFolders[0].uri.fsPath, join(__dirname, '../../testWorkspace'))); } }); @@ -68,14 +68,14 @@ suite('vscode API - workspace', () => { // not yet there const existing1 = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === uri.toString()); - assert.equal(existing1, undefined); + assert.strictEqual(existing1, undefined); // open and assert its there const doc = await vscode.workspace.openTextDocument(uri); assert.ok(doc); - assert.equal(doc.uri.toString(), uri.toString()); + assert.strictEqual(doc.uri.toString(), uri.toString()); const existing2 = vscode.workspace.textDocuments.find(doc => doc.uri.toString() === uri.toString()); - assert.equal(existing2 === doc, true); + assert.strictEqual(existing2 === doc, true); }); test('openTextDocument, illegal path', () => { @@ -88,7 +88,7 @@ suite('vscode API - workspace', () => { test('openTextDocument, untitled is dirty', async function () { return vscode.workspace.openTextDocument(vscode.workspace.workspaceFolders![0].uri.with({ scheme: 'untitled', path: posix.join(vscode.workspace.workspaceFolders![0].uri.path, 'newfile.txt') })).then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.uri.scheme, 'untitled'); assert.ok(doc.isDirty); }); }); @@ -96,31 +96,31 @@ suite('vscode API - workspace', () => { test('openTextDocument, untitled with host', function () { const uri = vscode.Uri.parse('untitled://localhost/c%24/Users/jrieken/code/samples/foobar.txt'); return vscode.workspace.openTextDocument(uri).then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.uri.scheme, 'untitled'); }); }); test('openTextDocument, untitled without path', function () { return vscode.workspace.openTextDocument().then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.uri.scheme, 'untitled'); assert.ok(doc.isDirty); }); }); test('openTextDocument, untitled without path but language ID', function () { return vscode.workspace.openTextDocument({ language: 'xml' }).then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); - assert.equal(doc.languageId, 'xml'); + assert.strictEqual(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.languageId, 'xml'); assert.ok(doc.isDirty); }); }); test('openTextDocument, untitled without path but language ID and content', function () { return vscode.workspace.openTextDocument({ language: 'html', content: '

Hello world!

' }).then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); - assert.equal(doc.languageId, 'html'); + assert.strictEqual(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.languageId, 'html'); assert.ok(doc.isDirty); - assert.equal(doc.getText(), '

Hello world!

'); + assert.strictEqual(doc.getText(), '

Hello world!

'); }); }); @@ -128,7 +128,7 @@ suite('vscode API - workspace', () => { const path = join(vscode.workspace.rootPath || '', './newfile.txt'); return vscode.workspace.openTextDocument(vscode.Uri.parse('untitled:' + path)).then(doc => { - assert.equal(doc.uri.scheme, 'untitled'); + assert.strictEqual(doc.uri.scheme, 'untitled'); assert.ok(doc.isDirty); let closed: vscode.TextDocument; @@ -137,7 +137,7 @@ suite('vscode API - workspace', () => { return vscode.window.showTextDocument(doc).then(() => { return doc.save().then((didSave: boolean) => { - assert.equal(didSave, true, `FAILED to save${doc.uri.toString()}`); + assert.strictEqual(didSave, true, `FAILED to save${doc.uri.toString()}`); assert.ok(closed === doc); assert.ok(!doc.isDirty); @@ -161,16 +161,16 @@ suite('vscode API - workspace', () => { return Promise.all([ vscode.workspace.openTextDocument(vscode.Uri.parse('sc://auth')).then(doc => { - assert.equal(doc.uri.authority, 'auth'); - assert.equal(doc.uri.path, ''); + assert.strictEqual(doc.uri.authority, 'auth'); + assert.strictEqual(doc.uri.path, ''); }), vscode.workspace.openTextDocument(vscode.Uri.parse('sc:///path')).then(doc => { - assert.equal(doc.uri.authority, ''); - assert.equal(doc.uri.path, '/path'); + assert.strictEqual(doc.uri.authority, ''); + assert.strictEqual(doc.uri.path, '/path'); }), vscode.workspace.openTextDocument(vscode.Uri.parse('sc://auth/path')).then(doc => { - assert.equal(doc.uri.authority, 'auth'); - assert.equal(doc.uri.path, '/path'); + assert.strictEqual(doc.uri.authority, 'auth'); + assert.strictEqual(doc.uri.path, '/path'); }) ]).then(() => { registration.dispose(); @@ -192,21 +192,21 @@ suite('vscode API - workspace', () => { // lower case (actual case) comes first let docOne = await vscode.workspace.openTextDocument(uriOne); - assert.equal(docOne.uri.toString(), uriOne.toString()); + assert.strictEqual(docOne.uri.toString(), uriOne.toString()); let docONE = await vscode.workspace.openTextDocument(uriONE); - assert.equal(docONE === docOne, true); - assert.equal(docONE.uri.toString(), uriOne.toString()); - assert.equal(docONE.uri.toString() !== uriONE.toString(), true); // yep + assert.strictEqual(docONE === docOne, true); + assert.strictEqual(docONE.uri.toString(), uriOne.toString()); + assert.strictEqual(docONE.uri.toString() !== uriONE.toString(), true); // yep // upper case (NOT the actual case) comes first let docTWO = await vscode.workspace.openTextDocument(uriTWO); - assert.equal(docTWO.uri.toString(), uriTWO.toString()); + assert.strictEqual(docTWO.uri.toString(), uriTWO.toString()); let docTwo = await vscode.workspace.openTextDocument(uriTwo); - assert.equal(docTWO === docTwo, true); - assert.equal(docTwo.uri.toString(), uriTWO.toString()); - assert.equal(docTwo.uri.toString() !== uriTwo.toString(), true); // yep + assert.strictEqual(docTWO === docTwo, true); + assert.strictEqual(docTwo.uri.toString(), uriTWO.toString()); + assert.strictEqual(docTwo.uri.toString() !== uriTwo.toString(), true); // yep reg.dispose(); }); @@ -214,17 +214,17 @@ suite('vscode API - workspace', () => { test('eol, read', () => { const a = createRandomFile('foo\nbar\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { - assert.equal(doc.eol, vscode.EndOfLine.LF); + assert.strictEqual(doc.eol, vscode.EndOfLine.LF); }); }); const b = createRandomFile('foo\nbar\nbar\r\nbaz').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { - assert.equal(doc.eol, vscode.EndOfLine.LF); + assert.strictEqual(doc.eol, vscode.EndOfLine.LF); }); }); const c = createRandomFile('foo\r\nbar\r\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { - assert.equal(doc.eol, vscode.EndOfLine.CRLF); + assert.strictEqual(doc.eol, vscode.EndOfLine.CRLF); }); }); return Promise.all([a, b, c]); @@ -233,14 +233,14 @@ suite('vscode API - workspace', () => { test('eol, change via editor', () => { return createRandomFile('foo\nbar\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { - assert.equal(doc.eol, vscode.EndOfLine.LF); + assert.strictEqual(doc.eol, vscode.EndOfLine.LF); return vscode.window.showTextDocument(doc).then(editor => { return editor.edit(builder => builder.setEndOfLine(vscode.EndOfLine.CRLF)); }).then(value => { assert.ok(value); assert.ok(doc.isDirty); - assert.equal(doc.eol, vscode.EndOfLine.CRLF); + assert.strictEqual(doc.eol, vscode.EndOfLine.CRLF); }); }); }); @@ -249,14 +249,14 @@ suite('vscode API - workspace', () => { test('eol, change via applyEdit', () => { return createRandomFile('foo\nbar\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { - assert.equal(doc.eol, vscode.EndOfLine.LF); + assert.strictEqual(doc.eol, vscode.EndOfLine.LF); const edit = new vscode.WorkspaceEdit(); edit.set(file, [vscode.TextEdit.setEndOfLine(vscode.EndOfLine.CRLF)]); return vscode.workspace.applyEdit(edit).then(value => { assert.ok(value); assert.ok(doc.isDirty); - assert.equal(doc.eol, vscode.EndOfLine.CRLF); + assert.strictEqual(doc.eol, vscode.EndOfLine.CRLF); }); }); }); @@ -271,7 +271,7 @@ suite('vscode API - workspace', () => { const file = await createRandomFile('foo\r\nbar\r\nbar'); const doc = await vscode.workspace.openTextDocument(file); - assert.equal(doc.eol, vscode.EndOfLine.CRLF); + assert.strictEqual(doc.eol, vscode.EndOfLine.CRLF); const edit = new vscode.WorkspaceEdit(); edit.set(file, [vscode.TextEdit.insert(new vscode.Position(0, 0), '-changes-')]); @@ -282,7 +282,7 @@ suite('vscode API - workspace', () => { assert.ok(successSave); assert.ok(called); assert.ok(!doc.isDirty); - assert.equal(doc.eol, vscode.EndOfLine.LF); + assert.strictEqual(doc.eol, vscode.EndOfLine.LF); sub.dispose(); }); @@ -358,10 +358,10 @@ suite('vscode API - workspace', () => { return createRandomFile('foo\nbar\nbar').then(file => { return vscode.workspace.openTextDocument(file).then(doc => { return vscode.window.showTextDocument(doc, { selection: new vscode.Range(new vscode.Position(1, 1), new vscode.Position(1, 2)) }).then(editor => { - assert.equal(editor.selection.start.line, 1); - assert.equal(editor.selection.start.character, 1); - assert.equal(editor.selection.end.line, 1); - assert.equal(editor.selection.end.character, 2); + assert.strictEqual(editor.selection.start.line, 1); + assert.strictEqual(editor.selection.start.character, 1); + assert.strictEqual(editor.selection.end.line, 1); + assert.strictEqual(editor.selection.end.character, 2); }); }); }); @@ -377,9 +377,9 @@ suite('vscode API - workspace', () => { const uri = vscode.Uri.parse('foo://testing/virtual.js'); return vscode.workspace.openTextDocument(uri).then(doc => { - assert.equal(doc.getText(), uri.toString()); - assert.equal(doc.isDirty, false); - assert.equal(doc.uri.toString(), uri.toString()); + assert.strictEqual(doc.getText(), uri.toString()); + assert.strictEqual(doc.isDirty, false); + assert.strictEqual(doc.uri.toString(), uri.toString()); registration.dispose(); }); }); @@ -424,8 +424,8 @@ suite('vscode API - workspace', () => { }); return Promise.all([ - vscode.workspace.openTextDocument(vscode.Uri.parse('foo://foo/bla')).then(doc => { assert.equal(doc.getText(), '1'); }), - vscode.workspace.openTextDocument(vscode.Uri.parse('foo://bar/bla')).then(doc => { assert.equal(doc.getText(), '2'); }) + vscode.workspace.openTextDocument(vscode.Uri.parse('foo://foo/bla')).then(doc => { assert.strictEqual(doc.getText(), '1'); }), + vscode.workspace.openTextDocument(vscode.Uri.parse('foo://bar/bla')).then(doc => { assert.strictEqual(doc.getText(), '2'); }) ]).then(() => { registration1.dispose(); registration2.dispose(); @@ -447,7 +447,7 @@ suite('vscode API - workspace', () => { }); return vscode.workspace.openTextDocument(vscode.Uri.parse('foo://foo/bla')).then(doc => { - assert.equal(doc.getText(), '1'); + assert.strictEqual(doc.getText(), '1'); registration1.dispose(); registration2.dispose(); }); @@ -480,7 +480,7 @@ suite('vscode API - workspace', () => { return vscode.window.showTextDocument(doc).then(editor => { assert.ok(editor.document === doc); - assert.equal(editor.document.getText(), 'I am virtual'); + assert.strictEqual(editor.document.getText(), 'I am virtual'); registration.dispose(); }); }); @@ -502,7 +502,7 @@ suite('vscode API - workspace', () => { let [first, second] = docs; assert.ok(first === second); assert.ok(vscode.workspace.textDocuments.some(doc => doc.uri.toString() === uri.toString())); - assert.equal(callCount, 1); + assert.strictEqual(callCount, 1); registration.dispose(); }); }); @@ -518,8 +518,8 @@ suite('vscode API - workspace', () => { const uri = vscode.Uri.parse('foo:doc/empty'); return vscode.workspace.openTextDocument(uri).then(doc => { - assert.equal(doc.getText(), ''); - assert.equal(doc.uri.toString(), uri.toString()); + assert.strictEqual(doc.getText(), ''); + assert.strictEqual(doc.uri.toString(), uri.toString()); registration.dispose(); }); }); @@ -539,14 +539,14 @@ suite('vscode API - workspace', () => { const uri = vscode.Uri.parse('foo://testing/path3'); const doc = await vscode.workspace.openTextDocument(uri); - assert.equal(callCount, 1); - assert.equal(doc.getText(), 'call0'); + assert.strictEqual(callCount, 1); + assert.strictEqual(doc.getText(), 'call0'); return new Promise(resolve => { let subscription = vscode.workspace.onDidChangeTextDocument(event => { assert.ok(event.document === doc); - assert.equal(event.document.getText(), 'call1'); + assert.strictEqual(event.document.getText(), 'call1'); subscription.dispose(); registration.dispose(); resolve(); @@ -558,36 +558,36 @@ suite('vscode API - workspace', () => { test('findFiles', () => { return vscode.workspace.findFiles('**/image.png').then((res) => { - assert.equal(res.length, 2); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + assert.strictEqual(res.length, 2); + assert.strictEqual(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); }); }); test('findFiles - null exclude', async () => { await vscode.workspace.findFiles('**/file.txt').then((res) => { // search.exclude folder is still searched, files.exclude folder is not - assert.equal(res.length, 1); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); + assert.strictEqual(res.length, 1); + assert.strictEqual(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); }); await vscode.workspace.findFiles('**/file.txt', null).then((res) => { // search.exclude and files.exclude folders are both searched - assert.equal(res.length, 2); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); + assert.strictEqual(res.length, 2); + assert.strictEqual(basename(vscode.workspace.asRelativePath(res[0])), 'file.txt'); }); }); test('findFiles - exclude', () => { return vscode.workspace.findFiles('**/image.png').then((res) => { - assert.equal(res.length, 2); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + assert.strictEqual(res.length, 2); + assert.strictEqual(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); }); }); test('findFiles, exclude', () => { return vscode.workspace.findFiles('**/image.png', '**/sub/**').then((res) => { - assert.equal(res.length, 1); - assert.equal(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); + assert.strictEqual(res.length, 1); + assert.strictEqual(basename(vscode.workspace.asRelativePath(res[0])), 'image.png'); }); }); @@ -598,7 +598,7 @@ suite('vscode API - workspace', () => { source.cancel(); return vscode.workspace.findFiles('*.js', null, 100, token).then((res) => { - assert.deepEqual(res, []); + assert.deepStrictEqual(res, []); }); }); @@ -616,10 +616,10 @@ suite('vscode API - workspace', () => { results.push(result); }); - assert.equal(results.length, 1); + assert.strictEqual(results.length, 1); const match = results[0]; assert(match.preview.text.indexOf('foo') >= 0); - assert.equal(basename(vscode.workspace.asRelativePath(match.uri)), '10linefile.ts'); + assert.strictEqual(basename(vscode.workspace.asRelativePath(match.uri)), '10linefile.ts'); }); test('findTextInFiles, cancellation', async () => { @@ -639,8 +639,8 @@ suite('vscode API - workspace', () => { edit.insert(doc.uri, new vscode.Position(0, 0), new Array(1000).join('Hello World')); let success = await vscode.workspace.applyEdit(edit); - assert.equal(success, true); - assert.equal(doc.isDirty, true); + assert.strictEqual(success, true); + assert.strictEqual(doc.isDirty, true); }); test('applyEdit should fail when editing deleted resource', withLogDisabled(async () => { @@ -651,7 +651,7 @@ suite('vscode API - workspace', () => { edit.insert(resource, new vscode.Position(0, 0), ''); let success = await vscode.workspace.applyEdit(edit); - assert.equal(success, false); + assert.strictEqual(success, false); })); test('applyEdit should fail when renaming deleted resource', withLogDisabled(async () => { @@ -662,7 +662,7 @@ suite('vscode API - workspace', () => { edit.renameFile(resource, resource); let success = await vscode.workspace.applyEdit(edit); - assert.equal(success, false); + assert.strictEqual(success, false); })); test('applyEdit should fail when editing renamed from resource', withLogDisabled(async () => { @@ -673,7 +673,7 @@ suite('vscode API - workspace', () => { edit.insert(resource, new vscode.Position(0, 0), ''); let success = await vscode.workspace.applyEdit(edit); - assert.equal(success, false); + assert.strictEqual(success, false); })); test('applyEdit "edit A -> rename A to B -> edit B"', async () => { @@ -699,8 +699,8 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(edit)); let doc = await vscode.workspace.openTextDocument(newUri); - assert.equal(doc.getText(), 'AFTERBEFORE'); - assert.equal(doc.isDirty, true); + assert.strictEqual(doc.getText(), 'AFTERBEFORE'); + assert.strictEqual(doc.isDirty, true); } function nameWithUnderscore(uri: vscode.Uri) { @@ -719,7 +719,7 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(we)); let doc = await vscode.workspace.openTextDocument(newUri); - assert.equal(doc.getText(), 'BarHelloFoo'); + assert.strictEqual(doc.getText(), 'BarHelloFoo'); })); test('WorkspaceEdit: Problem recreating a renamed resource #42634', withLogDisabled(async function () { @@ -737,9 +737,9 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(we)); let newDoc = await vscode.workspace.openTextDocument(newUri); - assert.equal(newDoc.getText(), 'HelloFoo'); + assert.strictEqual(newDoc.getText(), 'HelloFoo'); let doc = await vscode.workspace.openTextDocument(docUri); - assert.equal(doc.getText(), 'Bar'); + assert.strictEqual(doc.getText(), 'Bar'); })); test('WorkspaceEdit api - after saving a deleted file, it still shows up as deleted. #42667', withLogDisabled(async function () { @@ -783,7 +783,7 @@ suite('vscode API - workspace', () => { let doc = await vscode.workspace.openTextDocument(newUri); assert.ok(doc); - assert.equal(doc.getText(), 'Hello'); + assert.strictEqual(doc.getText(), 'Hello'); }); test('WorkspaceEdit: rename resource followed by edit does not work #42638', withLogDisabled(async function () { @@ -797,7 +797,7 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(we)); let doc = await vscode.workspace.openTextDocument(newUri); - assert.equal(doc.getText(), 'Hello'); + assert.strictEqual(doc.getText(), 'Hello'); })); test('WorkspaceEdit: create & override', withLogDisabled(async function () { @@ -807,12 +807,12 @@ suite('vscode API - workspace', () => { let we = new vscode.WorkspaceEdit(); we.createFile(docUri); assert.ok(!await vscode.workspace.applyEdit(we)); - assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), 'before'); + assert.strictEqual((await vscode.workspace.openTextDocument(docUri)).getText(), 'before'); we = new vscode.WorkspaceEdit(); we.createFile(docUri, { overwrite: true }); assert.ok(await vscode.workspace.applyEdit(we)); - assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), ''); + assert.strictEqual((await vscode.workspace.openTextDocument(docUri)).getText(), ''); })); test('WorkspaceEdit: create & ignoreIfExists', withLogDisabled(async function () { @@ -821,12 +821,12 @@ suite('vscode API - workspace', () => { let we = new vscode.WorkspaceEdit(); we.createFile(docUri, { ignoreIfExists: true }); assert.ok(await vscode.workspace.applyEdit(we)); - assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), 'before'); + assert.strictEqual((await vscode.workspace.openTextDocument(docUri)).getText(), 'before'); we = new vscode.WorkspaceEdit(); we.createFile(docUri, { overwrite: true, ignoreIfExists: true }); assert.ok(await vscode.workspace.applyEdit(we)); - assert.equal((await vscode.workspace.openTextDocument(docUri)).getText(), ''); + assert.strictEqual((await vscode.workspace.openTextDocument(docUri)).getText(), ''); })); test('WorkspaceEdit: rename & ignoreIfExists', withLogDisabled(async function () { @@ -880,9 +880,9 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(we)); - assert.equal((await vscode.workspace.openTextDocument(f3)).getText(), 'f3'); - assert.equal((await vscode.workspace.openTextDocument(f2)).getText(), 'f2'); - assert.equal((await vscode.workspace.openTextDocument(f1_)).getText(), 'f1'); + assert.strictEqual((await vscode.workspace.openTextDocument(f3)).getText(), 'f3'); + assert.strictEqual((await vscode.workspace.openTextDocument(f2)).getText(), 'f2'); + assert.strictEqual((await vscode.workspace.openTextDocument(f1_)).getText(), 'f1'); try { await vscode.workspace.fs.stat(f1); assert.ok(false); @@ -932,12 +932,12 @@ suite('vscode API - workspace', () => { assert.ok(await vscode.workspace.applyEdit(we)); const document = await vscode.workspace.openTextDocument(newUri); - assert.equal(document.isDirty, true); + assert.strictEqual(document.isDirty, true); await document.save(); - assert.equal(document.isDirty, false); + assert.strictEqual(document.isDirty, false); - assert.equal(document.getText(), expected); + assert.strictEqual(document.getText(), expected); await delay(10); } @@ -959,7 +959,7 @@ suite('vscode API - workspace', () => { const document = await vscode.workspace.openTextDocument(file1); // const expected = 'import1;import2;'; const expected2 = 'import2;import1;'; - assert.equal(document.getText(), expected2); + assert.strictEqual(document.getText(), expected2); }); test('The api workspace.applyEdit failed for some case of mixing resourceChange and textEdit #80688', async function () { @@ -978,7 +978,7 @@ suite('vscode API - workspace', () => { const document = await vscode.workspace.openTextDocument(file1); const expected = 'import1;import2;'; // const expected2 = 'import2;import1;'; - assert.equal(document.getText(), expected); + assert.strictEqual(document.getText(), expected); }); test('Should send a single FileWillRenameEvent instead of separate events when moving multiple files at once#111867', async function () { @@ -1073,8 +1073,8 @@ suite('vscode API - workspace', () => { { const document = await vscode.workspace.openTextDocument(newFile); await vscode.window.showTextDocument(document); - assert.equal(document.getText(), 'hello2'); - assert.equal(document.isDirty, true); + assert.strictEqual(document.getText(), 'hello2'); + assert.strictEqual(document.isDirty, true); } // undo and show the old document @@ -1082,7 +1082,7 @@ suite('vscode API - workspace', () => { await vscode.commands.executeCommand('undo'); const document = await vscode.workspace.openTextDocument(file); await vscode.window.showTextDocument(document); - assert.equal(document.getText(), 'hello'); + assert.strictEqual(document.getText(), 'hello'); } // redo and show the new document @@ -1090,8 +1090,8 @@ suite('vscode API - workspace', () => { await vscode.commands.executeCommand('redo'); const document = await vscode.workspace.openTextDocument(newFile); await vscode.window.showTextDocument(document); - assert.equal(document.getText(), 'hello2'); - assert.equal(document.isDirty, true); + assert.strictEqual(document.getText(), 'hello2'); + assert.strictEqual(document.isDirty, true); } }); @@ -1111,8 +1111,8 @@ suite('vscode API - workspace', () => { // check the document { - assert.equal(document.getText(), 'hello2\nworld'); - assert.equal(document.isDirty, true); + assert.strictEqual(document.getText(), 'hello2\nworld'); + assert.strictEqual(document.isDirty, true); } // apply no-op edit @@ -1125,8 +1125,8 @@ suite('vscode API - workspace', () => { // undo { await vscode.commands.executeCommand('undo'); - assert.equal(document.getText(), 'hello\nworld'); - assert.equal(document.isDirty, false); + assert.strictEqual(document.getText(), 'hello\nworld'); + assert.strictEqual(document.isDirty, false); } }); }); diff --git a/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts index 1b4ef88325a..5721e1ddf1b 100644 --- a/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts +++ b/extensions/vscode-api-tests/src/workspace-tests/workspace.test.ts @@ -21,7 +21,7 @@ suite('vscode API - workspace', () => { }); test('workspaceFolders', () => { - assert.equal(vscode.workspace.workspaceFolders!.length, 2); + assert.strictEqual(vscode.workspace.workspaceFolders!.length, 2); assert.ok(pathEquals(vscode.workspace.workspaceFolders![0].uri.fsPath, join(__dirname, '../../testWorkspace'))); assert.ok(pathEquals(vscode.workspace.workspaceFolders![1].uri.fsPath, join(__dirname, '../../testWorkspace2'))); assert.ok(pathEquals(vscode.workspace.workspaceFolders![1].name, 'Test Workspace 2')); diff --git a/extensions/vscode-api-tests/yarn.lock b/extensions/vscode-api-tests/yarn.lock index 0e3ca71c654..b54d6b48836 100644 --- a/extensions/vscode-api-tests/yarn.lock +++ b/extensions/vscode-api-tests/yarn.lock @@ -7,7 +7,7 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.2.0.tgz#3eb56d13a1de1d347ecb1957c6860c911704bc44" integrity sha512-/Sge3BymXo4lKc31C8OINJgXLaw+7vL1/L1pGiBNpGrBiT8FQiaFpSYV0uhTaG4y78vcMBTMFsWaHDvuD+xGzQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== diff --git a/extensions/vscode-colorize-tests/package.json b/extensions/vscode-colorize-tests/package.json index 0ec286b3385..b2ce2e9d9cf 100644 --- a/extensions/vscode-colorize-tests/package.json +++ b/extensions/vscode-colorize-tests/package.json @@ -21,7 +21,7 @@ "jsonc-parser": "2.2.1" }, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "contributes": { "semanticTokenTypes": [ diff --git a/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json b/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json index eb76b0e1d04..399fd0c2208 100644 --- a/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json +++ b/extensions/vscode-colorize-tests/test/colorize-results/test_bat.json @@ -100,13 +100,13 @@ }, { "c": "%", - "t": "source.batchfile punctuation.definition.variable.batchfile", + "t": "source.batchfile variable.parameter.batchfile punctuation.definition.variable.batchfile", "r": { - "dark_plus": "default: #D4D4D4", - "light_plus": "default: #000000", + "dark_plus": "variable: #9CDCFE", + "light_plus": "variable: #001080", "dark_vs": "default: #D4D4D4", "light_vs": "default: #000000", - "hc_black": "default: #FFFFFF" + "hc_black": "variable: #9CDCFE" } }, { diff --git a/extensions/vscode-colorize-tests/yarn.lock b/extensions/vscode-colorize-tests/yarn.lock index a02d1775928..15725cff502 100644 --- a/extensions/vscode-colorize-tests/yarn.lock +++ b/extensions/vscode-colorize-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== jsonc-parser@2.2.1: version "2.2.1" diff --git a/extensions/vscode-custom-editor-tests/package.json b/extensions/vscode-custom-editor-tests/package.json index c718e324bc9..997c3a94da6 100644 --- a/extensions/vscode-custom-editor-tests/package.json +++ b/extensions/vscode-custom-editor-tests/package.json @@ -22,7 +22,7 @@ "p-limit": "^3.0.2" }, "devDependencies": { - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/p-limit": "^2.2.0" }, "contributes": { diff --git a/extensions/vscode-custom-editor-tests/src/test/customEditor.test.ts b/extensions/vscode-custom-editor-tests/src/test/customEditor.test.ts index b4725c22de3..654afb84cd7 100644 --- a/extensions/vscode-custom-editor-tests/src/test/customEditor.test.ts +++ b/extensions/vscode-custom-editor-tests/src/test/customEditor.test.ts @@ -92,7 +92,7 @@ suite('CustomEditor tests', () => { await vscode.commands.executeCommand(commands.open, testDocument); const { content } = await listener.nextResponse(); - assert.equal(content, startingContent); + assert.strictEqual(content, startingContent); }); test('Should support basic edits', async () => { @@ -107,7 +107,7 @@ suite('CustomEditor tests', () => { const newContent = `basic edit test`; await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, newContent); const { content } = await listener.nextResponse(); - assert.equal(content, newContent); + assert.strictEqual(content, newContent); }); test('Should support single undo', async () => { @@ -123,13 +123,13 @@ suite('CustomEditor tests', () => { { await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, newContent); const { content } = await listener.nextResponse(); - assert.equal(content, newContent); + assert.strictEqual(content, newContent); } await delay(100); { await vscode.commands.executeCommand(commands.undo); const { content } = await listener.nextResponse(); - assert.equal(content, startingContent); + assert.strictEqual(content, startingContent); } }); @@ -148,7 +148,7 @@ suite('CustomEditor tests', () => { for (let i = 0; i < count; ++i) { await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, `${i}`); const { content } = await listener.nextResponse(); - assert.equal(`${i}`, content); + assert.strictEqual(`${i}`, content); } // Then undo them in order @@ -156,14 +156,14 @@ suite('CustomEditor tests', () => { await delay(100); await vscode.commands.executeCommand(commands.undo); const { content } = await listener.nextResponse(); - assert.equal(`${i - 1}`, content); + assert.strictEqual(`${i - 1}`, content); } { await delay(100); await vscode.commands.executeCommand(commands.undo); const { content } = await listener.nextResponse(); - assert.equal(content, startingContent); + assert.strictEqual(content, startingContent); } }); @@ -184,8 +184,8 @@ suite('CustomEditor tests', () => { await vscode.workspace.applyEdit(edit); const response = (await listener.nextResponse()); - assert.equal(response.content, startingContent); - assert.equal(response.source.toString(), newFileName.toString()); + assert.strictEqual(response.content, startingContent); + assert.strictEqual(response.source.toString(), newFileName.toString()); }); test('Should support saving custom editors', async () => { @@ -201,12 +201,12 @@ suite('CustomEditor tests', () => { { await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, newContent); const { content } = await listener.nextResponse(); - assert.equal(content, newContent); + assert.strictEqual(content, newContent); } { await vscode.commands.executeCommand(commands.save); const fileContent = (await fs.promises.readFile(testDocument.fsPath)).toString(); - assert.equal(fileContent, newContent); + assert.strictEqual(fileContent, newContent); } }); @@ -223,18 +223,18 @@ suite('CustomEditor tests', () => { { await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, newContent); const { content } = await listener.nextResponse(); - assert.equal(content, newContent); + assert.strictEqual(content, newContent); } { await vscode.commands.executeCommand(commands.save); const fileContent = (await fs.promises.readFile(testDocument.fsPath)).toString(); - assert.equal(fileContent, newContent); + assert.strictEqual(fileContent, newContent); } await delay(100); { await vscode.commands.executeCommand(commands.undo); const { content } = await listener.nextResponse(); - assert.equal(content, startingContent); + assert.strictEqual(content, startingContent); } }); @@ -244,14 +244,14 @@ suite('CustomEditor tests', () => { const untitledFile = randomFilePath({ root: testWorkspaceRoot, ext: '.abc' }).with({ scheme: 'untitled' }); await vscode.commands.executeCommand(commands.open, untitledFile); - assert.equal((await listener.nextResponse()).content, ''); + assert.strictEqual((await listener.nextResponse()).content, ''); await vscode.commands.executeCommand(Testing.abcEditorTypeCommand, `123`); - assert.equal((await listener.nextResponse()).content, '123'); + assert.strictEqual((await listener.nextResponse()).content, '123'); await vscode.commands.executeCommand(commands.save); const content = await fs.promises.readFile(untitledFile.fsPath); - assert.equal(content.toString(), '123'); + assert.strictEqual(content.toString(), '123'); }); test.skip('When switching away from a non-default custom editors and then back, we should continue using the non-default editor', async () => { diff --git a/extensions/vscode-custom-editor-tests/yarn.lock b/extensions/vscode-custom-editor-tests/yarn.lock index 29a81a09a49..76cc46da4b7 100644 --- a/extensions/vscode-custom-editor-tests/yarn.lock +++ b/extensions/vscode-custom-editor-tests/yarn.lock @@ -2,10 +2,10 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/p-limit@^2.2.0": version "2.2.0" diff --git a/extensions/vscode-notebook-tests/package.json b/extensions/vscode-notebook-tests/package.json index f1bdd988bee..c43a17911d1 100644 --- a/extensions/vscode-notebook-tests/package.json +++ b/extensions/vscode-notebook-tests/package.json @@ -20,7 +20,7 @@ }, "dependencies": {}, "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "contributes": { "commands": [ diff --git a/extensions/vscode-notebook-tests/yarn.lock b/extensions/vscode-notebook-tests/yarn.lock index e03bdd573ea..995b2c2f8b3 100644 --- a/extensions/vscode-notebook-tests/yarn.lock +++ b/extensions/vscode-notebook-tests/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== diff --git a/extensions/vscode-test-resolver/package.json b/extensions/vscode-test-resolver/package.json index 2256c047359..ccbf98c25b8 100644 --- a/extensions/vscode-test-resolver/package.json +++ b/extensions/vscode-test-resolver/package.json @@ -27,7 +27,7 @@ ], "main": "./out/extension", "devDependencies": { - "@types/node": "^12.19.9" + "@types/node": "14.x" }, "contributes": { "resourceLabelFormatters": [ diff --git a/extensions/vscode-test-resolver/yarn.lock b/extensions/vscode-test-resolver/yarn.lock index e03bdd573ea..995b2c2f8b3 100644 --- a/extensions/vscode-test-resolver/yarn.lock +++ b/extensions/vscode-test-resolver/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== diff --git a/package.json b/package.json index 89e90e9cf8f..1956b94ed17 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "code-oss-dev", "version": "1.57.0", - "distro": "f2ce80c1b46a963b719486003a0f17cf678add41", + "distro": "295947422e138a150d3fe7de5c2347039fea9540", "author": { "name": "Microsoft Corporation" }, @@ -105,7 +105,7 @@ "@types/keytar": "^4.4.0", "@types/minimist": "^1.2.1", "@types/mocha": "^8.2.0", - "@types/node": "^14.14.37", + "@types/node": "14.x", "@types/sinon": "^1.16.36", "@types/trusted-types": "^1.0.6", "@types/vscode-windows-registry": "^1.0.0", diff --git a/resources/linux/code-url-handler.desktop b/resources/linux/code-url-handler.desktop index b85525fbd04..7106e0e0969 100644 --- a/resources/linux/code-url-handler.desktop +++ b/resources/linux/code-url-handler.desktop @@ -2,7 +2,7 @@ Name=@@NAME_LONG@@ - URL Handler Comment=Code Editing. Redefined. GenericName=Text Editor -Exec=@@EXEC@@ --no-sandbox --open-url %U +Exec=@@EXEC@@ --open-url %U Icon=@@ICON@@ Type=Application NoDisplay=true diff --git a/resources/linux/code.desktop b/resources/linux/code.desktop index 62d6bfc47b4..ab3b79a011b 100755 --- a/resources/linux/code.desktop +++ b/resources/linux/code.desktop @@ -2,7 +2,7 @@ Name=@@NAME_LONG@@ Comment=Code Editing. Redefined. GenericName=Text Editor -Exec=@@EXEC@@ --no-sandbox --unity-launch %F +Exec=@@EXEC@@ --unity-launch %F Icon=@@ICON@@ Type=Application StartupNotify=false @@ -14,5 +14,5 @@ Keywords=vscode; [Desktop Action new-empty-window] Name=New Empty Window -Exec=@@EXEC@@ --no-sandbox --new-window %F +Exec=@@EXEC@@ --new-window %F Icon=@@ICON@@ diff --git a/scripts/code.sh b/scripts/code.sh index 3095f3897bf..713040b5a27 100755 --- a/scripts/code.sh +++ b/scripts/code.sh @@ -43,7 +43,7 @@ function code() { export ELECTRON_ENABLE_LOGGING=1 # Launch Code - exec "$CODE" . --no-sandbox "$@" + exec "$CODE" . "$@" } function code-wsl() diff --git a/scripts/test-integration.sh b/scripts/test-integration.sh index c6c116c2f67..0b2fe97b17d 100755 --- a/scripts/test-integration.sh +++ b/scripts/test-integration.sh @@ -6,8 +6,10 @@ if [[ "$OSTYPE" == "darwin"* ]]; then ROOT=$(dirname $(dirname $(realpath "$0"))) else ROOT=$(dirname $(dirname $(readlink -f $0))) - # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. - LINUX_EXTRA_ARGS="--no-sandbox" + # --disable-setuid-sandbox: setuid sandboxes requires root and is used in containers so we disable this + # --disable-dev-shm-usage --use-gl=swiftshader: when run on docker containers where size of /dev/shm + # partition < 64MB which causes OOM failure for chromium compositor that uses the partition for shared memory + LINUX_EXTRA_ARGS="--disable-setuid-sandbox --disable-dev-shm-usage --use-gl=swiftshader" fi VSCODEUSERDATADIR=`mktemp -d 2>/dev/null` @@ -44,13 +46,6 @@ else export ELECTRON_ENABLE_STACK_DUMPING=1 export ELECTRON_ENABLE_LOGGING=1 - # Production builds are run on docker containers where size of /dev/shm partition < 64MB which causes OOM failure - # for chromium compositor that uses the partition for shared memory - if [ "$LINUX_EXTRA_ARGS" ] - then - LINUX_EXTRA_ARGS="$LINUX_EXTRA_ARGS --disable-dev-shm-usage --use-gl=swiftshader" - fi - echo "Storing crash reports into '$VSCODECRASHDIR'." echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build." fi diff --git a/scripts/test.sh b/scripts/test.sh index 7594af3d976..68f75db60d8 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -6,8 +6,10 @@ if [[ "$OSTYPE" == "darwin"* ]]; then ROOT=$(dirname $(dirname $(realpath "$0"))) else ROOT=$(dirname $(dirname $(readlink -f $0))) - # Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox. - LINUX_EXTRA_ARGS="--no-sandbox --disable-dev-shm-usage --use-gl=swiftshader" + # --disable-setuid-sandbox: setuid sandboxes requires root and is used in containers so we disable this + # --disable-dev-shm-usage --use-gl=swiftshader: when run on docker containers where size of /dev/shm + # partition < 64MB which causes OOM failure for chromium compositor that uses the partition for shared memory + LINUX_EXTRA_ARGS="--disable-setuid-sandbox --disable-dev-shm-usage --use-gl=swiftshader" fi cd $ROOT diff --git a/src/vs/base/parts/quickinput/browser/quickInput.ts b/src/vs/base/parts/quickinput/browser/quickInput.ts index ae5d8b22987..2cb5092c901 100644 --- a/src/vs/base/parts/quickinput/browser/quickInput.ts +++ b/src/vs/base/parts/quickinput/browser/quickInput.ts @@ -473,8 +473,11 @@ class QuickPick extends QuickInput implements IQuickPi } set value(value: string) { - this._value = value || ''; - this.update(); + if (this._value !== value) { + this._value = value || ''; + this.update(); + this.onDidChangeValueEmitter.fire(this._value); + } } filterValue = (value: string) => value; diff --git a/src/vs/base/test/parts/quickinput/browser/quickinput.test.ts b/src/vs/base/test/parts/quickinput/browser/quickinput.test.ts new file mode 100644 index 00000000000..f74c90e013a --- /dev/null +++ b/src/vs/base/test/parts/quickinput/browser/quickinput.test.ts @@ -0,0 +1,75 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as assert from 'assert'; +import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list'; +import { List } from 'vs/base/browser/ui/list/listWidget'; +import { QuickInputController } from 'vs/base/parts/quickinput/browser/quickInput'; +import { IWorkbenchListOptions } from 'vs/platform/list/browser/listService'; + +// Simple promisify of setTimeout +function wait(delayMS: number) { + return new Promise(function (resolve) { + setTimeout(resolve, delayMS); + }); +} + +suite('QuickInput', () => { + let fixture: HTMLElement, controller: QuickInputController; + + setup(() => { + fixture = document.createElement('div'); + document.body.appendChild(fixture); + + controller = new QuickInputController({ + container: fixture, + idPrefix: 'testQuickInput', + ignoreFocusOut() { return false; }, + isScreenReaderOptimized() { return false; }, + returnFocus() { }, + backKeybindingLabel() { return undefined; }, + setContextKey() { return undefined; }, + createList: ( + user: string, + container: HTMLElement, + delegate: IListVirtualDelegate, + renderers: IListRenderer[], + options: IWorkbenchListOptions, + ) => new List(user, container, delegate, renderers, options), + styles: { + button: {}, + countBadge: {}, + inputBox: {}, + keybindingLabel: {}, + list: {}, + progressBar: {}, + widget: {} + } + }); + }); + + teardown(() => { + controller.dispose(); + document.body.removeChild(fixture); + }); + + test('onDidChangeValue gets triggered when .value is set', async () => { + const quickpick = controller.createQuickPick(); + + let value: string | undefined = undefined; + quickpick.onDidChangeValue((e) => value = e); + + // Trigger a change + quickpick.value = 'changed'; + + try { + // wait a bit to let the event play out. + await wait(200); + assert.strictEqual(value, quickpick.value); + } finally { + quickpick.dispose(); + } + }); +}); diff --git a/src/vs/code/node/cli.ts b/src/vs/code/node/cli.ts index 0ce6c5ee5be..834a2cfb120 100644 --- a/src/vs/code/node/cli.ts +++ b/src/vs/code/node/cli.ts @@ -14,7 +14,7 @@ import product from 'vs/platform/product/common/product'; import { isAbsolute, join } from 'vs/base/common/path'; import { whenDeleted, writeFileSync } from 'vs/base/node/pfs'; import { findFreePort, randomPort } from 'vs/base/node/ports'; -import { isWindows, isLinux, IProcessEnvironment } from 'vs/base/common/platform'; +import { isWindows, IProcessEnvironment } from 'vs/base/common/platform'; import type { ProfilingSession, Target } from 'v8-inspect-profiler'; import { isString } from 'vs/base/common/types'; import { hasStdinWithoutTty, stdinDataListener, getStdinFilePath, readFromStdin } from 'vs/platform/environment/node/stdin'; @@ -318,10 +318,6 @@ export async function main(argv: string[]): Promise { options['stdio'] = 'ignore'; } - if (isLinux) { - addArg(argv, '--no-sandbox'); // Electron 6 introduces a chrome-sandbox that requires root to run. This can fail. Disable sandbox via --no-sandbox - } - const child = spawn(process.execPath, argv.slice(2), options); if (args.wait && waitMarkerFilePath) { diff --git a/src/vs/editor/common/controller/cursorDeleteOperations.ts b/src/vs/editor/common/controller/cursorDeleteOperations.ts index 1d0fdd26576..6854a4e6386 100644 --- a/src/vs/editor/common/controller/cursorDeleteOperations.ts +++ b/src/vs/editor/common/controller/cursorDeleteOperations.ts @@ -12,6 +12,7 @@ import { Range } from 'vs/editor/common/core/range'; import { Selection } from 'vs/editor/common/core/selection'; import { ICommand } from 'vs/editor/common/editorCommon'; import { StandardAutoClosingPairConditional } from 'vs/editor/common/modes/languageConfiguration'; +import { Position } from 'vs/editor/common/core/position'; export class DeleteOperations { @@ -141,63 +142,70 @@ export class DeleteOperations { } public static deleteLeft(prevEditOperationType: EditOperationType, config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[], autoClosedCharacters: Range[]): [boolean, Array] { - if (this.isAutoClosingPairDelete(config.autoClosingDelete, config.autoClosingBrackets, config.autoClosingQuotes, config.autoClosingPairs.autoClosingPairsOpenByEnd, model, selections, autoClosedCharacters)) { return this._runAutoClosingPairDelete(config, model, selections); } - let commands: Array = []; + const commands: Array = []; let shouldPushStackElementBefore = (prevEditOperationType !== EditOperationType.DeletingLeft); for (let i = 0, len = selections.length; i < len; i++) { - const selection = selections[i]; + let deleteRange = DeleteOperations.getDeleteRange(selections[i], model, config); - let deleteSelection: Range = selection; - - if (deleteSelection.isEmpty()) { - let position = selection.getPosition(); - - if (config.useTabStops && position.column > 1) { - let lineContent = model.getLineContent(position.lineNumber); - - let firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent); - let lastIndentationColumn = ( - firstNonWhitespaceIndex === -1 - ? /* entire string is whitespace */lineContent.length + 1 - : firstNonWhitespaceIndex + 1 - ); - - if (position.column <= lastIndentationColumn) { - let fromVisibleColumn = CursorColumns.visibleColumnFromColumn2(config, model, position); - let toVisibleColumn = CursorColumns.prevIndentTabStop(fromVisibleColumn, config.indentSize); - let toColumn = CursorColumns.columnFromVisibleColumn2(config, model, position.lineNumber, toVisibleColumn); - deleteSelection = new Range(position.lineNumber, toColumn, position.lineNumber, position.column); - } else { - deleteSelection = new Range(position.lineNumber, position.column - 1, position.lineNumber, position.column); - } - } else { - let leftOfPosition = MoveOperations.left(config, model, position.lineNumber, position.column); - deleteSelection = new Range( - leftOfPosition.lineNumber, - leftOfPosition.column, - position.lineNumber, - position.column - ); - } - } - - if (deleteSelection.isEmpty()) { - // Probably at beginning of file => ignore + // Ignore empty delete ranges, as they have no effect + // They happen if the cursor is at the beginning of the file. + if (deleteRange.isEmpty()) { commands[i] = null; continue; } - if (deleteSelection.startLineNumber !== deleteSelection.endLineNumber) { + if (deleteRange.startLineNumber !== deleteRange.endLineNumber) { shouldPushStackElementBefore = true; } - commands[i] = new ReplaceCommand(deleteSelection, ''); + commands[i] = new ReplaceCommand(deleteRange, ''); } return [shouldPushStackElementBefore, commands]; + + } + + private static getDeleteRange(selection: Selection, model: ICursorSimpleModel, config: CursorConfiguration,): Range { + if (!selection.isEmpty()) { + return selection; + } + + const position = selection.getPosition(); + + // Unintend when using tab stops and cursor is within indentation + if (config.useTabStops && position.column > 1) { + const lineContent = model.getLineContent(position.lineNumber); + + const firstNonWhitespaceIndex = strings.firstNonWhitespaceIndex(lineContent); + const lastIndentationColumn = ( + firstNonWhitespaceIndex === -1 + ? /* entire string is whitespace */ lineContent.length + 1 + : firstNonWhitespaceIndex + 1 + ); + + if (position.column <= lastIndentationColumn) { + const fromVisibleColumn = CursorColumns.visibleColumnFromColumn2(config, model, position); + const toVisibleColumn = CursorColumns.prevIndentTabStop(fromVisibleColumn, config.indentSize); + const toColumn = CursorColumns.columnFromVisibleColumn2(config, model, position.lineNumber, toVisibleColumn); + return new Range(position.lineNumber, toColumn, position.lineNumber, position.column); + } + } + + return Range.fromPositions(DeleteOperations.decreasePositionInModelBy1Column(position, model) || position, position); + } + + private static decreasePositionInModelBy1Column(position: Position, model: ICursorSimpleModel): Position | undefined { + if (position.column > 1) { + return position.delta(0, -1); + } else if (position.lineNumber > 1) { + const newLine = position.lineNumber - 1; + return new Position(newLine, model.getLineMaxColumn(newLine)); + } else { + return undefined; + } } public static cut(config: CursorConfiguration, model: ICursorSimpleModel, selections: Selection[]): EditOperationResult { diff --git a/src/vs/editor/contrib/snippet/snippetParser.ts b/src/vs/editor/contrib/snippet/snippetParser.ts index 8986345e970..ab85481a3a8 100644 --- a/src/vs/editor/contrib/snippet/snippetParser.ts +++ b/src/vs/editor/contrib/snippet/snippetParser.ts @@ -388,11 +388,11 @@ export class FormatString extends Marker { } private _toPascalCase(value: string): string { - const match = value.match(/[a-z]+/gi); + const match = value.match(/[a-z0-9]+/gi); if (!match) { return value; } - return match.map(function (word) { + return match.map(word => { return word.charAt(0).toUpperCase() + word.substr(1).toLowerCase(); }) diff --git a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts index a9d41faf92f..21438244b86 100644 --- a/src/vs/editor/contrib/snippet/test/snippetParser.test.ts +++ b/src/vs/editor/contrib/snippet/test/snippetParser.test.ts @@ -655,6 +655,7 @@ suite('SnippetParser', () => { assert.strictEqual(new FormatString(1, 'capitalize').resolve('bar'), 'Bar'); assert.strictEqual(new FormatString(1, 'capitalize').resolve('bar no repeat'), 'Bar no repeat'); assert.strictEqual(new FormatString(1, 'pascalcase').resolve('bar-foo'), 'BarFoo'); + assert.strictEqual(new FormatString(1, 'pascalcase').resolve('bar-42-foo'), 'Bar42Foo'); assert.strictEqual(new FormatString(1, 'notKnown').resolve('input'), 'input'); // if diff --git a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts index a3763880de2..0eae1697985 100644 --- a/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts +++ b/src/vs/editor/contrib/suggest/suggestWidgetRenderer.ts @@ -209,13 +209,13 @@ export class ItemRenderer implements IListRenderer { model.dispose(); }); + + test('issue #122914: Left delete behavior in some languages is changed (useTabStops: false)', () => { + let model = createTextModel( + [ + 'สวัสดี' + ].join('\n') + ); + + withTestCodeEditor(null, { model: model, useTabStops: false }, (editor, viewModel) => { + editor.setSelections([ + new Selection(1, 7, 1, 7) + ]); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัสด'); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวัส'); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สวั'); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'สว'); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), 'ส'); + + CoreEditingCommands.DeleteLeft.runEditorCommand(null, editor, null); + assert.strictEqual(model.getValue(EndOfLinePreference.LF), ''); + }); + + model.dispose(); + }); }); suite('Editor Controller - Cursor Configuration', () => { diff --git a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts index 45d3b68c483..3d9ea6defaf 100644 --- a/src/vs/platform/extensionManagement/common/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/common/extensionGalleryService.ts @@ -358,13 +358,11 @@ function toExtension(galleryExtension: IRawGalleryExtension, version: IRawGaller /* __GDPR__FRAGMENT__ "GalleryExtensionTelemetryData2" : { "index" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, - "searchText": { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "querySource": { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ telemetryData: { index: ((query.pageNumber - 1) * query.pageSize) + index, - searchText: query.searchText, querySource }, preview: getIsPreview(galleryExtension.flags) diff --git a/src/vs/platform/externalTerminal/node/externalTerminalService.ts b/src/vs/platform/externalTerminal/node/externalTerminalService.ts index 9897e79a3b8..4d5ad0fc703 100644 --- a/src/vs/platform/externalTerminal/node/externalTerminalService.ts +++ b/src/vs/platform/externalTerminal/node/externalTerminalService.ts @@ -14,6 +14,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { optional } from 'vs/platform/instantiation/common/instantiation'; import { FileAccess } from 'vs/base/common/network'; import { ITerminalEnvironment } from 'vs/platform/terminal/common/terminal'; +import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; const TERMINAL_TITLE = nls.localize('console.title', "VS Code Console"); @@ -71,8 +72,8 @@ export class WindowsExternalTerminalService extends ExternalTerminalService impl } return new Promise((c, e) => { - const env = cwd ? { cwd: cwd } : undefined; - const child = spawner.spawn(command, cmdArgs, env); + const env = getSanitizedEnvironment(process); + const child = spawner.spawn(command, cmdArgs, { cwd, env }); child.on('error', e); child.on('exit', () => c()); }); @@ -91,7 +92,7 @@ export class WindowsExternalTerminalService extends ExternalTerminalService impl ]; // merge environment variables into a copy of the process.env - const env = Object.assign({}, process.env, envVars); + const env = Object.assign({}, getSanitizedEnvironment(process), envVars); // delete environment variables that have a null value Object.keys(env).filter(v => env[v] === null).forEach(key => delete env[key]); @@ -319,8 +320,8 @@ export class LinuxExternalTerminalService extends ExternalTerminalService implem return new Promise((c, e) => { execPromise.then(exec => { - const env = cwd ? { cwd } : undefined; - const child = spawner.spawn(exec, [], env); + const env = getSanitizedEnvironment(process); + const child = spawner.spawn(exec, [], { cwd, env }); child.on('error', e); child.on('exit', () => c()); }); @@ -328,6 +329,12 @@ export class LinuxExternalTerminalService extends ExternalTerminalService implem } } +function getSanitizedEnvironment(process: NodeJS.Process) { + const env = process.env; + sanitizeProcessEnvironment(env); + return env; +} + /** * tries to turn OS errors into more meaningful error messages */ diff --git a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts index 68fc5345562..e84a282762a 100644 --- a/src/vs/platform/quickinput/browser/commandsQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/commandsQuickAccess.ts @@ -55,7 +55,7 @@ export abstract class AbstractCommandsQuickAccessProvider extends PickerQuickAcc this.options = options; } - protected async getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { + protected async _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { // Ask subclass for all command picks const allCommandPicks = await this.getCommandPicks(disposables, token); diff --git a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts index eb1fe1be257..52db4d07881 100644 --- a/src/vs/platform/quickinput/browser/pickerQuickAccess.ts +++ b/src/vs/platform/quickinput/browser/pickerQuickAccess.ts @@ -122,7 +122,7 @@ export abstract class PickerQuickAccessProvider, skipEmpty?: boolean): boolean => { let items: readonly Pick[]; @@ -330,5 +330,5 @@ export abstract class PickerQuickAccessProvider | Promise> | FastAndSlowPicks | null; + protected abstract _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Picks | Promise> | FastAndSlowPicks | null; } diff --git a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts index 64168de41a6..f62912e56d1 100644 --- a/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts +++ b/src/vs/platform/sharedProcess/electron-main/sharedProcess.ts @@ -18,7 +18,6 @@ import { connect as connectMessagePort } from 'vs/base/parts/ipc/electron-main/i import { assertIsDefined } from 'vs/base/common/types'; import { Emitter, Event } from 'vs/base/common/event'; import { WindowError } from 'vs/platform/windows/electron-main/windows'; -import { resolveShellEnv } from 'vs/platform/environment/node/shellEnv'; import { IProtocolMainService } from 'vs/platform/protocol/electron-main/protocol'; export class SharedProcess extends Disposable implements ISharedProcess { @@ -139,9 +138,6 @@ export class SharedProcess extends Disposable implements ISharedProcess { // Always wait for first window asking for connection await this.firstWindowConnectionBarrier.wait(); - // Resolve shell environment - this.userEnv = { ...this.userEnv, ...(await resolveShellEnv(this.logService, this.environmentMainService.args, process.env)) }; - // Create window for shared process this.createWindow(); diff --git a/src/vs/platform/terminal/common/terminal.ts b/src/vs/platform/terminal/common/terminal.ts index 28a4c9b649f..59d7391c9e0 100644 --- a/src/vs/platform/terminal/common/terminal.ts +++ b/src/vs/platform/terminal/common/terminal.ts @@ -96,7 +96,8 @@ export interface IOffProcessTerminalService { attachToProcess(id: number): Promise; listProcesses(): Promise; getDefaultSystemShell(osOverride?: OperatingSystem): Promise; - getShellEnvironment(): Promise; + getWslPath(original: string): Promise; + getEnvironment(): Promise; setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise; getTerminalLayoutInfo(): Promise; reduceConnectionGraceTime(): Promise; @@ -161,7 +162,8 @@ export interface IPtyService { orphanQuestionReply(id: number): Promise; getDefaultSystemShell(osOverride?: OperatingSystem): Promise; - getShellEnvironment(): Promise; + getEnvironment(): Promise; + getWslPath(original: string): Promise; setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise; getTerminalLayoutInfo(args: IGetTerminalLayoutInfoArgs): Promise; reduceConnectionGraceTime(): Promise; diff --git a/src/vs/platform/terminal/common/terminalEnvironment.ts b/src/vs/platform/terminal/common/terminalEnvironment.ts new file mode 100644 index 00000000000..66b5ad31a3f --- /dev/null +++ b/src/vs/platform/terminal/common/terminalEnvironment.ts @@ -0,0 +1,14 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +export function escapeNonWindowsPath(path: string): string { + let newPath = path; + if (newPath.indexOf('\\') !== 0) { + newPath = newPath.replace(/\\/g, '\\\\'); + } + const bannedChars = /[\`\$\|\&\>\~\#\!\^\*\;\<\"\']/g; + newPath = newPath.replace(bannedChars, ''); + return `'${newPath}'`; +} diff --git a/src/vs/platform/terminal/common/terminalProcess.ts b/src/vs/platform/terminal/common/terminalProcess.ts index 6cdf3b88e17..2b0ea4ac642 100644 --- a/src/vs/platform/terminal/common/terminalProcess.ts +++ b/src/vs/platform/terminal/common/terminalProcess.ts @@ -26,7 +26,6 @@ export interface ICompleteTerminalConfiguration { 'terminal.integrated.env.windows': ISingleTerminalConfiguration; 'terminal.integrated.env.osx': ISingleTerminalConfiguration; 'terminal.integrated.env.linux': ISingleTerminalConfiguration; - 'terminal.integrated.inheritEnv': boolean; 'terminal.integrated.cwd': string; 'terminal.integrated.detectLocale': 'auto' | 'off' | 'on'; } diff --git a/src/vs/platform/terminal/common/terminalRecorder.ts b/src/vs/platform/terminal/common/terminalRecorder.ts index e8a6e17c366..68bd0f16fbc 100644 --- a/src/vs/platform/terminal/common/terminalRecorder.ts +++ b/src/vs/platform/terminal/common/terminalRecorder.ts @@ -26,7 +26,7 @@ export class TerminalRecorder { this._entries = [{ cols, rows, data: [] }]; } - public recordResize(cols: number, rows: number): void { + recordResize(cols: number, rows: number): void { if (this._entries.length > 0) { const lastEntry = this._entries[this._entries.length - 1]; if (lastEntry.data.length === 0) { @@ -52,7 +52,7 @@ export class TerminalRecorder { this._entries.push({ cols, rows, data: [] }); } - public recordData(data: string): void { + recordData(data: string): void { const lastEntry = this._entries[this._entries.length - 1]; lastEntry.data.push(data); @@ -76,7 +76,7 @@ export class TerminalRecorder { } } - public generateReplayEvent(): IPtyHostProcessReplayEvent { + generateReplayEvent(): IPtyHostProcessReplayEvent { // normalize entries to one element per data array this._entries.forEach((entry) => { if (entry.data.length > 0) { diff --git a/src/vs/platform/terminal/node/ptyHostService.ts b/src/vs/platform/terminal/node/ptyHostService.ts index fba6308c4ef..12cd6b1fc69 100644 --- a/src/vs/platform/terminal/node/ptyHostService.ts +++ b/src/vs/platform/terminal/node/ptyHostService.ts @@ -122,6 +122,7 @@ export class PtyHostService extends Disposable implements IPtyService { // Setup logging const logChannel = client.getChannel(TerminalIpcChannels.Log); + LogLevelChannelClient.setLevel(logChannel, this._logService.getLevel()); this._register(this._logService.onDidChangeLogLevel(() => { LogLevelChannelClient.setLevel(logChannel, this._logService.getLevel()); })); @@ -199,8 +200,11 @@ export class PtyHostService extends Disposable implements IPtyService { getDefaultSystemShell(osOverride?: OperatingSystem): Promise { return this._proxy.getDefaultSystemShell(osOverride); } - getShellEnvironment(): Promise { - return this._proxy.getShellEnvironment(); + getEnvironment(): Promise { + return this._proxy.getEnvironment(); + } + getWslPath(original: string): Promise { + return this._proxy.getWslPath(original); } setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise { diff --git a/src/vs/platform/terminal/node/ptyService.ts b/src/vs/platform/terminal/node/ptyService.ts index d9ea875c408..77e21a77185 100644 --- a/src/vs/platform/terminal/node/ptyService.ts +++ b/src/vs/platform/terminal/node/ptyService.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { Disposable, toDisposable } from 'vs/base/common/lifecycle'; -import { IProcessEnvironment, OperatingSystem, OS } from 'vs/base/common/platform'; +import { IProcessEnvironment, isWindows, OperatingSystem, OS } from 'vs/base/common/platform'; import { IPtyService, IProcessDataEvent, IShellLaunchConfig, ITerminalDimensionsOverride, ITerminalLaunchError, LocalReconnectConstants, ITerminalsLayoutInfo, IRawTerminalInstanceLayoutInfo, ITerminalTabLayoutInfoById, ITerminalInstanceLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; import { AutoOpenBarrier, Queue, RunOnceScheduler } from 'vs/base/common/async'; import { Emitter } from 'vs/base/common/event'; @@ -14,6 +14,9 @@ import { ISetTerminalLayoutInfoArgs, ITerminalTabLayoutInfoDto, IProcessDetails, import { ILogService } from 'vs/platform/log/common/log'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; import { getSystemShell } from 'vs/base/node/shell'; +import { getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; +import { execFile } from 'child_process'; +import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; type WorkspaceId = string; @@ -166,10 +169,25 @@ export class PtyService extends Disposable implements IPtyService { return getSystemShell(osOverride, process.env); } - async getShellEnvironment(): Promise { + async getEnvironment(): Promise { return { ...process.env }; } + async getWslPath(original: string): Promise { + if (!isWindows) { + return original; + } + if (getWindowsBuildNumber() < 17063) { + return original.replace(/\\/g, '/'); + } + return new Promise(c => { + const proc = execFile('bash.exe', ['-c', `wslpath ${escapeNonWindowsPath(original)}`], {}, (error, stdout, stderr) => { + c(escapeNonWindowsPath(stdout.trim())); + }); + proc.stdin!.end(); + }); + } + async setTerminalLayoutInfo(args: ISetTerminalLayoutInfoArgs): Promise { this._workspaceLayoutInfos.set(args.workspaceId, args); } @@ -279,9 +297,9 @@ export class PersistentTerminalProcess extends Disposable { constructor( private _persistentProcessId: number, private readonly _terminalProcess: TerminalProcess, - public readonly workspaceId: string, - public readonly workspaceName: string, - public readonly shouldPersistTerminal: boolean, + readonly workspaceId: string, + readonly workspaceName: string, + readonly shouldPersistTerminal: boolean, cols: number, rows: number, private readonly _logService: ILogService, private readonly _icon?: string diff --git a/src/vs/platform/terminal/node/terminalProcess.ts b/src/vs/platform/terminal/node/terminalProcess.ts index 3626928f23c..0dba7ba9ffd 100644 --- a/src/vs/platform/terminal/node/terminalProcess.ts +++ b/src/vs/platform/terminal/node/terminalProcess.ts @@ -90,21 +90,21 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess private _isPtyPaused: boolean = false; private _unacknowledgedCharCount: number = 0; - public get exitMessage(): string | undefined { return this._exitMessage; } + get exitMessage(): string | undefined { return this._exitMessage; } - public get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } - public get shellType(): TerminalShellType { return this._windowsShellHelper ? this._windowsShellHelper.shellType : undefined; } + get currentTitle(): string { return this._windowsShellHelper?.shellTitle || this._currentTitle; } + get shellType(): TerminalShellType { return this._windowsShellHelper ? this._windowsShellHelper.shellType : undefined; } private readonly _onProcessData = this._register(new Emitter()); - public get onProcessData(): Event { return this._onProcessData.event; } + get onProcessData(): Event { return this._onProcessData.event; } private readonly _onProcessExit = this._register(new Emitter()); - public get onProcessExit(): Event { return this._onProcessExit.event; } + get onProcessExit(): Event { return this._onProcessExit.event; } private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); - public get onProcessTitleChanged(): Event { return this._onProcessTitleChanged.event; } + get onProcessTitleChanged(): Event { return this._onProcessTitleChanged.event; } private readonly _onProcessShellTypeChanged = this._register(new Emitter()); - public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; constructor( private readonly _shellLaunchConfig: IShellLaunchConfig, @@ -164,7 +164,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess onProcessOverrideDimensions?: Event | undefined; onProcessResolvedShellLaunchConfig?: Event | undefined; - public async start(): Promise { + async start(): Promise { const results = await Promise.all([this._validateCwd(), this._validateExecutable()]); const firstError = results.find(r => r !== undefined); if (firstError) { @@ -255,7 +255,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess this._sendProcessId(ptyProcess.pid); } - public override dispose(): void { + override dispose(): void { this._isDisposed = true; if (this._titleInterval) { clearInterval(this._titleInterval); @@ -336,7 +336,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess this._onProcessTitleChanged.fire(this._currentTitle); } - public shutdown(immediate: boolean): void { + shutdown(immediate: boolean): void { // don't force immediate disposal of the terminal processes on Windows as an additional // mitigation for https://github.com/microsoft/vscode/issues/71966 which causes the pty host // to become unresponsive, disconnecting all terminals across all windows. @@ -356,7 +356,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - public input(data: string, isBinary?: boolean): void { + input(data: string, isBinary?: boolean): void { if (this._isDisposed || !this._ptyProcess) { return; } @@ -370,7 +370,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess this._startWrite(); } - public async processBinary(data: string): Promise { + async processBinary(data: string): Promise { this.input(data, true); } @@ -404,7 +404,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - public resize(cols: number, rows: number): void { + resize(cols: number, rows: number): void { if (this._isDisposed) { return; } @@ -437,7 +437,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - public acknowledgeDataEvent(charCount: number): void { + acknowledgeDataEvent(charCount: number): void { // Prevent lower than 0 to heal from errors this._unacknowledgedCharCount = Math.max(this._unacknowledgedCharCount - charCount, 0); this._logService.trace(`Flow control: Ack ${charCount} chars (unacknowledged: ${this._unacknowledgedCharCount})`); @@ -448,7 +448,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - public clearUnacknowledgedChars(): void { + clearUnacknowledgedChars(): void { this._unacknowledgedCharCount = 0; this._logService.trace(`Flow control: Cleared all unacknowledged chars, forcing resume`); if (this._isPtyPaused) { @@ -457,11 +457,11 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess } } - public getInitialCwd(): Promise { + getInitialCwd(): Promise { return Promise.resolve(this._initialCwd); } - public getCwd(): Promise { + getCwd(): Promise { if (isMacintosh) { // Disable cwd lookup on macOS Big Sur due to spawn blocking thread (darwin v20 is macOS // Big Sur) https://github.com/Microsoft/vscode/issues/105446 @@ -506,7 +506,7 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess }); } - public getLatency(): Promise { + getLatency(): Promise { return Promise.resolve(0); } } @@ -515,12 +515,12 @@ export class TerminalProcess extends Disposable implements ITerminalChildProcess * Tracks the latest resize event to be trigger at a later point. */ class DelayedResizer extends Disposable { - public rows: number | undefined; - public cols: number | undefined; + rows: number | undefined; + cols: number | undefined; private _timeout: NodeJS.Timeout; private readonly _onTrigger = this._register(new Emitter<{ rows?: number, cols?: number }>()); - public get onTrigger(): Event<{ rows?: number, cols?: number }> { return this._onTrigger.event; } + get onTrigger(): Event<{ rows?: number, cols?: number }> { return this._onTrigger.event; } constructor() { super(); diff --git a/src/vs/platform/terminal/node/windowsShellHelper.ts b/src/vs/platform/terminal/node/windowsShellHelper.ts index 64c3d205db2..efa33b6e5f6 100644 --- a/src/vs/platform/terminal/node/windowsShellHelper.ts +++ b/src/vs/platform/terminal/node/windowsShellHelper.ts @@ -38,15 +38,15 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe private _isDisposed: boolean; private _currentRequest: Promise | undefined; private _shellType: TerminalShellType | undefined; - public get shellType(): TerminalShellType | undefined { return this._shellType; } + get shellType(): TerminalShellType | undefined { return this._shellType; } private _shellTitle: string = ''; - public get shellTitle(): string { return this._shellTitle; } + get shellTitle(): string { return this._shellTitle; } private readonly _onShellNameChanged = new Emitter(); - public get onShellNameChanged(): Event { return this._onShellNameChanged.event; } + get onShellNameChanged(): Event { return this._onShellNameChanged.event; } private readonly _onShellTypeChanged = new Emitter(); - public get onShellTypeChanged(): Event { return this._onShellTypeChanged.event; } + get onShellTypeChanged(): Event { return this._onShellTypeChanged.event; } - public constructor( + constructor( private _rootProcessId: number ) { super(); @@ -112,7 +112,7 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe return this.traverseTree(tree.children[favouriteChild]); } - public override dispose(): void { + override dispose(): void { this._isDisposed = true; super.dispose(); } @@ -120,7 +120,7 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe /** * Returns the innermost shell executable running in the terminal */ - public getShellName(): Promise { + getShellName(): Promise { if (this._isDisposed) { return Promise.resolve(''); } @@ -141,7 +141,7 @@ export class WindowsShellHelper extends Disposable implements IWindowsShellHelpe return this._currentRequest; } - public getShellType(executable: string): TerminalShellType { + getShellType(executable: string): TerminalShellType { switch (executable.toLowerCase()) { case 'cmd.exe': return WindowsShellType.CommandPrompt; diff --git a/src/vs/platform/workspace/common/workspaceTrust.ts b/src/vs/platform/workspace/common/workspaceTrust.ts index e0733647220..19eca765c4e 100644 --- a/src/vs/platform/workspace/common/workspaceTrust.ts +++ b/src/vs/platform/workspace/common/workspaceTrust.ts @@ -45,8 +45,8 @@ export interface IWorkspaceTrustManagementService { setParentFolderTrust(trusted: boolean): void; canSetWorkspaceTrust(): boolean; setWorkspaceTrust(trusted: boolean): void; - getFolderTrustInfo(folder: URI): IWorkspaceTrustUriInfo; - setFoldersTrust(folders: URI[], trusted: boolean): void; + getUriTrustInfo(folder: URI): IWorkspaceTrustUriInfo; + setUrisTrust(folders: URI[], trusted: boolean): void; getTrustedFolders(): URI[]; setTrustedFolders(folders: URI[]): void; } diff --git a/src/vs/vscode.d.ts b/src/vs/vscode.d.ts index 5c6d52b4a6e..573f1398d9f 100644 --- a/src/vs/vscode.d.ts +++ b/src/vs/vscode.d.ts @@ -9341,6 +9341,13 @@ declare module 'vscode' { * as normal. */ hideFromUser?: boolean; + + /** + * A message to write to the terminal on first launch, note that this is not sent to the + * process but, rather written directly to the terminal. This supports escape sequences such + * a setting text style. + */ + message?: string; } /** diff --git a/src/vs/vscode.proposed.d.ts b/src/vs/vscode.proposed.d.ts index 6b67672a710..05e9872705a 100644 --- a/src/vs/vscode.proposed.d.ts +++ b/src/vs/vscode.proposed.d.ts @@ -842,19 +842,28 @@ declare module 'vscode' { //#endregion - //#region Terminal initial text https://github.com/microsoft/vscode/issues/120368 + //#region Terminal name change event https://github.com/microsoft/vscode/issues/114898 - export interface TerminalOptions { + export interface Pseudoterminal { /** - * A message to write to the terminal on first launch, note that this is not sent to the - * process but, rather written directly to the terminal. This supports escape sequences such - * a setting text style. + * An event that when fired allows changing the name of the terminal. + * + * **Example:** Change the terminal name to "My new terminal". + * ```typescript + * const writeEmitter = new vscode.EventEmitter(); + * const changeNameEmitter = new vscode.EventEmitter(); + * const pty: vscode.Pseudoterminal = { + * onDidWrite: writeEmitter.event, + * onDidChangeName: changeNameEmitter.event, + * open: () => changeNameEmitter.fire('My new terminal'), + * close: () => {} + * }; + * vscode.window.createTerminal({ name: 'My terminal', pty }); + * ``` */ - readonly message?: string; + onDidChangeName?: Event; } - //#endregion - //#region Terminal icon https://github.com/microsoft/vscode/issues/120538 export interface TerminalOptions { @@ -881,6 +890,28 @@ declare module 'vscode' { } //#endregion + //#region Custom Tree View Drag and Drop https://github.com/microsoft/vscode/issues/32592 + export interface TreeViewOptions { + /** + * * Whether the tree supports drag and drop. + */ + canDragAndDrop?: boolean; + } + + export interface TreeDataProvider { + /** + * Optional method to reparent an `element`. + * + * **NOTE:** This method should be implemented if the tree supports drag and drop. + * + * @param elements The selected elements that will be reparented. + * @param targetElement The new parent of the elements. + */ + setParent?(elements: T[], targetElement: T): Thenable; + } + + //#endregion + //#region Task presentation group: https://github.com/microsoft/vscode/issues/47265 export interface TaskPresentationOptions { /** diff --git a/src/vs/workbench/api/browser/mainThreadCustomEditors.ts b/src/vs/workbench/api/browser/mainThreadCustomEditors.ts index 00e0592719e..3fcd1c6a452 100644 --- a/src/vs/workbench/api/browser/mainThreadCustomEditors.ts +++ b/src/vs/workbench/api/browser/mainThreadCustomEditors.ts @@ -322,7 +322,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod untitledDocumentData = editors[0].untitledDocumentData; } const { editable } = await proxy.$createCustomDocument(resource, viewType, options.backupId, untitledDocumentData, cancellation); - return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, !!options.backupId, editable, getEditors); + return instantiationService.createInstance(MainThreadCustomEditorModel, proxy, viewType, resource, !!options.backupId, editable, !!untitledDocumentData, getEditors); } constructor( @@ -331,6 +331,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod private readonly _editorResource: URI, fromBackup: boolean, private readonly _editable: boolean, + startDirty: boolean, private readonly _getEditors: () => CustomEditorInput[], @IFileDialogService private readonly _fileDialogService: IFileDialogService, @IFileService private readonly _fileService: IFileService, @@ -338,7 +339,7 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod @IUndoRedoService private readonly _undoService: IUndoRedoService, @IWorkbenchEnvironmentService private readonly _environmentService: IWorkbenchEnvironmentService, @IWorkingCopyService workingCopyService: IWorkingCopyService, - @IPathService private readonly _pathService: IPathService + @IPathService private readonly _pathService: IPathService, ) { super(); @@ -348,6 +349,11 @@ class MainThreadCustomEditorModel extends Disposable implements ICustomEditorMod this._register(workingCopyService.registerWorkingCopy(this)); } + // Normally means we're re-opening an untitled file + if (startDirty) { + this._isDirtyFromContentChange = true; + } + this._register(_fileService.onDidFilesChange(e => this.onDidFilesChange(e))); } diff --git a/src/vs/workbench/api/browser/mainThreadTerminalService.ts b/src/vs/workbench/api/browser/mainThreadTerminalService.ts index 428f24124f6..5505c02239c 100644 --- a/src/vs/workbench/api/browser/mainThreadTerminalService.ts +++ b/src/vs/workbench/api/browser/mainThreadTerminalService.ts @@ -3,20 +3,20 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecycle'; -import { StopWatch } from 'vs/base/common/stopwatch'; +import { DisposableStore, Disposable, IDisposable } from 'vs/base/common/lifecycle'; +import { ExtHostContext, ExtHostTerminalServiceShape, MainThreadTerminalServiceShape, MainContext, IExtHostContext, TerminalLaunchConfig, ITerminalDimensionsDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol'; +import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { URI } from 'vs/base/common/uri'; +import { StopWatch } from 'vs/base/common/stopwatch'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ILogService } from 'vs/platform/log/common/log'; import { IShellLaunchConfig, IShellLaunchConfigDto, ITerminalDimensions } from 'vs/platform/terminal/common/terminal'; import { TerminalDataBufferer } from 'vs/platform/terminal/common/terminalDataBuffering'; -import { ExtHostContext, ExtHostTerminalServiceShape, IExtHostContext, ITerminalDimensionsDto, MainContext, MainThreadTerminalServiceShape, TerminalIdentifier, TerminalLaunchConfig } from 'vs/workbench/api/common/extHost.protocol'; -import { extHostNamedCustomer } from 'vs/workbench/api/common/extHostCustomers'; import { ITerminalExternalLinkProvider, ITerminalInstance, ITerminalInstanceService, ITerminalLink, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy'; import { IEnvironmentVariableService, ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; import { deserializeEnvironmentVariableCollection, serializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared'; -import { IAvailableProfilesRequest as IAvailableProfilesRequest, IDefaultShellAndArgsRequest, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IAvailableProfilesRequest as IAvailableProfilesRequest, IStartExtensionTerminalRequest, ITerminalProcessExtHostProxy, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; @@ -72,11 +72,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape this._toDispose.add(_terminalService.onInstanceTitleChanged(instance => instance && this._onTitleChanged(instance.instanceId, instance.title))); this._toDispose.add(_terminalService.onRequestAvailableProfiles(e => this._onRequestAvailableProfiles(e))); - // ITerminalInstanceService listeners - if (terminalInstanceService.onRequestDefaultShellAndArgs) { - this._toDispose.add(terminalInstanceService.onRequestDefaultShellAndArgs(e => this._onRequestDefaultShellAndArgs(e))); - } - // Set initial ext host state this._terminalService.terminalInstances.forEach(t => { this._onTerminalOpened(t); @@ -265,7 +260,15 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape } public $sendProcessTitle(terminalId: number, title: string): void { - this._terminalProcessProxies.get(terminalId)?.emitTitle(title); + // Since title events can only come from vscode.Pseudoterminals right now, these are routed + // directly to the instance as API source events such that they will replace the initial + // `name` property provided for the Pseudoterminal. If we support showing both Api and + // Process titles at the same time we may want to pass this through as a Process source + // event. + const instance = this._terminalService.getInstanceFromId(terminalId); + if (instance) { + instance.setTitle(title, TitleEventSource.Api); + } } public $sendProcessData(terminalId: number, data: string): void { @@ -323,13 +326,6 @@ export class MainThreadTerminalService implements MainThreadTerminalServiceShape } } - private async _onRequestDefaultShellAndArgs(req: IDefaultShellAndArgsRequest): Promise { - if (this._isPrimaryExtHost()) { - const res = await this._proxy.$getDefaultShellAndArgs(req.useAutomationShell); - req.callback(res.shell, res.args); - } - } - private _getTerminalProcess(terminalId: number): ITerminalProcessExtHostProxy | undefined { const terminal = this._terminalProcessProxies.get(terminalId); if (!terminal) { diff --git a/src/vs/workbench/api/browser/mainThreadTreeViews.ts b/src/vs/workbench/api/browser/mainThreadTreeViews.ts index b70ff475447..219fa248b0c 100644 --- a/src/vs/workbench/api/browser/mainThreadTreeViews.ts +++ b/src/vs/workbench/api/browser/mainThreadTreeViews.ts @@ -31,7 +31,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie this._proxy = extHostContext.getProxy(ExtHostContext.ExtHostTreeViews); } - async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean }): Promise { + async $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, canDragAndDrop: boolean }): Promise { this.logService.trace('MainThreadTreeViews#$registerTreeViewDataProvider', treeViewId, options); this.extensionService.whenInstalledExtensionsRegistered().then(() => { @@ -43,6 +43,7 @@ export class MainThreadTreeViews extends Disposable implements MainThreadTreeVie // Set all other properties first! viewer.showCollapseAllAction = !!options.showCollapseAll; viewer.canSelectMany = !!options.canSelectMany; + viewer.canDragAndDrop = !!options.canDragAndDrop; viewer.dataProvider = dataProvider; this.registerListeners(treeViewId, viewer); this._proxy.$setVisible(treeViewId, viewer.visible); @@ -183,6 +184,10 @@ class TreeViewDataProvider implements ITreeViewDataProvider { })); } + setParent(treeItem: ITreeItem[], targetTreeItem: ITreeItem): Promise { + return this._proxy.$setParent(this.treeViewId, treeItem.map(item => item.handle), targetTreeItem.handle); + } + getItemsToRefresh(itemsToRefreshByHandle: { [treeItemHandle: string]: ITreeItem }): ITreeItem[] { const itemsToRefresh: ITreeItem[] = []; if (itemsToRefreshByHandle) { diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts index 7e0e04ce045..74645046ca7 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -643,9 +643,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I if ('pty' in nameOrOptions) { return extHostTerminalService.createExtensionTerminal(nameOrOptions); } - if (nameOrOptions.message) { - checkProposedApiEnabled(extension); - } if (nameOrOptions.icon) { checkProposedApiEnabled(extension); } diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts index 1907f1113b2..107fcce2d75 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts @@ -289,7 +289,7 @@ export interface MainThreadTextEditorsShape extends IDisposable { } export interface MainThreadTreeViewsShape extends IDisposable { - $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean; }): Promise; + $registerTreeViewDataProvider(treeViewId: string, options: { showCollapseAll: boolean, canSelectMany: boolean, canDragAndDrop: boolean; }): Promise; $refresh(treeViewId: string, itemsToRefresh?: { [treeItemHandle: string]: ITreeItem; }): Promise; $reveal(treeViewId: string, itemInfo: { item: ITreeItem, parentChain: ITreeItem[] } | undefined, options: IRevealOptions): Promise; $setMessage(treeViewId: string, message: string): void; @@ -1229,6 +1229,7 @@ export interface ExtHostDocumentsAndEditorsShape { export interface ExtHostTreeViewsShape { $getChildren(treeViewId: string, treeItemHandle?: string): Promise; + $setParent(treeViewId: string, treeItemHandle: string[], newParentTreeItemHandle: string): Promise; $setExpanded(treeViewId: string, treeItemHandle: string, expanded: boolean): void; $setSelection(treeViewId: string, treeItemHandles: string[]): void; $setVisible(treeViewId: string, visible: boolean): void; @@ -1717,7 +1718,6 @@ export interface ExtHostTerminalServiceShape { $acceptProcessRequestCwd(id: number): void; $acceptProcessRequestLatency(id: number): number; $getAvailableProfiles(configuredProfilesOnly: boolean): Promise; - $getDefaultShellAndArgs(useAutomationShell: boolean): Promise; $provideLinks(id: number, line: string): Promise; $activateLink(id: number, linkId: number): void; $initEnvironmentVariableCollections(collections: [string, ISerializableEnvironmentVariableCollection][]): void; diff --git a/src/vs/workbench/api/common/extHostTerminalService.ts b/src/vs/workbench/api/common/extHostTerminalService.ts index a10d6b973b4..2be854f592c 100644 --- a/src/vs/workbench/api/common/extHostTerminalService.ts +++ b/src/vs/workbench/api/common/extHostTerminalService.ts @@ -5,7 +5,7 @@ import type * as vscode from 'vscode'; import { Event, Emitter } from 'vs/base/common/event'; -import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, IShellAndArgsDto, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier } from 'vs/workbench/api/common/extHost.protocol'; +import { ExtHostTerminalServiceShape, MainContext, MainThreadTerminalServiceShape, ITerminalDimensionsDto, ITerminalLinkDto, TerminalIdentifier, IShellAndArgsDto } from 'vs/workbench/api/common/extHost.protocol'; import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { URI } from 'vs/base/common/uri'; @@ -44,6 +44,7 @@ export interface IExtHostTerminalService extends ExtHostTerminalServiceShape, ID getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string; registerLinkProvider(provider: vscode.TerminalLinkProvider): vscode.Disposable; getEnvironmentVariableCollection(extension: IExtensionDescription, persistent?: boolean): vscode.EnvironmentVariableCollection; + getDefaultShellAndArgs(useAutomationShell: boolean): Promise; } export const IExtHostTerminalService = createDecorator('IExtHostTerminalService'); @@ -259,6 +260,9 @@ export class ExtHostPseudoterminal implements ITerminalChildProcess { if (this._pty.onDidOverrideDimensions) { this._pty.onDidOverrideDimensions(e => this._onProcessOverrideDimensions.fire(e ? { cols: e.columns, rows: e.rows } : e)); } + if (this._pty.onDidChangeName) { + this._pty.onDidChangeName(title => this._onProcessTitleChanged.fire(title)); + } this._pty.open(initialDimensions ? initialDimensions : undefined); @@ -334,8 +338,8 @@ export abstract class BaseExtHostTerminalService extends Disposable implements I public abstract createTerminalFromOptions(options: vscode.TerminalOptions): vscode.Terminal; public abstract getDefaultShell(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string; public abstract getDefaultShellArgs(useAutomationShell: boolean, configProvider: ExtHostConfigProvider): string[] | string; + public abstract getDefaultShellAndArgs(useAutomationShell: boolean): Promise; public abstract $getAvailableProfiles(configuredProfilesOnly: boolean): Promise; - public abstract $getDefaultShellAndArgs(useAutomationShell: boolean): Promise; public createExtensionTerminal(options: vscode.ExtensionTerminalOptions): vscode.Terminal { const terminal = new ExtHostTerminal(this._proxy, generateUuid(), options, options.name); @@ -783,11 +787,11 @@ export class WorkerExtHostTerminalService extends BaseExtHostTerminalService { throw new NotSupportedError(); } - public $getAvailableProfiles(configuredProfilesOnly: boolean): Promise { + public async getDefaultShellAndArgs(useAutomationShell: boolean): Promise { throw new NotSupportedError(); } - public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise { + public $getAvailableProfiles(configuredProfilesOnly: boolean): Promise { throw new NotSupportedError(); } } diff --git a/src/vs/workbench/api/common/extHostTreeViews.ts b/src/vs/workbench/api/common/extHostTreeViews.ts index bf2801705cf..eb94d4f861b 100644 --- a/src/vs/workbench/api/common/extHostTreeViews.ts +++ b/src/vs/workbench/api/common/extHostTreeViews.ts @@ -84,7 +84,7 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape { if (!options || !options.treeDataProvider) { throw new Error('Options with treeDataProvider is mandatory'); } - const registerPromise = this._proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany }); + const registerPromise = this._proxy.$registerTreeViewDataProvider(viewId, { showCollapseAll: !!options.showCollapseAll, canSelectMany: !!options.canSelectMany, canDragAndDrop: !!options.canDragAndDrop }); const treeView = this.createExtHostTreeView(viewId, options, extension); return { get onDidCollapseElement() { return treeView.onDidCollapseElement; }, @@ -127,6 +127,14 @@ export class ExtHostTreeViews implements ExtHostTreeViewsShape { return treeView.getChildren(treeItemHandle); } + $setParent(treeViewId: string, treeItemHandles: string[], newParentItemHandle: string): Promise { + const treeView = this.treeViews.get(treeViewId); + if (!treeView) { + return Promise.reject(new Error(localize('treeView.notRegistered', 'No tree view with id \'{0}\' registered.', treeViewId))); + } + return treeView.setParent(treeItemHandles, newParentItemHandle); + } + async $hasResolve(treeViewId: string): Promise { const treeView = this.treeViews.get(treeViewId); if (!treeView) { @@ -369,6 +377,15 @@ class ExtHostTreeView extends Disposable { } } + setParent(treeItemHandleOrNodes: TreeItemHandle[], newParentHandleOrNode: TreeItemHandle): Promise { + const elements = treeItemHandleOrNodes.map(item => this.getExtensionElement(item)).filter(element => !isUndefinedOrNull(element)); + const newParentElement = this.getExtensionElement(newParentHandleOrNode); + if (this.dataProvider.setParent && elements && newParentElement) { + return asPromise(() => this.dataProvider.setParent!(elements, newParentElement)); + } + return Promise.resolve(undefined); + } + get hasResolve(): boolean { return !!this.dataProvider.resolveTreeItem; } diff --git a/src/vs/workbench/api/common/shared/tasks.ts b/src/vs/workbench/api/common/shared/tasks.ts index 4de859f671b..066b22f90ea 100644 --- a/src/vs/workbench/api/common/shared/tasks.ts +++ b/src/vs/workbench/api/common/shared/tasks.ts @@ -19,6 +19,7 @@ export interface TaskPresentationOptionsDTO { showReuseMessage?: boolean; clear?: boolean; group?: string; + close?: boolean; } export interface RunOptionsDTO { diff --git a/src/vs/workbench/api/node/extHostTask.ts b/src/vs/workbench/api/node/extHostTask.ts index dd250c83c29..8d6652775fa 100644 --- a/src/vs/workbench/api/node/extHostTask.ts +++ b/src/vs/workbench/api/node/extHostTask.ts @@ -173,7 +173,7 @@ export class ExtHostTask extends ExtHostTaskBase { } public $getDefaultShellAndArgs(): Promise<{ shell: string, args: string[] | string | undefined }> { - return this._terminalService.$getDefaultShellAndArgs(true); + return this._terminalService.getDefaultShellAndArgs(true); } public async $jsonTasksSupported(): Promise { diff --git a/src/vs/workbench/api/node/extHostTerminalService.ts b/src/vs/workbench/api/node/extHostTerminalService.ts index 6b0ccaeec66..6cd875992d2 100644 --- a/src/vs/workbench/api/node/extHostTerminalService.ts +++ b/src/vs/workbench/api/node/extHostTerminalService.ts @@ -17,7 +17,7 @@ import { ExtHostDocumentsAndEditors, IExtHostDocumentsAndEditors } from 'vs/work import { IExtHostRpcService } from 'vs/workbench/api/common/extHostRpcService'; import { BaseExtHostTerminalService, ExtHostTerminal } from 'vs/workbench/api/common/extHostTerminalService'; import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace'; -import { ITerminalProfile, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProfile, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; import { detectAvailableProfiles } from 'vs/workbench/contrib/terminal/node/terminalProfiles'; import type * as vscode from 'vscode'; @@ -122,7 +122,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { return detectAvailableProfiles(configuredProfilesOnly, safeConfigProvider, undefined, this._logService, await this._variableResolverPromise, this._lastActiveWorkspace); } - public async $getDefaultShellAndArgs(useAutomationShell: boolean): Promise { + public async getDefaultShellAndArgs(useAutomationShell: boolean): Promise { const configProvider = await this._extHostConfiguration.getConfigProvider(); return { shell: this.getDefaultShell(useAutomationShell, configProvider), @@ -134,7 +134,7 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService { private _buildSafeConfigProvider(configProvider: ExtHostConfigProvider): SafeConfigProvider { const config = configProvider.getConfiguration(); return (key: string) => { - const isWorkspaceConfigAllowed = config.get(TERMINAL_SETTING_ID.AllowWorkspaceConfiguration); + const isWorkspaceConfigAllowed = config.get(TerminalSettingId.AllowWorkspaceConfiguration); if (isWorkspaceConfigAllowed) { return config.get(key) as any; } diff --git a/src/vs/workbench/browser/actions/layoutActions.ts b/src/vs/workbench/browser/actions/layoutActions.ts index 746e22b079f..3d94cd32bc6 100644 --- a/src/vs/workbench/browser/actions/layoutActions.ts +++ b/src/vs/workbench/browser/actions/layoutActions.ts @@ -5,10 +5,8 @@ import { localize } from 'vs/nls'; import Severity from 'vs/base/common/severity'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { Action } from 'vs/base/common/actions'; -import { SyncActionDescriptor, MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; -import { IWorkbenchActionRegistry, Extensions as WorkbenchExtensions, CATEGORIES } from 'vs/workbench/common/actions'; +import { MenuId, MenuRegistry, registerAction2, Action2 } from 'vs/platform/actions/common/actions'; +import { CATEGORIES } from 'vs/workbench/common/actions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; @@ -25,11 +23,9 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs'; import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService'; import { IPanelService } from 'vs/workbench/services/panel/common/panelService'; -const registry = Registry.as(WorkbenchExtensions.WorkbenchActions); - // --- Close Side Bar -class CloseSidebarAction extends Action2 { +registerAction2(class extends Action2 { constructor() { super({ @@ -43,9 +39,7 @@ class CloseSidebarAction extends Action2 { run(accessor: ServicesAccessor): void { accessor.get(IWorkbenchLayoutService).setSideBarHidden(true); } -} - -registerAction2(CloseSidebarAction); +}); // --- Toggle Activity Bar @@ -89,7 +83,7 @@ registerAction2(ToggleActivityBarVisibilityAction); // --- Toggle Centered Layout -class ToggleCenteredLayout extends Action2 { +registerAction2(class extends Action2 { constructor() { super({ @@ -115,41 +109,21 @@ class ToggleCenteredLayout extends Action2 { layoutService.centerEditorLayout(!layoutService.isEditorLayoutCentered()); } -} - -registerAction2(ToggleCenteredLayout); +}); // --- Toggle Sidebar Position -export class ToggleSidebarPositionAction extends Action { +export class ToggleSidebarPositionAction extends Action2 { static readonly ID = 'workbench.action.toggleSidebarPosition'; static readonly LABEL = localize('toggleSidebarPosition', "Toggle Side Bar Position"); private static readonly sidebarPositionConfigurationKey = 'workbench.sideBar.location'; - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IConfigurationService private readonly configurationService: IConfigurationService - ) { - super(id, label); - } - - override run(): Promise { - const position = this.layoutService.getSideBarPosition(); - const newPositionValue = (position === Position.LEFT) ? 'right' : 'left'; - - return this.configurationService.updateValue(ToggleSidebarPositionAction.sidebarPositionConfigurationKey, newPositionValue); - } - static getLabel(layoutService: IWorkbenchLayoutService): string { return layoutService.getSideBarPosition() === Position.LEFT ? localize('moveSidebarRight', "Move Side Bar Right") : localize('moveSidebarLeft', "Move Side Bar Left"); } -} -registerAction2(class extends Action2 { constructor() { super({ id: ToggleSidebarPositionAction.ID, @@ -158,10 +132,20 @@ registerAction2(class extends Action2 { f1: true }); } - run(accessor: ServicesAccessor) { - accessor.get(IInstantiationService).createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.LABEL).run(); + + run(accessor: ServicesAccessor): Promise { + const layoutService = accessor.get(IWorkbenchLayoutService); + const configurationService = accessor.get(IConfigurationService); + + const position = layoutService.getSideBarPosition(); + const newPositionValue = (position === Position.LEFT) ? 'right' : 'left'; + + return configurationService.updateValue(ToggleSidebarPositionAction.sidebarPositionConfigurationKey, newPositionValue); } -}); +} + +registerAction2(ToggleSidebarPositionAction); + MenuRegistry.appendMenuItems([{ id: MenuId.ViewContainerTitleContext, item: { @@ -228,35 +212,32 @@ MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { order: 2 }); -// --- Toggle Sidebar Visibility +// --- Toggle Editor Visibility -export class ToggleEditorVisibilityAction extends Action { - static readonly ID = 'workbench.action.toggleEditorVisibility'; - static readonly LABEL = localize('toggleEditor', "Toggle Editor Area Visibility"); +registerAction2(class extends Action2 { - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService - ) { - super(id, label); + constructor() { + super({ + id: 'workbench.action.toggleEditorVisibility', + title: { + value: localize('toggleEditor', "Toggle Editor Area Visibility"), + mnemonicTitle: localize({ key: 'miShowEditorArea', comment: ['&& denotes a mnemonic'] }, "Show &&Editor Area"), + original: 'Toggle Editor Area Visibility' + }, + category: CATEGORIES.View, + f1: true, + toggled: EditorAreaVisibleContext, + menu: { + id: MenuId.MenubarAppearanceMenu, + group: '2_workbench_layout', + order: 5 + } + }); } - override async run(): Promise { - this.layoutService.toggleMaximizedPanel(); + run(accessor: ServicesAccessor): void { + accessor.get(IWorkbenchLayoutService).toggleMaximizedPanel(); } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleEditorVisibilityAction), 'View: Toggle Editor Area Visibility', CATEGORIES.View.value); - -MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { - group: '2_workbench_layout', - command: { - id: ToggleEditorVisibilityAction.ID, - title: localize({ key: 'miShowEditorArea', comment: ['&& denotes a mnemonic'] }, "Show &&Editor Area"), - toggled: EditorAreaVisibleContext - }, - order: 5 }); MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { @@ -266,11 +247,15 @@ MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, { order: 1 }); -export const TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID = 'workbench.action.toggleSidebarVisibility'; -registerAction2(class extends Action2 { +// Toggle Sidebar Visibility + +class ToggleSidebarVisibilityAction extends Action2 { + + static readonly ID = 'workbench.action.toggleSidebarVisibility'; + constructor() { super({ - id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + id: ToggleSidebarVisibilityAction.ID, title: { value: localize('toggleSidebar', "Toggle Side Bar Visibility"), original: 'Toggle Side Bar Visibility' }, category: CATEGORIES.View, f1: true, @@ -280,17 +265,22 @@ registerAction2(class extends Action2 { } }); } - run(accessor: ServicesAccessor) { + + run(accessor: ServicesAccessor): void { const layoutService = accessor.get(IWorkbenchLayoutService); + layoutService.setSideBarHidden(layoutService.isVisible(Parts.SIDEBAR_PART)); } -}); +} + +registerAction2(ToggleSidebarVisibilityAction); + MenuRegistry.appendMenuItems([{ id: MenuId.ViewContainerTitleContext, item: { group: '3_workbench_layout_move', command: { - id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + id: ToggleSidebarVisibilityAction.ID, title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"), }, when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewContainerLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), @@ -301,123 +291,127 @@ MenuRegistry.appendMenuItems([{ item: { group: '3_workbench_layout_move', command: { - id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, + id: ToggleSidebarVisibilityAction.ID, title: localize('compositePart.hideSideBarLabel', "Hide Side Bar"), }, when: ContextKeyExpr.and(SideBarVisibleContext, ContextKeyExpr.equals('viewLocation', ViewContainerLocationToString(ViewContainerLocation.Sidebar))), order: 2 } +}, { + id: MenuId.MenubarAppearanceMenu, + item: { + group: '2_workbench_layout', + command: { + id: ToggleSidebarVisibilityAction.ID, + title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"), + toggled: SideBarVisibleContext + }, + order: 1 + } }]); -MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { - group: '2_workbench_layout', - command: { - id: TOGGLE_SIDEBAR_VISIBILITY_ACTION_ID, - title: localize({ key: 'miShowSidebar', comment: ['&& denotes a mnemonic'] }, "Show &&Side Bar"), - toggled: SideBarVisibleContext - }, - order: 1 -}); - // --- Toggle Statusbar Visibility -export class ToggleStatusbarVisibilityAction extends Action { +export class ToggleStatusbarVisibilityAction extends Action2 { static readonly ID = 'workbench.action.toggleStatusbarVisibility'; - static readonly LABEL = localize('toggleStatusbar', "Toggle Status Bar Visibility"); private static readonly statusbarVisibleKey = 'workbench.statusBar.visible'; - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService, - @IConfigurationService private readonly configurationService: IConfigurationService - ) { - super(id, label); + constructor() { + super({ + id: ToggleStatusbarVisibilityAction.ID, + title: { + value: localize('toggleStatusbar', "Toggle Status Bar Visibility"), + mnemonicTitle: localize({ key: 'miShowStatusbar', comment: ['&& denotes a mnemonic'] }, "Show S&&tatus Bar"), + original: 'Toggle Status Bar Visibility' + }, + category: CATEGORIES.View, + f1: true, + toggled: ContextKeyExpr.equals('config.workbench.statusBar.visible', true), + menu: { + id: MenuId.MenubarAppearanceMenu, + group: '2_workbench_layout', + order: 3 + } + }); } - override run(): Promise { - const visibility = this.layoutService.isVisible(Parts.STATUSBAR_PART); + run(accessor: ServicesAccessor): Promise { + const layoutService = accessor.get(IWorkbenchLayoutService); + const configurationService = accessor.get(IConfigurationService); + + const visibility = layoutService.isVisible(Parts.STATUSBAR_PART); const newVisibilityValue = !visibility; - return this.configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue); + return configurationService.updateValue(ToggleStatusbarVisibilityAction.statusbarVisibleKey, newVisibilityValue); } } -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleStatusbarVisibilityAction), 'View: Toggle Status Bar Visibility', CATEGORIES.View.value); - -MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { - group: '2_workbench_layout', - command: { - id: ToggleStatusbarVisibilityAction.ID, - title: localize({ key: 'miShowStatusbar', comment: ['&& denotes a mnemonic'] }, "Show S&&tatus Bar"), - toggled: ContextKeyExpr.equals('config.workbench.statusBar.visible', true) - }, - order: 3 -}); +registerAction2(ToggleStatusbarVisibilityAction); // --- Toggle Tabs Visibility -class ToggleTabsVisibilityAction extends Action { +registerAction2(class extends Action2 { - static readonly ID = 'workbench.action.toggleTabsVisibility'; - static readonly LABEL = localize('toggleTabs', "Toggle Tab Visibility"); - - private static readonly tabsVisibleKey = 'workbench.editor.showTabs'; - - constructor( - id: string, - label: string, - @IConfigurationService private readonly configurationService: IConfigurationService - ) { - super(id, label); + constructor() { + super({ + id: 'workbench.action.toggleTabsVisibility', + title: { + value: localize('toggleTabs', "Toggle Tab Visibility"), + original: 'Toggle Tab Visibility' + }, + category: CATEGORIES.View, + f1: true, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: undefined, + mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, }, + linux: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, } + } + }); } - override run(): Promise { - const visibility = this.configurationService.getValue(ToggleTabsVisibilityAction.tabsVisibleKey); + run(accessor: ServicesAccessor): Promise { + const configurationService = accessor.get(IConfigurationService); + + const visibility = configurationService.getValue('workbench.editor.showTabs'); const newVisibilityValue = !visibility; - return this.configurationService.updateValue(ToggleTabsVisibilityAction.tabsVisibleKey, newVisibilityValue); + return configurationService.updateValue('workbench.editor.showTabs', newVisibilityValue); } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleTabsVisibilityAction, { - primary: undefined, - mac: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, }, - linux: { primary: KeyMod.CtrlCmd | KeyMod.WinCtrl | KeyCode.KEY_W, } -}), 'View: Toggle Tab Visibility', CATEGORIES.View.value); +}); // --- Toggle Zen Mode -class ToggleZenMode extends Action { +registerAction2(class extends Action2 { - static readonly ID = 'workbench.action.toggleZenMode'; - static readonly LABEL = localize('toggleZenMode', "Toggle Zen Mode"); - - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService - ) { - super(id, label); + constructor() { + super({ + id: 'workbench.action.toggleZenMode', + title: { + value: localize('toggleZenMode', "Toggle Zen Mode"), + mnemonicTitle: localize('miToggleZenMode', "Zen Mode"), + original: 'Toggle Zen Mode' + }, + category: CATEGORIES.View, + f1: true, + keybinding: { + weight: KeybindingWeight.WorkbenchContrib, + primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) + }, + toggled: InEditorZenModeContext, + menu: { + id: MenuId.MenubarAppearanceMenu, + group: '1_toggle_view', + order: 2 + } + }); } - override async run(): Promise { - this.layoutService.toggleZenMode(); + run(accessor: ServicesAccessor): void { + return accessor.get(IWorkbenchLayoutService).toggleZenMode(); } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleZenMode, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_Z) }), 'View: Toggle Zen Mode', CATEGORIES.View.value); - -MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { - group: '1_toggle_view', - command: { - id: ToggleZenMode.ID, - title: localize('miToggleZenMode', "Zen Mode"), - toggled: InEditorZenModeContext - }, - order: 2 }); KeybindingsRegistry.registerCommandAndKeybindingRule({ @@ -433,85 +427,103 @@ KeybindingsRegistry.registerCommandAndKeybindingRule({ // --- Toggle Menu Bar -export class ToggleMenuBarAction extends Action { - - static readonly ID = 'workbench.action.toggleMenuBar'; - static readonly LABEL = localize('toggleMenuBar', "Toggle Menu Bar"); - - constructor( - id: string, - label: string, - @IWorkbenchLayoutService private readonly layoutService: IWorkbenchLayoutService - ) { - super(id, label); - } - - override async run(): Promise { - this.layoutService.toggleMenuBar(); - } -} - if (isWindows || isLinux || isWeb) { - registry.registerWorkbenchAction(SyncActionDescriptor.from(ToggleMenuBarAction), 'View: Toggle Menu Bar', CATEGORIES.View.value); + registerAction2(class extends Action2 { + + constructor() { + super({ + id: 'workbench.action.toggleMenuBar', + title: { + value: localize('toggleMenuBar', "Toggle Menu Bar"), + mnemonicTitle: localize({ key: 'miShowMenuBar', comment: ['&& denotes a mnemonic'] }, "Show Menu &&Bar"), + original: 'Toggle Menu Bar' + }, + category: CATEGORIES.View, + f1: true, + toggled: ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'hidden'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'toggle'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'compact')), + menu: { + id: MenuId.MenubarAppearanceMenu, + group: '2_workbench_layout', + order: 0 + } + }); + } + + run(accessor: ServicesAccessor): void { + return accessor.get(IWorkbenchLayoutService).toggleMenuBar(); + } + }); } -MenuRegistry.appendMenuItem(MenuId.MenubarAppearanceMenu, { - group: '2_workbench_layout', - command: { - id: ToggleMenuBarAction.ID, - title: localize({ key: 'miShowMenuBar', comment: ['&& denotes a mnemonic'] }, "Show Menu &&Bar"), - toggled: ContextKeyExpr.and(IsMacNativeContext.toNegated(), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'hidden'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'toggle'), ContextKeyExpr.notEquals('config.window.menuBarVisibility', 'compact')) - }, - when: IsMacNativeContext.toNegated(), - order: 0 +// --- Reset View Locations + +registerAction2(class extends Action2 { + + constructor() { + super({ + id: 'workbench.action.resetViewLocations', + title: { + value: localize('resetViewLocations', "Reset View Locations"), + original: 'Reset View Locations' + }, + category: CATEGORIES.View, + f1: true + }); + } + + run(accessor: ServicesAccessor): void { + return accessor.get(IViewDescriptorService).reset(); + } }); -// --- Reset View Positions +// --- Move View -export class ResetViewLocationsAction extends Action { - static readonly ID = 'workbench.action.resetViewLocations'; - static readonly LABEL = localize('resetViewLocations', "Reset View Locations"); +registerAction2(class extends Action2 { - constructor( - id: string, - label: string, - @IViewDescriptorService private viewDescriptorService: IViewDescriptorService - ) { - super(id, label); + constructor() { + super({ + id: 'workbench.action.moveView', + title: { + value: localize('moveView', "Move View"), + original: 'Move View' + }, + category: CATEGORIES.View, + f1: true + }); } - override async run(): Promise { - this.viewDescriptorService.reset(); - } -} + async run(accessor: ServicesAccessor): Promise { + const viewDescriptorService = accessor.get(IViewDescriptorService); + const instantiationService = accessor.get(IInstantiationService); + const quickInputService = accessor.get(IQuickInputService); + const contextKeyService = accessor.get(IContextKeyService); + const activityBarService = accessor.get(IActivityBarService); + const panelService = accessor.get(IPanelService); -registry.registerWorkbenchAction(SyncActionDescriptor.from(ResetViewLocationsAction), 'View: Reset View Locations', CATEGORIES.View.value); + const focusedViewId = FocusedViewContext.getValue(contextKeyService); + let viewId: string; -// --- Move View with Command -export class MoveViewAction extends Action { - static readonly ID = 'workbench.action.moveView'; - static readonly LABEL = localize('moveView', "Move View"); + if (focusedViewId && viewDescriptorService.getViewDescriptorById(focusedViewId)?.canMoveView) { + viewId = focusedViewId; + } - constructor( - id: string, - label: string, - @IViewDescriptorService private viewDescriptorService: IViewDescriptorService, - @IInstantiationService private instantiationService: IInstantiationService, - @IQuickInputService private quickInputService: IQuickInputService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IActivityBarService private activityBarService: IActivityBarService, - @IPanelService private panelService: IPanelService - ) { - super(id, label); + viewId = await this.getView(quickInputService, activityBarService, viewDescriptorService, panelService, viewId!); + + if (!viewId) { + return; + } + + const moveFocusedViewAction = new MoveFocusedViewAction(); + instantiationService.invokeFunction(accessor => moveFocusedViewAction.run(accessor, viewId)); } - private getViewItems(): Array { + private getViewItems(activityBarService: IActivityBarService, viewDescriptorService: IViewDescriptorService, panelService: IPanelService): Array { const results: Array = []; - const viewlets = this.activityBarService.getVisibleViewContainerIds(); + const viewlets = activityBarService.getVisibleViewContainerIds(); viewlets.forEach(viewletId => { - const container = this.viewDescriptorService.getViewContainerById(viewletId)!; - const containerModel = this.viewDescriptorService.getViewContainerModel(container); + const container = viewDescriptorService.getViewContainerById(viewletId)!; + const containerModel = viewDescriptorService.getViewContainerModel(container); let hasAddedView = false; containerModel.visibleViewDescriptors.forEach(viewDescriptor => { @@ -532,10 +544,10 @@ export class MoveViewAction extends Action { }); }); - const panels = this.panelService.getPinnedPanels(); + const panels = panelService.getPinnedPanels(); panels.forEach(panel => { - const container = this.viewDescriptorService.getViewContainerById(panel.id)!; - const containerModel = this.viewDescriptorService.getViewContainerModel(container); + const container = viewDescriptorService.getViewContainerById(panel.id)!; + const containerModel = viewDescriptorService.getViewContainerModel(container); let hasAddedView = false; containerModel.visibleViewDescriptors.forEach(viewDescriptor => { @@ -559,10 +571,10 @@ export class MoveViewAction extends Action { return results; } - private async getView(viewId?: string): Promise { - const quickPick = this.quickInputService.createQuickPick(); + private async getView(quickInputService: IQuickInputService, activityBarService: IActivityBarService, viewDescriptorService: IViewDescriptorService, panelService: IPanelService, viewId?: string): Promise { + const quickPick = quickInputService.createQuickPick(); quickPick.placeholder = localize('moveFocusedView.selectView', "Select a View to Move"); - quickPick.items = this.getViewItems(); + quickPick.items = this.getViewItems(activityBarService, viewDescriptorService, panelService); quickPick.selectedItems = quickPick.items.filter(item => (item as IQuickPickItem).id === viewId) as IQuickPickItem[]; return new Promise((resolve, reject) => { @@ -582,68 +594,55 @@ export class MoveViewAction extends Action { quickPick.show(); }); } +}); - override async run(): Promise { - const focusedViewId = FocusedViewContext.getValue(this.contextKeyService); - let viewId: string; +// --- Move Focused View - if (focusedViewId && this.viewDescriptorService.getViewDescriptorById(focusedViewId)?.canMoveView) { - viewId = focusedViewId; - } +class MoveFocusedViewAction extends Action2 { - viewId = await this.getView(viewId!); - - if (!viewId) { - return; - } - - this.instantiationService.createInstance(MoveFocusedViewAction, MoveFocusedViewAction.ID, MoveFocusedViewAction.LABEL).run(viewId); - } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveViewAction), 'View: Move View', CATEGORIES.View.value); - -// --- Move Focused View with Command -export class MoveFocusedViewAction extends Action { - static readonly ID = 'workbench.action.moveFocusedView'; - static readonly LABEL = localize('moveFocusedView', "Move Focused View"); - - constructor( - id: string, - label: string, - @IViewDescriptorService private viewDescriptorService: IViewDescriptorService, - @IViewsService private viewsService: IViewsService, - @IQuickInputService private quickInputService: IQuickInputService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IDialogService private dialogService: IDialogService, - @IActivityBarService private activityBarService: IActivityBarService, - @IPanelService private panelService: IPanelService - ) { - super(id, label); + constructor() { + super({ + id: 'workbench.action.moveFocusedView', + title: { + value: localize('moveFocusedView', "Move Focused View"), + original: 'Move Focused View' + }, + category: CATEGORIES.View, + precondition: FocusedViewContext.notEqualsTo(''), + f1: true + }); } - override async run(viewId: string): Promise { - const focusedViewId = viewId || FocusedViewContext.getValue(this.contextKeyService); + run(accessor: ServicesAccessor, viewId?: string): void { + const viewDescriptorService = accessor.get(IViewDescriptorService); + const viewsService = accessor.get(IViewsService); + const quickInputService = accessor.get(IQuickInputService); + const contextKeyService = accessor.get(IContextKeyService); + const dialogService = accessor.get(IDialogService); + const activityBarService = accessor.get(IActivityBarService); + const panelService = accessor.get(IPanelService); + + const focusedViewId = viewId || FocusedViewContext.getValue(contextKeyService); if (focusedViewId === undefined || focusedViewId.trim() === '') { - this.dialogService.show(Severity.Error, localize('moveFocusedView.error.noFocusedView', "There is no view currently focused."), [localize('ok', 'OK')]); + dialogService.show(Severity.Error, localize('moveFocusedView.error.noFocusedView', "There is no view currently focused."), [localize('ok', 'OK')]); return; } - const viewDescriptor = this.viewDescriptorService.getViewDescriptorById(focusedViewId); + const viewDescriptor = viewDescriptorService.getViewDescriptorById(focusedViewId); if (!viewDescriptor || !viewDescriptor.canMoveView) { - this.dialogService.show(Severity.Error, localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable."), [localize('ok', 'OK')]); + dialogService.show(Severity.Error, localize('moveFocusedView.error.nonMovableView', "The currently focused view is not movable."), [localize('ok', 'OK')]); return; } - const quickPick = this.quickInputService.createQuickPick(); + const quickPick = quickInputService.createQuickPick(); quickPick.placeholder = localize('moveFocusedView.selectDestination', "Select a Destination for the View"); quickPick.title = localize({ key: 'moveFocusedView.title', comment: ['{0} indicates the title of the view the user has selected to move.'] }, "View: Move {0}", viewDescriptor.name); const items: Array = []; - const currentContainer = this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!; - const currentLocation = this.viewDescriptorService.getViewLocationById(focusedViewId)!; - const isViewSolo = this.viewDescriptorService.getViewContainerModel(currentContainer).allViewDescriptors.length === 1; + const currentContainer = viewDescriptorService.getViewContainerByViewId(focusedViewId)!; + const currentLocation = viewDescriptorService.getViewLocationById(focusedViewId)!; + const isViewSolo = viewDescriptorService.getViewContainerModel(currentContainer).allViewDescriptors.length === 1; if (!(isViewSolo && currentLocation === ViewContainerLocation.Panel)) { items.push({ @@ -664,19 +663,19 @@ export class MoveFocusedViewAction extends Action { label: localize('sidebar', "Side Bar") }); - const pinnedViewlets = this.activityBarService.getVisibleViewContainerIds(); + const pinnedViewlets = activityBarService.getVisibleViewContainerIds(); items.push(...pinnedViewlets .filter(viewletId => { - if (viewletId === this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) { + if (viewletId === viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) { return false; } - return !this.viewDescriptorService.getViewContainerById(viewletId)!.rejectAddedViews; + return !viewDescriptorService.getViewContainerById(viewletId)!.rejectAddedViews; }) .map(viewletId => { return { id: viewletId, - label: this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerById(viewletId)!)!.title + label: viewDescriptorService.getViewContainerModel(viewDescriptorService.getViewContainerById(viewletId)!)!.title }; })); @@ -685,19 +684,19 @@ export class MoveFocusedViewAction extends Action { label: localize('panel', "Panel") }); - const pinnedPanels = this.panelService.getPinnedPanels(); + const pinnedPanels = panelService.getPinnedPanels(); items.push(...pinnedPanels .filter(panel => { - if (panel.id === this.viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) { + if (panel.id === viewDescriptorService.getViewContainerByViewId(focusedViewId)!.id) { return false; } - return !this.viewDescriptorService.getViewContainerById(panel.id)!.rejectAddedViews; + return !viewDescriptorService.getViewContainerById(panel.id)!.rejectAddedViews; }) .map(panel => { return { id: panel.id, - label: this.viewDescriptorService.getViewContainerModel(this.viewDescriptorService.getViewContainerById(panel.id)!)!.title + label: viewDescriptorService.getViewContainerModel(viewDescriptorService.getViewContainerById(panel.id)!)!.title }; })); @@ -707,14 +706,14 @@ export class MoveFocusedViewAction extends Action { const destination = quickPick.selectedItems[0]; if (destination.id === '_.panel.newcontainer') { - this.viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Panel); - this.viewsService.openView(focusedViewId, true); + viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Panel); + viewsService.openView(focusedViewId, true); } else if (destination.id === '_.sidebar.newcontainer') { - this.viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Sidebar); - this.viewsService.openView(focusedViewId, true); + viewDescriptorService.moveViewToLocation(viewDescriptor!, ViewContainerLocation.Sidebar); + viewsService.openView(focusedViewId, true); } else if (destination.id) { - this.viewDescriptorService.moveViewsToContainer([viewDescriptor], this.viewDescriptorService.getViewContainerById(destination.id)!); - this.viewsService.openView(focusedViewId, true); + viewDescriptorService.moveViewsToContainer([viewDescriptor], viewDescriptorService.getViewContainerById(destination.id)!); + viewsService.openView(focusedViewId, true); } quickPick.hide(); @@ -724,54 +723,56 @@ export class MoveFocusedViewAction extends Action { } } -registry.registerWorkbenchAction(SyncActionDescriptor.from(MoveFocusedViewAction), 'View: Move Focused View', CATEGORIES.View.value, FocusedViewContext.notEqualsTo('')); +registerAction2(MoveFocusedViewAction); -// --- Reset View Location with Command -export class ResetFocusedViewLocationAction extends Action { - static readonly ID = 'workbench.action.resetFocusedViewLocation'; - static readonly LABEL = localize('resetFocusedViewLocation', "Reset Focused View Location"); +// --- Reset Focused View Location - constructor( - id: string, - label: string, - @IViewDescriptorService private viewDescriptorService: IViewDescriptorService, - @IContextKeyService private contextKeyService: IContextKeyService, - @IDialogService private dialogService: IDialogService, - @IViewsService private viewsService: IViewsService - ) { - super(id, label); +registerAction2(class extends Action2 { + + constructor() { + super({ + id: 'workbench.action.resetFocusedViewLocation', + title: { + value: localize('resetFocusedViewLocation', "Reset Focused View Location"), + original: 'Reset Focused View Location' + }, + category: CATEGORIES.View, + f1: true, + precondition: FocusedViewContext.notEqualsTo('') + }); } - override async run(): Promise { - const focusedViewId = FocusedViewContext.getValue(this.contextKeyService); + run(accessor: ServicesAccessor): void { + const viewDescriptorService = accessor.get(IViewDescriptorService); + const contextKeyService = accessor.get(IContextKeyService); + const dialogService = accessor.get(IDialogService); + const viewsService = accessor.get(IViewsService); + + const focusedViewId = FocusedViewContext.getValue(contextKeyService); let viewDescriptor: IViewDescriptor | null = null; if (focusedViewId !== undefined && focusedViewId.trim() !== '') { - viewDescriptor = this.viewDescriptorService.getViewDescriptorById(focusedViewId); + viewDescriptor = viewDescriptorService.getViewDescriptorById(focusedViewId); } if (!viewDescriptor) { - this.dialogService.show(Severity.Error, localize('resetFocusedView.error.noFocusedView', "There is no view currently focused."), [localize('ok', 'OK')]); + dialogService.show(Severity.Error, localize('resetFocusedView.error.noFocusedView', "There is no view currently focused."), [localize('ok', 'OK')]); return; } - const defaultContainer = this.viewDescriptorService.getDefaultContainerById(viewDescriptor.id); - if (!defaultContainer || defaultContainer === this.viewDescriptorService.getViewContainerByViewId(viewDescriptor.id)) { + const defaultContainer = viewDescriptorService.getDefaultContainerById(viewDescriptor.id); + if (!defaultContainer || defaultContainer === viewDescriptorService.getViewContainerByViewId(viewDescriptor.id)) { return; } - this.viewDescriptorService.moveViewsToContainer([viewDescriptor], defaultContainer); - this.viewsService.openView(viewDescriptor.id, true); - + viewDescriptorService.moveViewsToContainer([viewDescriptor], defaultContainer); + viewsService.openView(viewDescriptor.id, true); } -} - -registry.registerWorkbenchAction(SyncActionDescriptor.from(ResetFocusedViewLocationAction), 'View: Reset Focused View Location', CATEGORIES.View.value, FocusedViewContext.notEqualsTo('')); - +}); // --- Resize View -export abstract class BaseResizeViewAction extends Action2 { +abstract class BaseResizeViewAction extends Action2 { protected static readonly RESIZE_INCREMENT = 6.5; // This is a media-size percentage @@ -800,7 +801,7 @@ export abstract class BaseResizeViewAction extends Action2 { } } -export class IncreaseViewSizeAction extends BaseResizeViewAction { +class IncreaseViewSizeAction extends BaseResizeViewAction { constructor() { super({ @@ -810,12 +811,12 @@ export class IncreaseViewSizeAction extends BaseResizeViewAction { }); } - async run(accessor: ServicesAccessor): Promise { + run(accessor: ServicesAccessor): void { this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT, BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService)); } } -export class IncreaseViewWidthAction extends BaseResizeViewAction { +class IncreaseViewWidthAction extends BaseResizeViewAction { constructor() { super({ @@ -825,12 +826,12 @@ export class IncreaseViewWidthAction extends BaseResizeViewAction { }); } - async run(accessor: ServicesAccessor): Promise { + run(accessor: ServicesAccessor): void { this.resizePart(BaseResizeViewAction.RESIZE_INCREMENT, 0, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART); } } -export class IncreaseViewHeightAction extends BaseResizeViewAction { +class IncreaseViewHeightAction extends BaseResizeViewAction { constructor() { super({ @@ -839,12 +840,13 @@ export class IncreaseViewHeightAction extends BaseResizeViewAction { f1: true }); } - async run(accessor: ServicesAccessor): Promise { + + run(accessor: ServicesAccessor): void { this.resizePart(0, BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART); } } -export class DecreaseViewSizeAction extends BaseResizeViewAction { +class DecreaseViewSizeAction extends BaseResizeViewAction { constructor() { super({ @@ -854,12 +856,12 @@ export class DecreaseViewSizeAction extends BaseResizeViewAction { }); } - async run(accessor: ServicesAccessor): Promise { + run(accessor: ServicesAccessor): void { this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT, -BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService)); } } -export class DecreaseViewWidthAction extends BaseResizeViewAction { +class DecreaseViewWidthAction extends BaseResizeViewAction { constructor() { super({ id: 'workbench.action.decreaseViewWidth', @@ -868,13 +870,12 @@ export class DecreaseViewWidthAction extends BaseResizeViewAction { }); } - async run(accessor: ServicesAccessor): Promise { + run(accessor: ServicesAccessor): void { this.resizePart(-BaseResizeViewAction.RESIZE_INCREMENT, 0, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART); } } - -export class DecreaseViewHeightAction extends BaseResizeViewAction { +class DecreaseViewHeightAction extends BaseResizeViewAction { constructor() { super({ @@ -884,7 +885,7 @@ export class DecreaseViewHeightAction extends BaseResizeViewAction { }); } - async run(accessor: ServicesAccessor): Promise { + run(accessor: ServicesAccessor): void { this.resizePart(0, -BaseResizeViewAction.RESIZE_INCREMENT, accessor.get(IWorkbenchLayoutService), Parts.EDITOR_PART); } } diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts index 21c6e8d0c79..fdfb3f17dac 100644 --- a/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts +++ b/src/vs/workbench/browser/parts/activitybar/activitybarPart.ts @@ -169,16 +169,7 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Menu const menuBarVisibility = getMenuBarVisibility(this.configurationService); if (menuBarVisibility === 'compact' || menuBarVisibility === 'hidden' || menuBarVisibility === 'toggle') { - topActions.push({ - id: 'toggleMenuVisibility', - label: localize('menu', "Menu"), - class: undefined, - tooltip: localize('menu', "Menu"), - checked: menuBarVisibility === 'compact', - enabled: true, - run: async () => this.configurationService.updateValue('window.menuBarVisibility', menuBarVisibility === 'compact' ? 'toggle' : 'compact'), - dispose: () => { } - }); + topActions.push(toAction({ id: 'toggleMenuVisibility', label: localize('menu', "Menu"), checked: menuBarVisibility === 'compact', run: () => this.configurationService.updateValue('window.menuBarVisibility', menuBarVisibility === 'compact' ? 'toggle' : 'compact') })); } if (topActions.length) { @@ -187,24 +178,14 @@ export class ActivitybarPart extends Part implements IActivityBarService { // Accounts actions.push(new Separator()); - actions.push({ - id: 'toggleAccountsVisibility', - label: localize('accounts', "Accounts"), - class: undefined, - tooltip: localize('accounts', "Accounts"), - checked: this.accountsVisibilityPreference, - enabled: true, - run: async () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference, - dispose: () => { } - }); - + actions.push(toAction({ id: 'toggleAccountsVisibility', label: localize('accounts', "Accounts"), checked: this.accountsVisibilityPreference, run: () => this.accountsVisibilityPreference = !this.accountsVisibilityPreference })); actions.push(new Separator()); // Toggle Sidebar - actions.push(this.instantiationService.createInstance(ToggleSidebarPositionAction, ToggleSidebarPositionAction.ID, ToggleSidebarPositionAction.getLabel(this.layoutService))); + actions.push(toAction({ id: ToggleSidebarPositionAction.ID, label: ToggleSidebarPositionAction.getLabel(this.layoutService), run: () => this.instantiationService.invokeFunction(accessor => new ToggleSidebarPositionAction().run(accessor)) })); // Toggle Activity Bar - actions.push(toAction({ id: ToggleActivityBarVisibilityAction.ID, label: localize('hideActivitBar', "Hide Activity Bar"), run: async () => this.instantiationService.invokeFunction(accessor => new ToggleActivityBarVisibilityAction().run(accessor)) })); + actions.push(toAction({ id: ToggleActivityBarVisibilityAction.ID, label: localize('hideActivitBar', "Hide Activity Bar"), run: () => this.instantiationService.invokeFunction(accessor => new ToggleActivityBarVisibilityAction().run(accessor)) })); }, getContextMenuActionsForComposite: compositeId => this.getContextMenuActionsForComposite(compositeId), getDefaultCompositeId: () => this.viewDescriptorService.getDefaultViewContainer(this.location)!.id, diff --git a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts index a2e88453c0d..7f8a6094a07 100644 --- a/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts +++ b/src/vs/workbench/browser/parts/editor/editorQuickAccess.ts @@ -68,7 +68,7 @@ export abstract class BaseEditorQuickAccessProvider extends PickerQuickAccessPro return super.provide(picker, token); } - protected getPicks(filter: string): Array { + protected _getPicks(filter: string): Array { const query = prepareQuery(filter); // Filtering diff --git a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts index 20fe201cd09..727124472c9 100644 --- a/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts +++ b/src/vs/workbench/browser/parts/statusbar/statusbarPart.ts @@ -14,7 +14,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { StatusbarAlignment, IStatusbarService, IStatusbarEntry, IStatusbarEntryAccessor } from 'vs/workbench/services/statusbar/common/statusbar'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator } from 'vs/base/common/actions'; +import { Action, IAction, WorkbenchActionExecutedEvent, WorkbenchActionExecutedClassification, Separator, toAction } from 'vs/base/common/actions'; import { IThemeService, registerThemingParticipant, ThemeColor } from 'vs/platform/theme/common/themeService'; import { STATUS_BAR_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_BACKGROUND, STATUS_BAR_ITEM_HOVER_BACKGROUND, STATUS_BAR_ITEM_ACTIVE_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND, STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_HOVER_BACKGROUND, STATUS_BAR_BORDER, STATUS_BAR_NO_FOLDER_FOREGROUND, STATUS_BAR_NO_FOLDER_BORDER } from 'vs/workbench/common/theme'; import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace'; @@ -625,7 +625,7 @@ export class StatusbarPart extends Part implements IStatusbarService { const actions: IAction[] = []; // Provide an action to hide the status bar at last - actions.push(this.instantiationService.createInstance(ToggleStatusbarVisibilityAction, ToggleStatusbarVisibilityAction.ID, localize('hideStatusBar', "Hide Status Bar"))); + actions.push(toAction({ id: ToggleStatusbarVisibilityAction.ID, label: localize('hideStatusBar', "Hide Status Bar"), run: () => this.instantiationService.invokeFunction(accessor => new ToggleStatusbarVisibilityAction().run(accessor)) })); actions.push(new Separator()); // Show an entry per known status entry diff --git a/src/vs/workbench/browser/parts/views/treeView.ts b/src/vs/workbench/browser/parts/views/treeView.ts index 075cf857ad1..e3dbbad6383 100644 --- a/src/vs/workbench/browser/parts/views/treeView.ts +++ b/src/vs/workbench/browser/parts/views/treeView.ts @@ -38,7 +38,9 @@ import { textLinkForeground, textCodeBlockBackground, focusBorder, listFilterMat import { isString } from 'vs/base/common/types'; import { ILabelService } from 'vs/platform/label/common/label'; import { IListVirtualDelegate, IIdentityProvider } from 'vs/base/browser/ui/list/list'; -import { ITreeRenderer, ITreeNode, IAsyncDataSource, ITreeContextMenuEvent } from 'vs/base/browser/ui/tree/tree'; +import { ITreeRenderer, ITreeNode, IAsyncDataSource, ITreeContextMenuEvent, ITreeDragAndDrop, ITreeDragOverReaction, TreeDragOverBubble } from 'vs/base/browser/ui/tree/tree'; +import { ElementsDragAndDropData } from 'vs/base/browser/ui/list/listView'; +import { IDragAndDropData } from 'vs/base/browser/dnd'; import { FuzzyScore, createMatches } from 'vs/base/common/filters'; import { CollapseAllAction } from 'vs/base/browser/ui/tree/treeDefaults'; import { isFalsyOrWhitespace } from 'vs/base/common/strings'; @@ -87,6 +89,7 @@ export class TreeViewPane extends ViewPane { if (options.titleDescription !== this.treeView.description) { this.updateTitleDescription(this.treeView.description); } + this.updateTreeVisibility(); } @@ -156,6 +159,7 @@ export class TreeView extends Disposable implements ITreeView { private treeContainer!: HTMLElement; private _messageValue: string | undefined; private _canSelectMany: boolean = false; + private _canDragAndDrop = false; private messageElement!: HTMLDivElement; private tree: Tree | undefined; private treeLabels: ResourceLabels | undefined; @@ -277,6 +281,12 @@ export class TreeView extends Disposable implements ITreeView { } return children; } + + async setParent(nodes: ITreeItem[], parentNode: ITreeItem): Promise { + if (dataProvider.setParent) { + await dataProvider.setParent(nodes, parentNode); + } + } }; if (this._dataProvider.onDidChangeEmpty) { this._register(this._dataProvider.onDidChangeEmpty(() => this._onDidChangeWelcomeState.fire())); @@ -329,6 +339,14 @@ export class TreeView extends Disposable implements ITreeView { this._canSelectMany = canSelectMany; } + get canDragAndDrop(): boolean { + return this._canDragAndDrop; + } + + set canDragAndDrop(canDragAndDrop: boolean) { + this._canDragAndDrop = canDragAndDrop; + } + get hasIconForParentNode(): boolean { return this._hasIconForParentNode; } @@ -503,6 +521,7 @@ export class TreeView extends Disposable implements ITreeView { return e.collapsibleState !== TreeItemCollapsibleState.Expanded; }, multipleSelectionSupport: this.canSelectMany, + dnd: this.canDragAndDrop ? this.instantiationService.createInstance(CustomTreeViewDragAndDrop, dataSource) : undefined, overrideStyles: { listBackground: this.viewLocation === ViewContainerLocation.Sidebar ? SIDE_BAR_BACKGROUND : PANEL_BACKGROUND } @@ -795,6 +814,18 @@ class TreeDataSource implements IAsyncDataSource { } return result; } + + async setParent(elements: ITreeItem[], newParentElement: ITreeItem): Promise { + if (this.treeView.dataProvider && this.treeView.dataProvider.setParent) { + try { + await this.withProgress(this.treeView.dataProvider.setParent(elements, newParentElement)); + } catch (e) { + if (!(e.message).startsWith('Bad progress location:')) { + throw e; + } + } + } + } } // todo@jrieken,sandy make this proper and contributable from extensions @@ -1183,3 +1214,32 @@ export class CustomTreeView extends TreeView { } } } + +export class CustomTreeViewDragAndDrop implements ITreeDragAndDrop { + constructor(private dataSource: TreeDataSource, @ILabelService private readonly labelService: ILabelService) { } + + onDragOver(data: IDragAndDropData, targetElement: ITreeItem, targetIndex: number, originalEvent: DragEvent): boolean | ITreeDragOverReaction { + return { accept: true, bubble: TreeDragOverBubble.Down, autoExpand: true }; + } + + getDragURI(element: ITreeItem): string | null { + return element.resourceUri ? URI.revive(element.resourceUri).toString() : element.handle; + } + + getDragLabel?(elements: ITreeItem[]): string | undefined { + if (elements.length > 1) { + return String(elements.length); + } + const element = elements[0]; + return element.label ? element.label.label : (element.resourceUri ? this.labelService.getUriLabel(URI.revive(element.resourceUri)) : undefined); + } + + async drop(data: IDragAndDropData, targetNode: ITreeItem | undefined, targetIndex: number | undefined, originalEvent: DragEvent): Promise { + if (data instanceof ElementsDragAndDropData) { + const elements = data.elements; + if (targetNode) { + await this.dataSource.setParent(elements, targetNode); + } + } + } +} diff --git a/src/vs/workbench/common/theme.ts b/src/vs/workbench/common/theme.ts index 272f767d2e8..2c1b2d50872 100644 --- a/src/vs/workbench/common/theme.ts +++ b/src/vs/workbench/common/theme.ts @@ -249,14 +249,6 @@ export const EDITOR_DRAG_AND_DROP_BACKGROUND = registerColor('editorGroup.dropBa hc: null }, localize('editorDragAndDropBackground', "Background color when dragging editors around. The color should have transparency so that the editor contents can still shine through.")); -// < --- Resource Viewer --- > - -export const IMAGE_PREVIEW_BORDER = registerColor('imagePreview.border', { - dark: Color.fromHex('#808080').transparent(0.35), - light: Color.fromHex('#808080').transparent(0.35), - hc: contrastBorder -}, localize('imagePreviewBorder', "Border color for image in image preview.")); - // < --- Panels --- > export const PANEL_BACKGROUND = registerColor('panel.background', { diff --git a/src/vs/workbench/common/views.ts b/src/vs/workbench/common/views.ts index e7b8d1d6145..484af52fd8f 100644 --- a/src/vs/workbench/common/views.ts +++ b/src/vs/workbench/common/views.ts @@ -634,6 +634,8 @@ export interface ITreeView extends IDisposable { canSelectMany: boolean; + canDragAndDrop: boolean; + message?: string; title: string; @@ -810,7 +812,7 @@ export interface ITreeViewDataProvider { readonly isTreeEmpty?: boolean; onDidChangeEmpty?: Event; getChildren(element?: ITreeItem): Promise; - + setParent?(elements: ITreeItem[], newParent: ITreeItem): Promise; } export interface IEditableData { diff --git a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts index dc1c0e064cb..cb02f6275e5 100644 --- a/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts +++ b/src/vs/workbench/contrib/codeEditor/browser/find/simpleFindWidget.ts @@ -69,7 +69,7 @@ export abstract class SimpleFindWidget extends Widget { this._updateHistoryDelayer = new Delayer(500); this.oninput(this._findInput.domNode, (e) => { - this.foundMatch = this.onInputChanged(); + this.foundMatch = this._onInputChanged(); this.updateButtons(this.foundMatch); this._delayedUpdateHistory(); }); @@ -138,25 +138,25 @@ export abstract class SimpleFindWidget extends Widget { }); this._focusTracker = this._register(dom.trackFocus(this._innerDomNode)); - this._register(this._focusTracker.onDidFocus(this.onFocusTrackerFocus.bind(this))); - this._register(this._focusTracker.onDidBlur(this.onFocusTrackerBlur.bind(this))); + this._register(this._focusTracker.onDidFocus(this._onFocusTrackerFocus.bind(this))); + this._register(this._focusTracker.onDidBlur(this._onFocusTrackerBlur.bind(this))); this._findInputFocusTracker = this._register(dom.trackFocus(this._findInput.domNode)); - this._register(this._findInputFocusTracker.onDidFocus(this.onFindInputFocusTrackerFocus.bind(this))); - this._register(this._findInputFocusTracker.onDidBlur(this.onFindInputFocusTrackerBlur.bind(this))); + this._register(this._findInputFocusTracker.onDidFocus(this._onFindInputFocusTrackerFocus.bind(this))); + this._register(this._findInputFocusTracker.onDidBlur(this._onFindInputFocusTrackerBlur.bind(this))); this._register(dom.addDisposableListener(this._innerDomNode, 'click', (event) => { event.stopPropagation(); })); } - protected abstract onInputChanged(): boolean; + protected abstract _onInputChanged(): boolean; protected abstract find(previous: boolean): void; protected abstract findFirst(): void; - protected abstract onFocusTrackerFocus(): void; - protected abstract onFocusTrackerBlur(): void; - protected abstract onFindInputFocusTrackerFocus(): void; - protected abstract onFindInputFocusTrackerBlur(): void; + protected abstract _onFocusTrackerFocus(): void; + protected abstract _onFocusTrackerBlur(): void; + protected abstract _onFindInputFocusTrackerFocus(): void; + protected abstract _onFindInputFocusTrackerBlur(): void; protected get inputValue() { return this._findInput.getValue(); diff --git a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts index 08f1b94ef06..3e5d30f7748 100644 --- a/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts +++ b/src/vs/workbench/contrib/customEditor/browser/customEditorInput.ts @@ -44,10 +44,6 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { const id = generateUuid(); const webview = accessor.get(IWebviewService).createWebviewOverlay(id, { customClasses: options?.customClasses }, {}, undefined); const input = instantiationService.createInstance(CustomEditorInput, resource, viewType, id, webview, { untitledDocumentData: untitledDocumentData }); - // If we're loading untitled file data we should ensure it's dirty - if (untitledDocumentData) { - input._defaultDirtyState = true; - } if (typeof group !== 'undefined') { input.updateGroup(group); } @@ -221,7 +217,10 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput { this._modelRef = this._register(assertIsDefined(await this.customEditorService.models.tryRetain(this.resource, this.viewType))); this._register(this._modelRef.object.onDidChangeDirty(() => this._onDidChangeDirty.fire())); this._register(this._modelRef.object.onDidChangeOrphaned(() => this._onDidChangeLabel.fire())); - + // If we're loading untitled file data we should ensure it's dirty + if (this._untitledDocumentData) { + this._defaultDirtyState = true; + } if (this.isDirty()) { this._onDidChangeDirty.fire(); } diff --git a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts index 9b114cc9c8d..619fe93edf7 100644 --- a/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts +++ b/src/vs/workbench/contrib/debug/browser/debugAdapterManager.ts @@ -247,7 +247,7 @@ export class AdapterManager implements IAdapterManager { } } - if (gettingConfigurations && candidates.length === 0) { + if ((!languageLabel || gettingConfigurations) && candidates.length === 0) { await this.activateDebuggers('onDebugInitialConfigurations'); candidates = this.debuggers.filter(dbg => dbg.hasInitialConfiguration() || dbg.hasConfigurationProvider()); } diff --git a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts index 3c920d1366f..e29b61897e2 100644 --- a/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts +++ b/src/vs/workbench/contrib/debug/browser/debugQuickAccess.ts @@ -33,7 +33,7 @@ export class StartDebugQuickAccessProvider extends PickerQuickAccessProvider { + protected async _getPicks(filter: string): Promise<(IQuickPickSeparator | IPickerQuickAccessItem)[]> { const picks: Array = []; picks.push({ type: 'separator', label: 'launch.json' }); diff --git a/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts b/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts index 921231f3f86..8aecf0ed0c3 100644 --- a/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts +++ b/src/vs/workbench/contrib/extensions/browser/extensionsQuickAccess.ts @@ -28,7 +28,7 @@ export class InstallExtensionQuickAccessProvider extends PickerQuickAccessProvid super(InstallExtensionQuickAccessProvider.PREFIX); } - protected getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array | Promise> { + protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array | Promise> { // Nothing typed if (!filter) { @@ -100,7 +100,7 @@ export class ManageExtensionsQuickAccessProvider extends PickerQuickAccessProvid super(ManageExtensionsQuickAccessProvider.PREFIX); } - protected getPicks(): Array { + protected _getPicks(): Array { return [{ label: localize('manage', "Press Enter to manage your extensions."), accept: () => openExtensionsViewlet(this.viewletService) diff --git a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts index 36890e2ac3d..33cd340d10f 100644 --- a/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts +++ b/src/vs/workbench/contrib/extensions/test/electron-browser/extensionsWorkbenchService.test.ts @@ -176,14 +176,14 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.strictEqual(4, actual.rating); assert.strictEqual(100, actual.ratingCount); assert.strictEqual(false, actual.outdated); - assert.deepEqual(['pub.1', 'pub.2'], actual.dependencies); + assert.deepStrictEqual(['pub.1', 'pub.2'], actual.dependencies); }); }); test('test for empty installed extensions', async () => { testObject = await aWorkbenchService(); - assert.deepEqual([], testObject.local); + assert.deepStrictEqual([], testObject.local); }); test('test for installed extensions', async () => { @@ -233,7 +233,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.strictEqual(undefined, actual.rating); assert.strictEqual(undefined, actual.ratingCount); assert.strictEqual(false, actual.outdated); - assert.deepEqual(['pub.1', 'pub.2'], actual.dependencies); + assert.deepStrictEqual(['pub.1', 'pub.2'], actual.dependencies); actual = actuals[1]; assert.strictEqual(ExtensionType.System, actual.type); @@ -251,7 +251,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.strictEqual(undefined, actual.rating); assert.strictEqual(undefined, actual.ratingCount); assert.strictEqual(false, actual.outdated); - assert.deepEqual([], actual.dependencies); + assert.deepStrictEqual([], actual.dependencies); }); test('test installed extensions get syncs with gallery', async () => { @@ -327,7 +327,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.strictEqual(4, actual.rating); assert.strictEqual(100, actual.ratingCount); assert.strictEqual(true, actual.outdated); - assert.deepEqual(['pub.1'], actual.dependencies); + assert.deepStrictEqual(['pub.1'], actual.dependencies); actual = actuals[1]; assert.strictEqual(ExtensionType.System, actual.type); @@ -345,7 +345,7 @@ suite('ExtensionsWorkbenchServiceTest', () => { assert.strictEqual(undefined, actual.rating); assert.strictEqual(undefined, actual.ratingCount); assert.strictEqual(false, actual.outdated); - assert.deepEqual([], actual.dependencies); + assert.deepStrictEqual([], actual.dependencies); }); }); diff --git a/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts b/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts new file mode 100644 index 00000000000..02d01cb3bb9 --- /dev/null +++ b/src/vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution.ts @@ -0,0 +1,133 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as nls from 'vs/nls'; +import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; +import { URI } from 'vs/base/common/uri'; +import { MenuId, MenuRegistry, IMenuItem } from 'vs/platform/actions/common/actions'; +import { ITerminalService as IIntegratedTerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ResourceContextKey } from 'vs/workbench/common/resources'; +import { IFileService } from 'vs/platform/files/common/files'; +import { IListService } from 'vs/platform/list/browser/listService'; +import { getMultiSelectedResources, IExplorerService } from 'vs/workbench/contrib/files/browser/files'; +import { CommandsRegistry } from 'vs/platform/commands/common/commands'; +import { Schemas } from 'vs/base/common/network'; +import { distinct } from 'vs/base/common/arrays'; +import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; +import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; +import { optional } from 'vs/platform/instantiation/common/instantiation'; +import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; +import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; +import { Disposable } from 'vs/base/common/lifecycle'; +import { isWeb, isWindows } from 'vs/base/common/platform'; +import { dirname, basename } from 'vs/base/common/path'; +import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +import { Registry } from 'vs/platform/registry/common/platform'; +import { IExternalTerminalConfiguration, IExternalTerminalService } from 'vs/platform/externalTerminal/common/externalTerminal'; + +const OPEN_IN_TERMINAL_COMMAND_ID = 'openInTerminal'; +CommandsRegistry.registerCommand({ + id: OPEN_IN_TERMINAL_COMMAND_ID, + handler: (accessor, resource: URI) => { + const configurationService = accessor.get(IConfigurationService); + const editorService = accessor.get(IEditorService); + const fileService = accessor.get(IFileService); + const terminalService: IExternalTerminalService | undefined = accessor.get(IExternalTerminalService, optional); + const integratedTerminalService = accessor.get(IIntegratedTerminalService); + const remoteAgentService = accessor.get(IRemoteAgentService); + + const resources = getMultiSelectedResources(resource, accessor.get(IListService), editorService, accessor.get(IExplorerService)); + return fileService.resolveAll(resources.map(r => ({ resource: r }))).then(async stats => { + const targets = distinct(stats.filter(data => data.success)); + // Always use integrated terminal when using a remote + const useIntegratedTerminal = remoteAgentService.getConnection() || configurationService.getValue().terminal.explorerKind === 'integrated'; + if (useIntegratedTerminal) { + // TODO: Use uri for cwd in createterminal + const opened: { [path: string]: boolean } = {}; + targets.map(({ stat }) => { + const resource = stat!.resource; + if (stat!.isDirectory) { + return resource; + } + return URI.from({ + scheme: resource.scheme, + authority: resource.authority, + fragment: resource.fragment, + query: resource.query, + path: dirname(resource.path) + }); + }).forEach(cwd => { + if (opened[cwd.path]) { + return; + } + opened[cwd.path] = true; + const instance = integratedTerminalService.createTerminal({ cwd }); + if (instance && (resources.length === 1 || !resource || cwd.path === resource.path || cwd.path === dirname(resource.path))) { + integratedTerminalService.setActiveInstance(instance); + integratedTerminalService.showPanel(true); + } + }); + } else { + distinct(targets.map(({ stat }) => stat!.isDirectory ? stat!.resource.fsPath : dirname(stat!.resource.fsPath))).forEach(cwd => { + terminalService!.openTerminal(cwd); + }); + } + }); + } +}); + +export class ExternalTerminalContribution extends Disposable implements IWorkbenchContribution { + private _openInTerminalMenuItem: IMenuItem; + + constructor( + @IConfigurationService private readonly _configurationService: IConfigurationService + ) { + super(); + + this._openInTerminalMenuItem = { + group: 'navigation', + order: 30, + command: { + id: OPEN_IN_TERMINAL_COMMAND_ID, + title: nls.localize('scopedConsoleAction', "Open in Terminal") + }, + when: ContextKeyExpr.or(ResourceContextKey.Scheme.isEqualTo(Schemas.file), ResourceContextKey.Scheme.isEqualTo(Schemas.vscodeRemote)) + }; + MenuRegistry.appendMenuItem(MenuId.OpenEditorsContext, this._openInTerminalMenuItem); + MenuRegistry.appendMenuItem(MenuId.ExplorerContext, this._openInTerminalMenuItem); + + this._configurationService.onDidChangeConfiguration(e => { + if (e.affectsConfiguration('terminal.explorerKind') || e.affectsConfiguration('terminal.external')) { + this._refreshOpenInTerminalMenuItemTitle(); + } + }); + this._refreshOpenInTerminalMenuItemTitle(); + } + + private _refreshOpenInTerminalMenuItemTitle(): void { + if (isWeb) { + this._openInTerminalMenuItem.command.title = nls.localize('scopedConsoleAction.integrated', "Open in Integrated Terminal"); + return; + } + + const config = this._configurationService.getValue().terminal; + if (config.explorerKind === 'integrated') { + this._openInTerminalMenuItem.command.title = nls.localize('scopedConsoleAction.integrated', "Open in Integrated Terminal"); + return; + } + + if (isWindows && config.external.windowsExec) { + const file = basename(config.external.windowsExec); + if (file === 'wt' || file === 'wt.exe') { + this._openInTerminalMenuItem.command.title = nls.localize('scopedConsoleAction.wt', "Open in Windows Terminal"); + return; + } + } + + this._openInTerminalMenuItem.command.title = nls.localize('scopedConsoleAction.external', "Open in External Terminal"); + } +} + +Registry.as(WorkbenchExtensions.Workbench).registerWorkbenchContribution(ExternalTerminalContribution, LifecyclePhase.Restored); diff --git a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts index a1a01c70801..f0129e56073 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookEditorWidget.ts @@ -334,9 +334,9 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor this.scopedContextKeyService = contextKeyService.createScoped(this._overlayContainer); this.instantiationService = instantiationService.createChild(new ServiceCollection([IContextKeyService, this.scopedContextKeyService])); - this._register(instantiationService.createInstance(NotebookEditorContextKeys, this)); + this._register(this.instantiationService.createInstance(NotebookEditorContextKeys, this)); - this._kernelManger = instantiationService.createInstance(NotebookEditorKernelManager); + this._kernelManger = this.instantiationService.createInstance(NotebookEditorKernelManager); this._register(notebookKernelService.onDidChangeNotebookKernelBinding(e => { if (isEqual(e.notebook, this.viewModel?.uri)) { this._loadKernelPreloads(); @@ -925,7 +925,13 @@ export class NotebookEditorWidget extends Disposable implements INotebookEditor const cell = this.viewModel.viewCells.find(cell => cell.uri.toString() === cellOptions.resource.toString()); if (cell) { this.focusElement(cell); - await this.revealInCenterIfOutsideViewportAsync(cell); + const selection = cellOptions.options?.selection; + if (selection) { + await this.revealLineInCenterIfOutsideViewportAsync(cell, selection.startLineNumber); + } else { + await this.revealInCenterIfOutsideViewportAsync(cell); + } + const editor = this._renderedEditors.get(cell)!; if (editor) { if (cellOptions.options?.selection) { diff --git a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts index 5a59e6e2f9e..7ea304f760f 100644 --- a/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts +++ b/src/vs/workbench/contrib/notebook/browser/notebookServiceImpl.ts @@ -23,6 +23,7 @@ import { IFileService } from 'vs/platform/files/common/files'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { Registry } from 'vs/platform/registry/common/platform'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; +import { IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust'; import { NotebookExtensionDescription } from 'vs/workbench/api/common/extHost.protocol'; import { EditorExtensions, IEditorInput } from 'vs/workbench/common/editor'; import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput'; @@ -32,7 +33,7 @@ import { NotebookEditorOptions, updateEditorTopPadding } from 'vs/workbench/cont import { NotebookDiffEditorInput } from 'vs/workbench/contrib/notebook/browser/notebookDiffEditorInput'; import { NotebookCellTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookCellTextModel'; import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel'; -import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookMarkupRendererInfo, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; +import { ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, BUILTIN_RENDERER_ID, CellUri, DisplayOrderKey, INotebookExclusiveDocumentFilter, INotebookMarkupRendererInfo, INotebookRendererInfo, INotebookTextModel, IOrderedMimeType, IOutputDto, mimeTypeIsAlwaysSecure, mimeTypeSupportedByCore, NotebookDataDto, NotebookEditorPriority, NotebookRendererMatch, NotebookTextDiffEditorPreview, RENDERER_NOT_AVAILABLE, sortMimeTypes, TransientOptions } from 'vs/workbench/contrib/notebook/common/notebookCommon'; import { NotebookEditorInput } from 'vs/workbench/contrib/notebook/common/notebookEditorInput'; import { NotebookMarkupRendererInfo as NotebookMarkupRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookMarkdownRenderer'; import { NotebookOutputRendererInfo } from 'vs/workbench/contrib/notebook/common/notebookOutputRenderer'; @@ -148,7 +149,7 @@ export class NotebookProviderInfoStore extends Disposable { if (data) { notebookUri = data.notebook; - cellOptions = { resource: resource }; + cellOptions = { resource: resource, options: options }; } const notebookOptions = new NotebookEditorOptions({ ...options, cellOptions }); @@ -316,6 +317,7 @@ export class NotebookService extends Disposable implements INotebookService, IEd @IInstantiationService private readonly _instantiationService: IInstantiationService, @ICodeEditorService private readonly _codeEditorService: ICodeEditorService, @IConfigurationService private readonly configurationService: IConfigurationService, + @IWorkspaceTrustManagementService private readonly workspaceTrustManagementService: IWorkspaceTrustManagementService, ) { super(); @@ -614,7 +616,7 @@ export class NotebookService extends Disposable implements INotebookService, IEd orderMimeTypes.push({ mimeType: mimeType, rendererId: BUILTIN_RENDERER_ID, - isTrusted: true // TODO@roblourens mimeTypeIsAlwaysSecure(mimeType) || this.workspaceTrustManagementService.isWorkpaceTrusted() + isTrusted: mimeTypeIsAlwaysSecure(mimeType) || this.workspaceTrustManagementService.isWorkpaceTrusted() }); } } else { @@ -622,7 +624,7 @@ export class NotebookService extends Disposable implements INotebookService, IEd orderMimeTypes.push({ mimeType: mimeType, rendererId: BUILTIN_RENDERER_ID, - isTrusted: true // TODO@roblourens mimeTypeIsAlwaysSecure(mimeType) || this.workspaceTrustManagementService.isWorkpaceTrusted() + isTrusted: mimeTypeIsAlwaysSecure(mimeType) || this.workspaceTrustManagementService.isWorkpaceTrusted() }); } else { orderMimeTypes.push({ diff --git a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts index 1417f2e0e7e..398a6ee248c 100644 --- a/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts +++ b/src/vs/workbench/contrib/preferences/browser/preferencesEditor.ts @@ -307,7 +307,6 @@ export class PreferencesEditor extends EditorPane { } const data = { - filter, durations, counts, requestCount: metadata && metadata['nlpResult'] && metadata['nlpResult'].requestCount @@ -315,7 +314,6 @@ export class PreferencesEditor extends EditorPane { /* __GDPR__ "defaultSettings.filter" : { - "filter": { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "durations.nlpresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "counts.nlpresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "durations.filterresult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, @@ -684,7 +682,6 @@ class PreferencesRenderersController extends Disposable { }; if (this.lastFilterResult) { - data['query'] = this.lastFilterResult.query; data['editableSide'] = !!fromEditableSettings; const nlpMetadata = this.lastFilterResult.metadata && this.lastFilterResult.metadata['nlpResult']; @@ -704,7 +701,6 @@ class PreferencesRenderersController extends Disposable { /* __GDPR__ "defaultSettingsActions.copySetting" : { "userConfigurationKeys" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "query" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "displayIdx" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, diff --git a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts index 67213562318..25e3ff88fea 100644 --- a/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts +++ b/src/vs/workbench/contrib/preferences/browser/settingsEditor2.ts @@ -932,7 +932,6 @@ export class SettingsEditor2 extends EditorPane { const data = { key: props.key, - query: props.query, groupId, nlpIndex, displayIndex, @@ -944,7 +943,6 @@ export class SettingsEditor2 extends EditorPane { /* __GDPR__ "settingsEditor.settingModified" : { "key" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, - "query" : { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "groupId" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }, "nlpIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "displayIndex" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, @@ -1267,7 +1265,6 @@ export class SettingsEditor2 extends EditorPane { const requestCount = nlpMetadata && nlpMetadata.requestCount; const data = { - query, durations, counts, requestCount @@ -1275,7 +1272,6 @@ export class SettingsEditor2 extends EditorPane { /* __GDPR__ "settingsEditor.filter" : { - "query": { "classification": "CustomerContent", "purpose": "FeatureInsight" }, "durations.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "counts.nlpResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, "counts.filterResult" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }, diff --git a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts index 4590ddd4cde..f29bdac9e6a 100644 --- a/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts +++ b/src/vs/workbench/contrib/quickaccess/browser/viewQuickAccess.ts @@ -48,7 +48,7 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider { + protected _getPicks(filter: string): Array { const filteredViewEntries = this.doGetViewPickItems().filter(entry => { if (!filter) { return true; @@ -147,9 +147,9 @@ export class ViewQuickAccessProvider extends PickerQuickAccessProvider { - tab.terminalInstances.forEach((terminal, terminalIndex) => { - const label = localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title); + this.terminalService.terminalGroups.forEach((group, groupIndex) => { + group.terminalInstances.forEach((terminal, terminalIndex) => { + const label = localize('terminalTitle', "{0}: {1}", `${groupIndex + 1}.${terminalIndex + 1}`, terminal.title); viewEntries.push({ label, containerLabel: localize('terminals', "Terminal"), diff --git a/src/vs/workbench/contrib/remote/browser/tunnelView.ts b/src/vs/workbench/contrib/remote/browser/tunnelView.ts index a88776c30c5..10faa18ffe3 100644 --- a/src/vs/workbench/contrib/remote/browser/tunnelView.ts +++ b/src/vs/workbench/contrib/remote/browser/tunnelView.ts @@ -965,10 +965,14 @@ namespace LabelTunnelAction { export const LABEL = nls.localize('remote.tunnel.label', "Set Port Label"); export const COMMAND_ID_KEYWORD = 'label'; + function isITunnelItem(item: any): item is ITunnelItem { + return item && item.tunnelType && item.remoteHost && item.source; + } + export function handler(): ICommandHandler { return async (accessor, arg): Promise<{ port: number, label: string } | undefined> => { - const context = (arg !== undefined || arg instanceof TunnelItem) ? arg : accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName); - if (context instanceof TunnelItem) { + const context = isITunnelItem(arg) ? arg : accessor.get(IContextKeyService).getContextKeyValue(TunnelViewSelectionKeyName); + if (context) { return new Promise(resolve => { const remoteExplorerService = accessor.get(IRemoteExplorerService); const startingValue = context.name ? context.name : `${context.remotePort}`; @@ -1563,7 +1567,7 @@ MenuRegistry.appendMenuItem(MenuId.TunnelLocalAddressInline, ({ ContextKeyExpr.or(TunnelTypeContextKey.isEqualTo(TunnelType.Forwarded), TunnelTypeContextKey.isEqualTo(TunnelType.Detected))) })); -export const portWithRunningProcessForeground = registerColor('ports.iconRunningProcessforeground', { +export const portWithRunningProcessForeground = registerColor('ports.iconRunningProcessForeground', { light: STATUS_BAR_HOST_NAME_BACKGROUND, dark: STATUS_BAR_HOST_NAME_BACKGROUND, hc: STATUS_BAR_HOST_NAME_BACKGROUND diff --git a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts index fce8acd1d97..6b923801cb9 100644 --- a/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/anythingQuickAccess.ts @@ -259,7 +259,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider this.clearDecorations(activeEditorControl)); } - protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Picks | Promise> | FastAndSlowPicks | null { + protected _getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Picks | Promise> | FastAndSlowPicks | null { // Find a suitable range from the pattern looking for ":", "#" or "," // unless we have the `@` editor symbol character inside the filter diff --git a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts index 3c7d555dada..eaa56c70ef2 100644 --- a/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts +++ b/src/vs/workbench/contrib/search/browser/symbolsQuickAccess.ts @@ -83,7 +83,7 @@ export class SymbolsQuickAccessProvider extends PickerQuickAccessProvider> { + protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { return this.getSymbolPicks(filter, undefined, token); } diff --git a/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts b/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts index d1e61d327a1..bdee1a72ab1 100644 --- a/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts +++ b/src/vs/workbench/contrib/search/test/browser/queryBuilder.test.ts @@ -554,12 +554,12 @@ suite('QueryBuilder', () => { suite('parseSearchPaths', () => { test('simple includes', () => { function testSimpleIncludes(includePattern: string, expectedPatterns: string[]): void { + const result = queryBuilder.parseSearchPaths(includePattern); assert.deepStrictEqual( - queryBuilder.parseSearchPaths(includePattern), - { - pattern: patternsToIExpression(...expectedPatterns) - }, + { ...result.pattern }, + patternsToIExpression(...expectedPatterns), includePattern); + assert.strictEqual(result.searchPaths, undefined); } [ @@ -1070,18 +1070,18 @@ export function assertEqualQueries(actual: ITextQuery | IFileQuery, expected: IT actual.excludePattern = normalizeExpression(actual.excludePattern); cleanUndefinedQueryValues(actual); - assert.deepEqual(actual, expected); + assert.deepStrictEqual(actual, expected); } export function assertEqualSearchPathResults(actual: ISearchPathsInfo, expected: ISearchPathsInfo, message?: string): void { cleanUndefinedQueryValues(actual); - assert.deepStrictEqual(actual.pattern, expected.pattern, message); + assert.deepStrictEqual({ ...actual.pattern }, { ...expected.pattern }, message); assert.strictEqual(actual.searchPaths && actual.searchPaths.length, expected.searchPaths && expected.searchPaths.length); if (actual.searchPaths) { actual.searchPaths.forEach((searchPath, i) => { const expectedSearchPath = expected.searchPaths![i]; - assert.deepStrictEqual(searchPath.pattern, expectedSearchPath.pattern); + assert.deepStrictEqual(searchPath.pattern && { ...searchPath.pattern }, expectedSearchPath.pattern); assert.strictEqual(searchPath.searchPath.toString(), expectedSearchPath.searchPath.toString()); }); } @@ -1110,9 +1110,9 @@ export function globalGlob(pattern: string): string[] { ]; } -export function patternsToIExpression(...patterns: string[]): IExpression { +export function patternsToIExpression(...patterns: string[]): IExpression | undefined { return patterns.length ? - patterns.reduce((glob, cur) => { glob[cur] = true; return glob; }, Object.create(null)) : + patterns.reduce((glob, cur) => { glob[cur] = true; return glob; }, {} as IExpression) : undefined; } @@ -1133,7 +1133,7 @@ export function normalizeExpression(expression: IExpression | undefined): IExpre return expression; } - const normalized = Object.create(null); + const normalized: IExpression = {}; Object.keys(expression).forEach(key => { normalized[key.replace(/\\/g, '/')] = expression[key]; }); diff --git a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts index c03ff2c809e..67cd6d0c006 100644 --- a/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts +++ b/src/vs/workbench/contrib/searchEditor/browser/searchEditor.ts @@ -27,6 +27,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextViewService } from 'vs/platform/contextview/browser/contextView'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; import { ILabelService } from 'vs/platform/label/common/label'; import { IEditorProgressService, LongRunningOperation } from 'vs/platform/progress/common/progress'; import { IStorageService } from 'vs/platform/storage/common/storage'; @@ -78,12 +79,10 @@ export class SearchEditor extends BaseTextEditor { private runSearchDelayer = new Delayer(0); private pauseSearching: boolean = false; private showingIncludesExcludes: boolean = false; - private inSearchEditorContextKey: IContextKey; - private inputFocusContextKey: IContextKey; private searchOperation: LongRunningOperation; private searchHistoryDelayer: Delayer; private messageDisposables: DisposableStore; - private readonly container = DOM.$('.search-editor'); + private container: HTMLElement; private searchModel: SearchModel; private ongoingOperations: number = 0; @@ -106,10 +105,8 @@ export class SearchEditor extends BaseTextEditor { @IFileService private readonly fileService: IFileService ) { super(SearchEditor.ID, telemetryService, instantiationService, storageService, textResourceService, themeService, editorService, editorGroupService); + this.container = DOM.$('.search-editor'); - this.inSearchEditorContextKey = InSearchEditor.bindTo(this.scopedContextKeyService); - this.inSearchEditorContextKey.set(true); - this.inputFocusContextKey = InputBoxFocusedKey.bindTo(this.scopedContextKeyService); this.searchOperation = this._register(new LongRunningOperation(progressService)); this._register(this.messageDisposables = new DisposableStore()); @@ -118,29 +115,34 @@ export class SearchEditor extends BaseTextEditor { this.searchModel = this._register(this.instantiationService.createInstance(SearchModel)); } - private _scopedContextKeyService = this.contextKeyService.createScoped(this.container); - override get scopedContextKeyService(): IContextKeyService { - return this._scopedContextKeyService; - } - override createEditor(parent: HTMLElement) { DOM.append(parent, this.container); + this.queryEditorContainer = DOM.append(this.container, DOM.$('.query-container')); + const searchResultContainer = DOM.append(this.container, DOM.$('.search-results')); + super.createEditor(searchResultContainer); + this.registerEditorListeners(); - this.createQueryEditor(this.container); - this.createResultsEditor(this.container); + const scopedContextKeyService = assertIsDefined(this.scopedContextKeyService); + InSearchEditor.bindTo(scopedContextKeyService).set(true); + + this.createQueryEditor( + this.queryEditorContainer, + this.instantiationService.createChild(new ServiceCollection([IContextKeyService, scopedContextKeyService])), + InputBoxFocusedKey.bindTo(scopedContextKeyService) + ); } - private createQueryEditor(parent: HTMLElement) { - this.queryEditorContainer = DOM.append(parent, DOM.$('.query-container')); - this.queryEditorWidget = this._register(this.instantiationService.createInstance(SearchWidget, this.queryEditorContainer, { _hideReplaceToggle: true, showContextToggle: true })); + + private createQueryEditor(container: HTMLElement, scopedInstantiationService: IInstantiationService, inputBoxFocusedContextKey: IContextKey) { + this.queryEditorWidget = this._register(scopedInstantiationService.createInstance(SearchWidget, container, { _hideReplaceToggle: true, showContextToggle: true })); this._register(this.queryEditorWidget.onReplaceToggled(() => this.reLayout())); this._register(this.queryEditorWidget.onDidHeightChange(() => this.reLayout())); - this.queryEditorWidget.onSearchSubmit(({ delay }) => this.triggerSearch({ delay })); - this.queryEditorWidget.searchInput.onDidOptionChange(() => this.triggerSearch({ resetCursor: false })); - this.queryEditorWidget.onDidToggleContext(() => this.triggerSearch({ resetCursor: false })); + this._register(this.queryEditorWidget.onSearchSubmit(({ delay }) => this.triggerSearch({ delay }))); + this._register(this.queryEditorWidget.searchInput.onDidOptionChange(() => this.triggerSearch({ resetCursor: false }))); + this._register(this.queryEditorWidget.onDidToggleContext(() => this.triggerSearch({ resetCursor: false }))); // Includes/Excludes Dropdown - this.includesExcludesContainer = DOM.append(this.queryEditorContainer, DOM.$('.includes-excludes')); + this.includesExcludesContainer = DOM.append(container, DOM.$('.includes-excludes')); // Toggle query details button this.toggleQueryDetailsButton = DOM.append(this.includesExcludesContainer, DOM.$('.expand' + ThemeIcon.asCSSSelector(searchDetailsIcon), { tabindex: 0, role: 'button', title: localize('moreSearch', "Toggle Search Details") })); @@ -172,7 +174,7 @@ export class SearchEditor extends BaseTextEditor { const folderIncludesList = DOM.append(this.includesExcludesContainer, DOM.$('.file-types.includes')); const filesToIncludeTitle = localize('searchScope.includes', "files to include"); DOM.append(folderIncludesList, DOM.$('h4', undefined, filesToIncludeTitle)); - this.inputPatternIncludes = this._register(this.instantiationService.createInstance(IncludePatternInputWidget, folderIncludesList, this.contextViewService, { + this.inputPatternIncludes = this._register(scopedInstantiationService.createInstance(IncludePatternInputWidget, folderIncludesList, this.contextViewService, { ariaLabel: localize('label.includes', 'Search Include Patterns'), })); this.inputPatternIncludes.onSubmit(triggeredOnType => this.triggerSearch({ resetCursor: false, delay: triggeredOnType ? this.searchConfig.searchOnTypeDebouncePeriod : 0 })); @@ -182,7 +184,7 @@ export class SearchEditor extends BaseTextEditor { const excludesList = DOM.append(this.includesExcludesContainer, DOM.$('.file-types.excludes')); const excludesTitle = localize('searchScope.excludes', "files to exclude"); DOM.append(excludesList, DOM.$('h4', undefined, excludesTitle)); - this.inputPatternExcludes = this._register(this.instantiationService.createInstance(ExcludePatternInputWidget, excludesList, this.contextViewService, { + this.inputPatternExcludes = this._register(scopedInstantiationService.createInstance(ExcludePatternInputWidget, excludesList, this.contextViewService, { ariaLabel: localize('label.excludes', 'Search Exclude Patterns'), })); this.inputPatternExcludes.onSubmit(triggeredOnType => this.triggerSearch({ resetCursor: false, delay: triggeredOnType ? this.searchConfig.searchOnTypeDebouncePeriod : 0 })); @@ -192,7 +194,13 @@ export class SearchEditor extends BaseTextEditor { this._register(attachInputBoxStyler(input, this.themeService, { inputBorder: searchEditorTextInputBorder }))); // Messages - this.messageBox = DOM.append(this.queryEditorContainer, DOM.$('.messages')); + this.messageBox = DOM.append(container, DOM.$('.messages')); + + [this.queryEditorWidget.searchInputFocusTracker, this.queryEditorWidget.replaceInputFocusTracker, this.inputPatternExcludes.inputFocusTracker, this.inputPatternIncludes.inputFocusTracker] + .forEach(tracker => { + this._register(tracker.onDidFocus(() => setTimeout(() => inputBoxFocusedContextKey.set(true), 0))); + this._register(tracker.onDidBlur(() => inputBoxFocusedContextKey.set(false))); + }); } private toggleRunAgainMessage(show: boolean) { @@ -208,9 +216,7 @@ export class SearchEditor extends BaseTextEditor { } } - private createResultsEditor(parent: HTMLElement) { - const searchResultContainer = DOM.append(parent, DOM.$('.search-results')); - super.createEditor(searchResultContainer); + private registerEditorListeners() { this.searchResultEditor = super.getControl() as CodeEditorWidget; this.searchResultEditor.onMouseUp(e => { if (e.event.detail === 2) { @@ -232,12 +238,6 @@ export class SearchEditor extends BaseTextEditor { this._register(this.onDidBlur(() => this.saveViewState())); this._register(this.searchResultEditor.onDidChangeModelContent(() => this.getInput()?.setDirty(true))); - - [this.queryEditorWidget.searchInputFocusTracker, this.queryEditorWidget.replaceInputFocusTracker, this.inputPatternExcludes.inputFocusTracker, this.inputPatternIncludes.inputFocusTracker] - .forEach(tracker => { - this._register(tracker.onDidFocus(() => setTimeout(() => this.inputFocusContextKey.set(true), 0))); - this._register(tracker.onDidBlur(() => this.inputFocusContextKey.set(false))); - }); } override getControl() { diff --git a/src/vs/workbench/contrib/surveys/browser/ces.contribution.ts b/src/vs/workbench/contrib/surveys/browser/ces.contribution.ts index c8c3fbf2e7c..d2c856bc64d 100644 --- a/src/vs/workbench/contrib/surveys/browser/ces.contribution.ts +++ b/src/vs/workbench/contrib/surveys/browser/ces.contribution.ts @@ -78,7 +78,7 @@ class CESContribution extends Disposable implements IWorkbenchContribution { run: () => { sendTelemetry('accept'); this.telemetryService.getTelemetryInfo().then(info => { - this.openerService.open(URI.parse(`${this.productService.cesSurveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(this.productService.version)}&m=${encodeURIComponent(info.machineId)}}`)); + this.openerService.open(URI.parse(`${this.productService.cesSurveyUrl}?o=${encodeURIComponent(platform)}&v=${encodeURIComponent(this.productService.version)}&m=${encodeURIComponent(info.machineId)}`)); this.skipSurvey(); }); } diff --git a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts index 1fa918e9725..d38bcf4a660 100644 --- a/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts +++ b/src/vs/workbench/contrib/tasks/browser/abstractTaskService.ts @@ -3139,11 +3139,24 @@ export abstract class AbstractTaskService extends Disposable implements ITaskSer if (!this.canRunCommand()) { return; } - const activeTasks: Task[] = await this.getActiveTasks(); + const activeTasksPromise: Promise = this.getActiveTasks(); + const activeTasks: Task[] = await activeTasksPromise; + let group: string | undefined; if (activeTasks.length === 1) { this._taskSystem!.revealTask(activeTasks[0]); + } else if (activeTasks.every((task) => { + if (InMemoryTask.is(task)) { + return false; + } + + if (!group) { + group = task.command.presentation?.group; + } + return task.command.presentation?.group && (task.command.presentation.group === group); + })) { + this._taskSystem!.revealTask(activeTasks[0]); } else { - this.showQuickPick(this.getActiveTasks(), + this.showQuickPick(activeTasksPromise, nls.localize('TaskService.pickShowTask', 'Select the task to show its output'), { label: nls.localize('TaskService.noTaskIsRunning', 'No task is running'), diff --git a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts index 3b768e712a5..f322f2bc68e 100644 --- a/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts +++ b/src/vs/workbench/contrib/tasks/browser/tasksQuickAccess.ts @@ -39,7 +39,7 @@ export class TasksQuickAccessProvider extends PickerQuickAccessProvider> { + protected async _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { // always await extensions await this.activationPromise; diff --git a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts index f1bc1a55ff5..c58df8d40d2 100644 --- a/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts +++ b/src/vs/workbench/contrib/tasks/browser/terminalTaskSystem.ts @@ -27,7 +27,7 @@ import Constants from 'vs/workbench/contrib/markers/browser/constants'; import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { ITerminalProfileResolverService, TERMINAL_SETTING_ID, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProfileResolverService, TerminalSettingId, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalService, ITerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IOutputService } from 'vs/workbench/contrib/output/common/output'; import { StartStopProblemCollector, WatchingProblemCollector, ProblemCollectorEventKind, ProblemHandlingStrategy } from 'vs/workbench/contrib/tasks/common/problemCollectors'; @@ -1074,7 +1074,7 @@ export class TerminalTaskSystem implements ITaskSystem { // Under Mac remove -l to not start it as a login shell. if (platform === Platform.Platform.Mac) { // Background on -l on osx https://github.com/microsoft/vscode/issues/107563 - const osxShellArgs = this.configurationService.inspect(TERMINAL_SETTING_ID.ShellArgsMacOs); + const osxShellArgs = this.configurationService.inspect(TerminalSettingId.ShellArgsMacOs); if ((osxShellArgs.user === undefined) && (osxShellArgs.userLocal === undefined) && (osxShellArgs.userLocalValue === undefined) && (osxShellArgs.userRemote === undefined) && (osxShellArgs.userRemoteValue === undefined) && (osxShellArgs.userValue === undefined) && (osxShellArgs.workspace === undefined) @@ -1155,14 +1155,14 @@ export class TerminalTaskSystem implements ITaskSystem { private async createTerminal(task: CustomTask | ContributedTask, resolver: VariableResolver, workspaceFolder: IWorkspaceFolder | undefined): Promise<[ITerminalInstance | undefined, string | undefined, TaskError | undefined]> { let platform = resolver.taskSystemInfo ? resolver.taskSystemInfo.platform : Platform.platform; let options = await this.resolveOptions(resolver, task.command.options); - - let waitOnExit: boolean | string = false; const presentationOptions = task.command.presentation; + + let waitOnExit: boolean | string = presentationOptions?.close ? !presentationOptions.close : false; if (!presentationOptions) { throw new Error('Task presentation options should not be undefined here.'); } - if (presentationOptions.reveal !== RevealKind.Never || !task.configurationProperties.isBackground) { + if ((presentationOptions.close === undefined) && ((presentationOptions.reveal !== RevealKind.Never) || !task.configurationProperties.isBackground)) { if (presentationOptions.panel === PanelKind.New) { waitOnExit = nls.localize('closeTerminal', 'Press any key to close the terminal.'); } else if (presentationOptions.showReuseMessage) { diff --git a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts index fda80c732c9..0885bf6c6dd 100644 --- a/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts +++ b/src/vs/workbench/contrib/tasks/common/jsonSchema_v2.ts @@ -159,6 +159,10 @@ const presentation: IJSONSchema = { type: 'string', description: nls.localize('JsonSchema.tasks.presentation.group', 'Controls whether the task is executed in a specific terminal group using split panes.') }, + close: { + type: 'boolean', + description: nls.localize('JsonSchema.tasks.presentation.close', 'Controls whether the terminal the task runs in is closed when the task exits.') + } } }; diff --git a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts index 28d45ddf306..7ef30c474d9 100644 --- a/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts +++ b/src/vs/workbench/contrib/tasks/common/taskConfiguration.ts @@ -130,6 +130,11 @@ export interface PresentationOptionsConfig { * Controls whether the task is executed in a specific terminal group using split panes. */ group?: string; + + /** + * Controls whether the terminal that the task runs in is closed when the task completes. + */ + close?: boolean; } export interface RunOptionsConfig { @@ -829,7 +834,7 @@ namespace CommandOptions { namespace CommandConfiguration { export namespace PresentationOptions { - const properties: MetaData[] = [{ property: 'echo' }, { property: 'reveal' }, { property: 'revealProblems' }, { property: 'focus' }, { property: 'panel' }, { property: 'showReuseMessage' }, { property: 'clear' }, { property: 'group' }]; + const properties: MetaData[] = [{ property: 'echo' }, { property: 'reveal' }, { property: 'revealProblems' }, { property: 'focus' }, { property: 'panel' }, { property: 'showReuseMessage' }, { property: 'clear' }, { property: 'group' }, { property: 'close' }]; interface PresentationOptionsShape extends LegacyCommandProperties { presentation?: PresentationOptionsConfig; @@ -844,6 +849,7 @@ namespace CommandConfiguration { let showReuseMessage: boolean; let clear: boolean; let group: string | undefined; + let close: boolean | undefined; let hasProps = false; if (Types.isBoolean(config.echoCommand)) { echo = config.echoCommand; @@ -879,12 +885,15 @@ namespace CommandConfiguration { if (Types.isString(presentation.group)) { group = presentation.group; } + if (Types.isBoolean(presentation.close)) { + close = presentation.close; + } hasProps = true; } if (!hasProps) { return undefined; } - return { echo: echo!, reveal: reveal!, revealProblems: revealProblems!, focus: focus!, panel: panel!, showReuseMessage: showReuseMessage!, clear: clear!, group }; + return { echo: echo!, reveal: reveal!, revealProblems: revealProblems!, focus: focus!, panel: panel!, showReuseMessage: showReuseMessage!, clear: clear!, group, close: close }; } export function assignProperties(target: Tasks.PresentationOptions, source: Tasks.PresentationOptions | undefined): Tasks.PresentationOptions | undefined { diff --git a/src/vs/workbench/contrib/tasks/common/tasks.ts b/src/vs/workbench/contrib/tasks/common/tasks.ts index 8b12d99bd4b..9bbb50cfdfa 100644 --- a/src/vs/workbench/contrib/tasks/common/tasks.ts +++ b/src/vs/workbench/contrib/tasks/common/tasks.ts @@ -266,6 +266,11 @@ export interface PresentationOptions { * Controls whether the task is executed in a specific terminal group using split panes. */ group?: string; + + /** + * Controls whether the terminal that the task runs in is closed when the task completes. + */ + close?: boolean; } export namespace PresentationOptions { diff --git a/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts b/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts index 5f4ab95416f..9b1a369523a 100644 --- a/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts +++ b/src/vs/workbench/contrib/tasks/test/common/configuration.test.ts @@ -88,7 +88,7 @@ class PresentationBuilder { public result: Tasks.PresentationOptions; constructor(public parent: CommandConfigurationBuilder) { - this.result = { echo: false, reveal: Tasks.RevealKind.Always, revealProblems: Tasks.RevealProblemKind.Never, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false }; + this.result = { echo: false, reveal: Tasks.RevealKind.Always, revealProblems: Tasks.RevealProblemKind.Never, focus: false, panel: Tasks.PanelKind.Shared, showReuseMessage: true, clear: false, close: false }; } public echo(value: boolean): PresentationBuilder { @@ -116,6 +116,11 @@ class PresentationBuilder { return this; } + public close(value: boolean): PresentationBuilder { + this.result.close = value; + return this; + } + public done(): void { } } diff --git a/src/vs/workbench/contrib/terminal/.eslintrc.json b/src/vs/workbench/contrib/terminal/.eslintrc.json new file mode 100644 index 00000000000..ddd49198e1d --- /dev/null +++ b/src/vs/workbench/contrib/terminal/.eslintrc.json @@ -0,0 +1,19 @@ +{ + "rules": { + "@typescript-eslint/naming-convention": [ + "warn", + // variableLike + { "selector": "variable", "format": ["camelCase", "UPPER_CASE", "PascalCase"] }, + { "selector": "variable", "filter": "^I.+Service$", "format": ["PascalCase"], "prefix": ["I"] }, + // memberLike + { "selector": "memberLike", "modifiers": ["private"], "format": ["camelCase"], "leadingUnderscore": "require" }, + { "selector": "memberLike", "modifiers": ["protected"], "format": ["camelCase"], "leadingUnderscore": "require" }, + { "selector": "enumMember", "format": ["PascalCase"] }, + // memberLike - Allow enum-like objects to use UPPER_CASE + { "selector": "method", "modifiers": ["public"], "format": ["camelCase", "UPPER_CASE"] }, + // typeLike + { "selector": "typeLike", "format": ["PascalCase"] }, + { "selector": "interface", "format": ["PascalCase"] } + ] + } +} diff --git a/src/vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon.ts b/src/vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon.ts index 01c90349d9e..aa08c658100 100644 --- a/src/vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/addons/commandTrackerAddon.ts @@ -27,12 +27,12 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { private _isDisposable: boolean = false; private _terminal: Terminal | undefined; - public activate(terminal: Terminal): void { + activate(terminal: Terminal): void { this._terminal = terminal; terminal.onKey(e => this._onKey(e.key)); } - public dispose(): void { + dispose(): void { } private _onKey(key: string): void { @@ -55,7 +55,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { } } - public scrollToPreviousCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + scrollToPreviousCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { if (!this._terminal) { return; } @@ -94,7 +94,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._scrollToMarker(this._currentMarker, scrollPosition); } - public scrollToNextCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + scrollToNextCommand(scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { if (!this._terminal) { return; } @@ -144,7 +144,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._terminal.scrollToLine(line); } - public selectToPreviousCommand(): void { + selectToPreviousCommand(): void { if (!this._terminal) { return; } @@ -155,7 +155,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._selectLines(this._terminal, this._currentMarker, this._selectionStart); } - public selectToNextCommand(): void { + selectToNextCommand(): void { if (!this._terminal) { return; } @@ -166,7 +166,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._selectLines(this._terminal, this._currentMarker, this._selectionStart); } - public selectToPreviousLine(): void { + selectToPreviousLine(): void { if (!this._terminal) { return; } @@ -177,7 +177,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._selectLines(this._terminal, this._currentMarker, this._selectionStart); } - public selectToNextLine(): void { + selectToNextLine(): void { if (!this._terminal) { return; } @@ -222,7 +222,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { return marker.line; } - public scrollToPreviousLine(xterm: Terminal, scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + scrollToPreviousLine(xterm: Terminal, scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { if (!retainSelection) { this._selectionStart = null; } @@ -245,7 +245,7 @@ export class CommandTrackerAddon implements ICommandTracker, ITerminalAddon { this._scrollToMarker(this._currentMarker, scrollPosition); } - public scrollToNextLine(xterm: Terminal, scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { + scrollToNextLine(xterm: Terminal, scrollPosition: ScrollPosition = ScrollPosition.Top, retainSelection: boolean = false): void { if (!retainSelection) { this._selectionStart = null; } diff --git a/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts b/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts index ed9ea1f02d1..4b2b0bdc426 100644 --- a/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts +++ b/src/vs/workbench/contrib/terminal/browser/environmentVariableInfo.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { EnvironmentVariableMutatorType, IEnvironmentVariableInfo, IMergedEnvironmentVariableCollection, IMergedEnvironmentVariableCollectionDiff } from 'vs/workbench/contrib/terminal/common/environmentVariable'; -import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { localize } from 'vs/nls'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; @@ -64,7 +64,7 @@ export class EnvironmentVariableInfoStale implements IEnvironmentVariableInfo { return [{ label: localize('relaunchTerminalLabel', "Relaunch terminal"), run: () => this._terminalService.getInstanceFromId(this._terminalId)?.relaunch(), - commandId: TERMINAL_COMMAND_ID.RELAUNCH + commandId: TerminalCommandId.Relaunch }]; } } diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts index 6c382e0e04a..9b3530e26fb 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLink.ts @@ -24,17 +24,17 @@ export class TerminalLink extends DisposableStore implements ILink { private _hoverListeners: DisposableStore | undefined; private readonly _onInvalidated = new Emitter(); - public get onInvalidated(): Event { return this._onInvalidated.event; } + get onInvalidated(): Event { return this._onInvalidated.event; } constructor( private readonly _xterm: Terminal, - public readonly range: IBufferRange, - public readonly text: string, + readonly range: IBufferRange, + readonly text: string, private readonly _viewportY: number, private readonly _activateCallback: (event: MouseEvent | undefined, uri: string) => void, private readonly _tooltipCallback: (link: TerminalLink, viewportRange: IViewportRange, modifierDownCallback?: () => void, modifierUpCallback?: () => void) => void, private readonly _isHighConfidenceLink: boolean, - public readonly label: string | undefined, + readonly label: string | undefined, @IConfigurationService private readonly _configurationService: IConfigurationService ) { super(); diff --git a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts index 9f043c29802..7bc9a9bc587 100644 --- a/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/links/terminalLinkManager.ts @@ -124,11 +124,11 @@ export class TerminalLinkManager extends DisposableStore { } } - public setWidgetManager(widgetManager: TerminalWidgetManager): void { + setWidgetManager(widgetManager: TerminalWidgetManager): void { this._widgetManager = widgetManager; } - public set processCwd(processCwd: string) { + set processCwd(processCwd: string) { this._processCwd = processCwd; } @@ -140,7 +140,7 @@ export class TerminalLinkManager extends DisposableStore { } } - public registerExternalLinkProvider(instance: ITerminalInstance, linkProvider: ITerminalExternalLinkProvider): IDisposable { + registerExternalLinkProvider(instance: ITerminalInstance, linkProvider: ITerminalExternalLinkProvider): IDisposable { const wrappedLinkProvider = this._instantiationService.createInstance(TerminalExternalLinkProviderAdapter, this._xterm, instance, linkProvider, this._wrapLinkHandler.bind(this), this._tooltipCallback.bind(this)); const newLinkProvider = this._xterm.registerLinkProvider(wrappedLinkProvider); // Re-register the standard link providers so they are a lower priority that the new one @@ -200,7 +200,7 @@ export class TerminalLinkManager extends DisposableStore { if (uri.scheme === Schemas.file) { // Just using fsPath here is unsafe: https://github.com/microsoft/vscode/issues/109076 const fsPath = uri.fsPath; - this._handleLocalLink(((this.osPath.sep === posix.sep) && isWindows) ? fsPath.replace(/\\/g, posix.sep) : fsPath); + this._handleLocalLink(((this._osPath.sep === posix.sep) && isWindows) ? fsPath.replace(/\\/g, posix.sep) : fsPath); return; } @@ -263,7 +263,7 @@ export class TerminalLinkManager extends DisposableStore { return markdown.appendMarkdown(`[${label}](${uri}) (${clickLabel})`); } - private get osPath(): IPath { + private get _osPath(): IPath { if (!this._processManager) { throw new Error('Process manager is required'); } @@ -282,7 +282,7 @@ export class TerminalLinkManager extends DisposableStore { if (!this._processManager.userHome) { return null; } - link = this.osPath.join(this._processManager.userHome, link.substring(1)); + link = this._osPath.join(this._processManager.userHome, link.substring(1)); } else if (link.charAt(0) !== '/' && link.charAt(0) !== '~') { // Resolve workspace path . | .. | -> /. | /.. | / if (this._processManager.os === OperatingSystem.Windows) { @@ -291,7 +291,7 @@ export class TerminalLinkManager extends DisposableStore { // Abort if no workspace is open return null; } - link = this.osPath.join(this._processCwd, link); + link = this._osPath.join(this._processCwd, link); } else { // Remove \\?\ from paths so that they share the same underlying // uri and don't open multiple tabs for the same file @@ -302,10 +302,10 @@ export class TerminalLinkManager extends DisposableStore { // Abort if no workspace is open return null; } - link = this.osPath.join(this._processCwd, link); + link = this._osPath.join(this._processCwd, link); } } - link = this.osPath.normalize(link); + link = this._osPath.normalize(link); return link; } @@ -356,7 +356,7 @@ export class TerminalLinkManager extends DisposableStore { * * @param link Url link which may contain line and column number. */ - public extractLineColumnInfo(link: string): LineColumnInfo { + extractLineColumnInfo(link: string): LineColumnInfo { const matches: string[] | null = this._localLinkRegex.exec(link); const lineColumnInfo: LineColumnInfo = { lineNumber: 1, @@ -390,7 +390,7 @@ export class TerminalLinkManager extends DisposableStore { * * @param link url link which may contain line and column number. */ - public extractLinkUrl(link: string): string | null { + extractLinkUrl(link: string): string | null { const matches: string[] | null = this._localLinkRegex.exec(link); if (!matches) { return null; diff --git a/src/vs/workbench/contrib/terminal/browser/media/terminal.css b/src/vs/workbench/contrib/terminal/browser/media/terminal.css index e09bb9a0cf8..92efe61e64a 100644 --- a/src/vs/workbench/contrib/terminal/browser/media/terminal.css +++ b/src/vs/workbench/contrib/terminal/browser/media/terminal.css @@ -21,7 +21,7 @@ overflow: hidden; } -.monaco-workbench .pane-body.integrated-terminal .terminal-tab { +.monaco-workbench .pane-body.integrated-terminal .terminal-group { height: 100%; } @@ -253,10 +253,6 @@ vertical-align: text-bottom; } -.monaco-workbench .pane-body.integrated-terminal .tabs-widget .monaco-tl-twistie.force-no-twistie { - display: none !important; -} - .monaco-workbench .pane-body.integrated-terminal .tabs-widget .actions { display: none; } diff --git a/src/vs/workbench/contrib/terminal/browser/remotePty.ts b/src/vs/workbench/contrib/terminal/browser/remotePty.ts index 1096aeeb2d6..defd36db3f2 100644 --- a/src/vs/workbench/contrib/terminal/browser/remotePty.ts +++ b/src/vs/workbench/contrib/terminal/browser/remotePty.ts @@ -15,26 +15,26 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA export class RemotePty extends Disposable implements ITerminalChildProcess { - public readonly _onProcessData = this._register(new Emitter()); - public readonly onProcessData: Event = this._onProcessData.event; + readonly _onProcessData = this._register(new Emitter()); + readonly onProcessData: Event = this._onProcessData.event; private readonly _onProcessExit = this._register(new Emitter()); - public readonly onProcessExit: Event = this._onProcessExit.event; - public readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + readonly onProcessExit: Event = this._onProcessExit.event; + readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); + get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); - public readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; + readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); - public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter()); - public readonly onProcessOverrideDimensions: Event = this._onProcessOverrideDimensions.event; + readonly onProcessOverrideDimensions: Event = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter()); - public get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessResolvedShellLaunchConfig.event; } + get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessResolvedShellLaunchConfig.event; } private _startBarrier: Barrier; private _inReplay = false; - public get id(): number { return this._id; } + get id(): number { return this._id; } constructor( private _id: number, @@ -47,7 +47,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { this._startBarrier = new Barrier(); } - public async start(): Promise { + async start(): Promise { // Fetch the environment to check shell permissions const env = await this._remoteAgentService.getEnvironment(); if (!env) { @@ -68,13 +68,13 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { return undefined; } - public shutdown(immediate: boolean): void { + shutdown(immediate: boolean): void { this._startBarrier.wait().then(_ => { this._remoteTerminalChannel.shutdown(this._id, immediate); }); } - public input(data: string): void { + input(data: string): void { if (this._inReplay) { return; } @@ -84,7 +84,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { }); } - public resize(cols: number, rows: number): void { + resize(cols: number, rows: number): void { if (this._inReplay) { return; } @@ -94,7 +94,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { }); } - public acknowledgeDataEvent(charCount: number): void { + acknowledgeDataEvent(charCount: number): void { // Support flow control for server spawned processes if (this._inReplay) { return; @@ -105,12 +105,12 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { }); } - public async getInitialCwd(): Promise { + async getInitialCwd(): Promise { await this._startBarrier.wait(); return this._remoteTerminalChannel.getInitialCwd(this._id); } - public async getCwd(): Promise { + async getCwd(): Promise { await this._startBarrier.wait(); return this._remoteTerminalChannel.getCwd(this._id); } @@ -168,7 +168,7 @@ export class RemotePty extends Disposable implements ITerminalChildProcess { this._remoteTerminalChannel.orphanQuestionReply(this._id); } - public async getLatency(): Promise { + async getLatency(): Promise { return 0; } } diff --git a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts index 2d90f8e7d18..23cbb1c5d18 100644 --- a/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/remoteTerminalService.ts @@ -21,7 +21,7 @@ import { IRemoteTerminalAttachTarget, ITerminalConfigHelper } from 'vs/workbench import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; export class RemoteTerminalService extends Disposable implements IRemoteTerminalService { - public _serviceBrand: undefined; + declare _serviceBrand: undefined; private readonly _ptys: Map = new Map(); private readonly _remoteTerminalChannel: RemoteTerminalChannelClient | null; @@ -126,7 +126,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal } } - public async createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, shouldPersist: boolean, configHelper: ITerminalConfigHelper): Promise { + async createProcess(shellLaunchConfig: IShellLaunchConfig, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, cols: number, rows: number, shouldPersist: boolean, configHelper: ITerminalConfigHelper): Promise { if (!this._remoteTerminalChannel) { throw new Error(`Cannot create remote terminal when there is no remote!`); } @@ -158,7 +158,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal return pty; } - public async attachToProcess(id: number): Promise { + async attachToProcess(id: number): Promise { if (!this._remoteTerminalChannel) { throw new Error(`Cannot create remote terminal when there is no remote!`); } @@ -174,7 +174,7 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal return undefined; } - public async listProcesses(): Promise { + async listProcesses(): Promise { const terms = this._remoteTerminalChannel ? await this._remoteTerminalChannel.listProcesses() : []; return terms.map(termDto => { return { @@ -189,15 +189,23 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal }); } - public async getDefaultSystemShell(osOverride?: OperatingSystem): Promise { + async getDefaultSystemShell(osOverride?: OperatingSystem): Promise { return this._remoteTerminalChannel?.getDefaultSystemShell(osOverride) || ''; } - public async getShellEnvironment(): Promise { - return this._remoteTerminalChannel?.getShellEnvironment() || {}; + async getEnvironment(): Promise { + return this._remoteTerminalChannel?.getEnvironment() || {}; } - public setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { + async getWslPath(original: string): Promise { + const env = await this._remoteAgentService.getEnvironment(); + if (env?.os !== OperatingSystem.Windows) { + return original; + } + return this._remoteTerminalChannel?.getWslPath(original) || original; + } + + setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { if (!this._remoteTerminalChannel) { throw new Error(`Cannot call setActiveInstanceId when there is no remote`); } @@ -205,14 +213,14 @@ export class RemoteTerminalService extends Disposable implements IRemoteTerminal return this._remoteTerminalChannel.setTerminalLayoutInfo(layout); } - public async reduceConnectionGraceTime(): Promise { + async reduceConnectionGraceTime(): Promise { if (!this._remoteTerminalChannel) { throw new Error('Cannot reduce grace time when there is no remote'); } return this._remoteTerminalChannel.reduceConnectionGraceTime(); } - public async getTerminalLayoutInfo(): Promise { + async getTerminalLayoutInfo(): Promise { if (!this._remoteTerminalChannel) { throw new Error(`Cannot call getActiveInstanceId when there is no remote`); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts index c4fb638c41f..004ee4614b1 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.contribution.ts @@ -18,13 +18,13 @@ import { getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess'; import { Extensions as ViewContainerExtensions, IViewContainersRegistry, ViewContainerLocation, IViewsRegistry } from 'vs/workbench/common/views'; import { registerTerminalActions, terminalSendSequenceCommand } from 'vs/workbench/contrib/terminal/browser/terminalActions'; import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView'; -import { KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, TERMINAL_VIEW_ID, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE_KEY, KEYBINDING_CONTEXT_TERMINAL_FOCUS, TERMINAL_VIEW_ID, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { registerColors } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { setupTerminalCommands } from 'vs/workbench/contrib/terminal/browser/terminalCommands'; import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; import { TerminalService } from 'vs/workbench/contrib/terminal/browser/terminalService'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { IRemoteTerminalService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IRemoteTerminalService, ITerminalInstanceService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors'; import { ViewPaneContainer } from 'vs/workbench/browser/parts/views/viewPaneContainer'; import { IQuickAccessRegistry, Extensions as QuickAccessExtensions } from 'vs/platform/quickinput/common/quickAccess'; @@ -37,10 +37,12 @@ import { isIPad } from 'vs/base/browser/browser'; import { WindowsShellType } from 'vs/platform/terminal/common/terminal'; import { isWindows } from 'vs/base/common/platform'; import { setupTerminalMenus } from 'vs/workbench/contrib/terminal/browser/terminalMenus'; +import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; // Register services registerSingleton(ITerminalService, TerminalService, true); registerSingleton(IRemoteTerminalService, RemoteTerminalService); +registerSingleton(ITerminalInstanceService, TerminalInstanceService, true); // Register quick accesses const quickAccessRegistry = (Registry.as(QuickAccessExtensions.Quickaccess)); @@ -80,7 +82,7 @@ Registry.as(ViewContainerExtensions.ViewsRegistry).registerViews canMoveView: true, ctorDescriptor: new SyncDescriptor(TerminalViewPane), openCommandActionDescriptor: { - id: TERMINAL_COMMAND_ID.TOGGLE, + id: TerminalCommandId.Toggle, mnemonicTitle: nls.localize({ key: 'miToggleIntegratedTerminal', comment: ['&& denotes a mnemonic'] }, "&&Terminal"), keybindings: { primary: KeyMod.CtrlCmd | KeyCode.US_BACKTICK, @@ -95,7 +97,7 @@ registerTerminalActions(); function registerSendSequenceKeybinding(text: string, rule: { when?: ContextKeyExpression } & IKeybindings): void { KeybindingsRegistry.registerCommandAndKeybindingRule({ - id: TERMINAL_COMMAND_ID.SEND_SEQUENCE, + id: TerminalCommandId.SendSequence, weight: KeybindingWeight.WorkbenchContrib, when: rule.when || KEYBINDING_CONTEXT_TERMINAL_FOCUS, primary: rule.primary, diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.ts b/src/vs/workbench/contrib/terminal/browser/terminal.ts index 5d1161d8ef9..65640673ce6 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.ts @@ -6,12 +6,11 @@ import { Codicon } from 'vs/base/common/codicons'; import { Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; -import { IProcessEnvironment } from 'vs/base/common/platform'; import { URI } from 'vs/base/common/uri'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import { createDecorator } from 'vs/platform/instantiation/common/instantiation'; import { IOffProcessTerminalService, IShellLaunchConfig, ITerminalChildProcess, ITerminalDimensions, ITerminalLaunchError, ITerminalTabLayoutInfoById, TerminalShellType } from 'vs/platform/terminal/common/terminal'; -import { IAvailableProfilesRequest, ICommandTracker, IDefaultShellAndArgsRequest, INavigationMode, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, LinuxDistro, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IAvailableProfilesRequest, ICommandTracker, INavigationMode, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalProcessExtHostProxy, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; @@ -31,14 +30,10 @@ export const IRemoteTerminalService = createDecorator('r export interface ITerminalInstanceService { readonly _serviceBrand: undefined; - // These events are optional as the requests they make are only needed on the browser side - onRequestDefaultShellAndArgs?: Event; - getXtermConstructor(): Promise; getXtermSearchConstructor(): Promise; getXtermUnicode11Constructor(): Promise; getXtermWebglConstructor(): Promise; - getMainProcessParentEnv(): Promise; } export interface IBrowserTerminalConfigHelper extends ITerminalConfigHelper { @@ -52,11 +47,11 @@ export const enum Direction { Down = 3 } -export interface ITerminalTab { +export interface ITerminalGroup { activeInstance: ITerminalInstance | null; terminalInstances: ITerminalInstance[]; title: string; - onDisposed: Event; + onDisposed: Event; onInstancesChanged: Event; focusPreviousPane(): void; focusNextPane(): void; @@ -82,14 +77,14 @@ export interface ITerminalService { activeTabIndex: number; configHelper: ITerminalConfigHelper; terminalInstances: ITerminalInstance[]; - terminalTabs: ITerminalTab[]; + terminalGroups: ITerminalGroup[]; isProcessSupportRegistered: boolean; readonly connectionState: TerminalConnectionState; readonly availableProfiles: ITerminalProfile[]; initializeTerminals(): Promise; onActiveTabChanged: Event; - onTabDisposed: Event; + onTabDisposed: Event; onInstanceCreated: Event; onInstanceDisposed: Event; onInstanceProcessIdReady: Event; @@ -139,7 +134,7 @@ export interface ITerminalService { */ doWithActiveInstance(callback: (terminal: ITerminalInstance) => T): T | void; - getActiveTab(): ITerminalTab | null; + getActiveGroup(): ITerminalGroup | null; setActiveTabToNext(): void; setActiveTabToPrevious(): void; setActiveTabByIndex(tabIndex: number): void; @@ -171,16 +166,10 @@ export interface ITerminalService { showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise; - getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined; + getGroupForInstance(instance: ITerminalInstance): ITerminalGroup | undefined; setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): void; - /** - * Injects native Windows functionality into the service. - */ - setNativeWindowsDelegate(delegate: ITerminalNativeWindowsDelegate): void; - setLinuxDistro(linuxDistro: LinuxDistro): void; - /** * Takes a path and returns the properly escaped path to send to the terminal. * On Windows, this included trying to prepare the path for WSL if needed. @@ -188,9 +177,10 @@ export interface ITerminalService { * @param executable The executable off the shellLaunchConfig * @param title The terminal's title * @param path The path to be escaped and formatted. + * @param isRemote Whether the terminal's pty is remote. * @returns An escaped version of the path to be execuded in the terminal. */ - preparePathForTerminalAsync(path: string, executable: string | undefined, title: string, shellType: TerminalShellType): Promise; + preparePathForTerminalAsync(path: string, executable: string | undefined, title: string, shellType: TerminalShellType, isRemote: boolean): Promise; extHostReady(remoteAuthority: string): void; requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise; @@ -286,6 +276,11 @@ export interface ITerminalInstance { */ readonly isDisconnected: boolean; + /** + * Whether the terminal's pty is hosted on a remote. + */ + readonly isRemote: boolean; + /** * An event that fires when the terminal instance's title changes. */ @@ -297,6 +292,7 @@ export interface ITerminalInstance { onDisposed: Event; onFocused: Event; + onDropped: Event<{ instance: ITerminalInstance, dragEvent: DragEvent; }>; onProcessIdReady: Event; onLinksReady: Event; onRequestExtHostProcess: Event; @@ -577,3 +573,9 @@ export interface ITerminalInstance { */ changeIcon(): Promise; } + +export const enum LinuxDistro { + Unknown = 1, + Fedora = 2, + Ubuntu = 3, +} diff --git a/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts b/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts index 2eb6ec2de2b..79728c55919 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminal.web.contribution.ts @@ -5,24 +5,16 @@ import { KeyCode, KeyMod } from 'vs/base/common/keyCodes'; import { KeybindingWeight, KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { ITerminalProfileResolverService, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { getNoDefaultTerminalShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; +import { ITerminalProfileResolverService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { BrowserTerminalProfileResolverService } from 'vs/workbench/contrib/terminal/browser/terminalProfileResolverService'; registerSingleton(ITerminalProfileResolverService, BrowserTerminalProfileResolverService, true); -// Desktop shell configuration are registered in electron-browser as their default values rely -// on process.env -const configurationRegistry = Registry.as(Extensions.Configuration); -configurationRegistry.registerConfiguration(getNoDefaultTerminalShellConfiguration()); - // Register standard external terminal keybinding as integrated terminal when in web as the // external terminal is not available KeybindingsRegistry.registerKeybindingRule({ - id: TERMINAL_COMMAND_ID.NEW, + id: TerminalCommandId.New, weight: KeybindingWeight.WorkbenchContrib, when: undefined, primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_C diff --git a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts index 7769b1c6dd4..9107c38f578 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalActions.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalActions.ts @@ -32,7 +32,7 @@ import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/w import { FindInFilesCommand, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions'; import { Direction, IRemoteTerminalService, ITerminalInstance, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess'; -import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, ITerminalProfile, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_ACTION_CATEGORY, TERMINAL_COMMAND_ID, TERMINAL_SETTING_ID, TERMINAL_VIEW_ID, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, ITerminalProfile, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TERMINAL_ACTION_CATEGORY, TerminalCommandId, TerminalSettingId, TERMINAL_VIEW_ID, TitleEventSource } from 'vs/workbench/contrib/terminal/common/terminal'; import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; @@ -105,7 +105,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NEW_IN_ACTIVE_WORKSPACE, + id: TerminalCommandId.NewInActiveWorkspace, title: { value: localize('workbench.action.terminal.newInActiveWorkspace', "Create New Integrated Terminal (In Active Workspace)"), original: 'Create New Integrated Terminal (In Active Workspace)' }, f1: true, category @@ -126,7 +126,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NEW_WITH_PROFILE, + id: TerminalCommandId.NewWithProfile, title: { value: localize('workbench.action.terminal.newWithProfile', "Create New Integrated Terminal (With Profile)"), original: 'Create New Integrated Terminal (With Profile)' }, f1: true, category, @@ -195,7 +195,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SHOW_TABS, + id: TerminalCommandId.ShowTabs, title: { value: localize('workbench.action.terminal.showTabs', "Show Tabs"), original: 'Show Tabs' }, f1: false, category, @@ -211,7 +211,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS_PANE, + id: TerminalCommandId.FocusPreviousPane, title: { value: localize('workbench.action.terminal.focusPreviousPane', "Focus Previous Pane"), original: 'Focus Previous Pane' }, f1: true, category, @@ -230,14 +230,14 @@ export function registerTerminalActions() { } async run(accessor: ServicesAccessor) { const terminalService = accessor.get(ITerminalService); - terminalService.getActiveTab()?.focusPreviousPane(); + terminalService.getActiveGroup()?.focusPreviousPane(); await terminalService.showPanel(true); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS_NEXT_PANE, + id: TerminalCommandId.FocusNextPane, title: { value: localize('workbench.action.terminal.focusNextPane', "Focus Next Pane"), original: 'Focus Next Pane' }, f1: true, category, @@ -256,14 +256,14 @@ export function registerTerminalActions() { } async run(accessor: ServicesAccessor) { const terminalService = accessor.get(ITerminalService); - terminalService.getActiveTab()?.focusNextPane(); + terminalService.getActiveGroup()?.focusNextPane(); await terminalService.showPanel(true); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RESIZE_PANE_LEFT, + id: TerminalCommandId.ResizePaneLeft, title: { value: localize('workbench.action.terminal.resizePaneLeft', "Resize Pane Left"), original: 'Resize Pane Left' }, f1: true, category, @@ -277,13 +277,13 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Left); + accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Left); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RESIZE_PANE_RIGHT, + id: TerminalCommandId.ResizePaneRight, title: { value: localize('workbench.action.terminal.resizePaneRight', "Resize Pane Right"), original: 'Resize Pane Right' }, f1: true, category, @@ -297,13 +297,13 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Right); + accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Right); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RESIZE_PANE_UP, + id: TerminalCommandId.ResizePaneUp, title: { value: localize('workbench.action.terminal.resizePaneUp', "Resize Pane Up"), original: 'Resize Pane Up' }, f1: true, category, @@ -316,13 +316,13 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Up); + accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Up); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RESIZE_PANE_DOWN, + id: TerminalCommandId.ResizePaneDown, title: { value: localize('workbench.action.terminal.resizePaneDown', "Resize Pane Down"), original: 'Resize Pane Down' }, f1: true, category, @@ -335,13 +335,13 @@ export function registerTerminalActions() { }); } async run(accessor: ServicesAccessor) { - accessor.get(ITerminalService).getActiveTab()?.resizePane(Direction.Down); + accessor.get(ITerminalService).getActiveGroup()?.resizePane(Direction.Down); } }); registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS, + id: TerminalCommandId.Focus, title: { value: localize('workbench.action.terminal.focus', "Focus Terminal"), original: 'Focus Terminal' }, f1: true, category, @@ -353,20 +353,20 @@ export function registerTerminalActions() { order: 0, when: ContextKeyAndExpr.create([ ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID), - ContextKeyExpr.has(`config.${TERMINAL_SETTING_ID.TabsEnabled}`), + ContextKeyExpr.has(`config.${TerminalSettingId.TabsEnabled}`), ContextKeyExpr.or( ContextKeyExpr.and( - ContextKeyExpr.equals(`config.${TERMINAL_SETTING_ID.TabsShowActiveTerminal}`, 'singleTerminal'), + ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminal'), ContextKeyExpr.equals('terminalCount', 1) ), ContextKeyExpr.and( - ContextKeyExpr.equals(`config.${TERMINAL_SETTING_ID.TabsShowActiveTerminal}`, 'singleTerminalOrNarrow'), + ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'singleTerminalOrNarrow'), ContextKeyExpr.or( ContextKeyExpr.equals('terminalCount', 1), ContextKeyExpr.has('isTerminalTabsNarrow') ) ), - ContextKeyExpr.equals(`config.${TERMINAL_SETTING_ID.TabsShowActiveTerminal}`, 'always') + ContextKeyExpr.equals(`config.${TerminalSettingId.TabsShowActiveTerminal}`, 'always') ) ]), } @@ -385,7 +385,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS_TABS, + id: TerminalCommandId.FocusTabs, title: { value: localize('workbench.action.terminal.focus.tabsView', "Focus Terminal Tabs View"), original: 'Focus Terminal Tabs View' }, f1: true, category, @@ -404,7 +404,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS_NEXT, + id: TerminalCommandId.FocusNext, title: { value: localize('workbench.action.terminal.focusNext', "Focus Next Terminal"), original: 'Focus Next Terminal' }, f1: true, category, @@ -428,7 +428,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FOCUS_PREVIOUS, + id: TerminalCommandId.FocusPrevious, title: { value: localize('workbench.action.terminal.focusPrevious', "Focus Previous Terminal"), original: 'Focus Previous Terminal' }, f1: true, category, @@ -452,7 +452,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT, + id: TerminalCommandId.RunSelectedText, title: { value: localize('workbench.action.terminal.runSelectedText', "Run Selected Text In Active Terminal"), original: 'Run Selected Text In Active Terminal' }, f1: true, category, @@ -464,11 +464,11 @@ export function registerTerminalActions() { const codeEditorService = accessor.get(ICodeEditorService); const instance = terminalService.getActiveOrCreateInstance(); - let editor = codeEditorService.getActiveCodeEditor(); + const editor = codeEditorService.getActiveCodeEditor(); if (!editor || !editor.hasModel()) { return; } - let selection = editor.getSelection(); + const selection = editor.getSelection(); let text: string; if (selection.isEmpty()) { text = editor.getModel().getLineContent(selection.selectionStartLineNumber).trim(); @@ -483,7 +483,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE, + id: TerminalCommandId.RunActiveFile, title: { value: localize('workbench.action.terminal.runActiveFile', "Run Active File In Active Terminal"), original: 'Run Active File In Active Terminal' }, f1: true, category, @@ -508,7 +508,7 @@ export function registerTerminalActions() { // TODO: Convert this to ctrl+c, ctrl+v for pwsh? const instance = terminalService.getActiveOrCreateInstance(); - const path = await terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType); + const path = await terminalService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType, instance.isRemote); instance.sendText(path, true); return terminalService.showPanel(); } @@ -516,7 +516,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_DOWN_LINE, + id: TerminalCommandId.ScrollDownLine, title: { value: localize('workbench.action.terminal.scrollDown', "Scroll Down (Line)"), original: 'Scroll Down (Line)' }, f1: true, category, @@ -536,7 +536,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_DOWN_PAGE, + id: TerminalCommandId.ScrollDownPage, title: { value: localize('workbench.action.terminal.scrollDownPage', "Scroll Down (Page)"), original: 'Scroll Down (Page)' }, f1: true, category, @@ -556,7 +556,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_TO_BOTTOM, + id: TerminalCommandId.ScrollToBottom, title: { value: localize('workbench.action.terminal.scrollToBottom', "Scroll to Bottom"), original: 'Scroll to Bottom' }, f1: true, category, @@ -576,7 +576,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_UP_LINE, + id: TerminalCommandId.ScrollUpLine, title: { value: localize('workbench.action.terminal.scrollUp', "Scroll Up (Line)"), original: 'Scroll Up (Line)' }, f1: true, category, @@ -596,7 +596,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_UP_PAGE, + id: TerminalCommandId.ScrollUpPage, title: { value: localize('workbench.action.terminal.scrollUpPage', "Scroll Up (Page)"), original: 'Scroll Up (Page)' }, f1: true, category, @@ -616,7 +616,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_TO_TOP, + id: TerminalCommandId.ScrollToTop, title: { value: localize('workbench.action.terminal.scrollToTop', "Scroll to Top"), original: 'Scroll to Top' }, f1: true, category, @@ -636,7 +636,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT, + id: TerminalCommandId.NavigationModeExit, title: { value: localize('workbench.action.terminal.navigationModeExit', "Exit Navigation Mode"), original: 'Exit Navigation Mode' }, f1: true, category, @@ -655,7 +655,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS, + id: TerminalCommandId.NavigationModeFocusPrevious, title: { value: localize('workbench.action.terminal.navigationModeFocusPrevious', "Focus Previous Line (Navigation Mode)"), original: 'Focus Previous Line (Navigation Mode)' }, f1: true, category, @@ -677,7 +677,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT, + id: TerminalCommandId.NavigationModeFocusNext, title: { value: localize('workbench.action.terminal.navigationModeFocusNext', "Focus Next Line (Navigation Mode)"), original: 'Focus Next Line (Navigation Mode)' }, f1: true, category, @@ -699,7 +699,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CLEAR_SELECTION, + id: TerminalCommandId.ClearSelection, title: { value: localize('workbench.action.terminal.clearSelection', "Clear Selection"), original: 'Clear Selection' }, f1: true, category, @@ -721,7 +721,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CHANGE_ICON, + id: TerminalCommandId.ChangeIcon, title: { value: localize('workbench.action.terminal.changeIcon', "Change Icon..."), original: 'Change Icon...' }, f1: true, category, @@ -735,7 +735,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CHANGE_ICON_INSTANCE, + id: TerminalCommandId.ChangeIconInstance, title: { value: localize('workbench.action.terminal.changeIcon', "Change Icon..."), original: 'Change Icon...' }, f1: false, category, @@ -749,7 +749,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RENAME, + id: TerminalCommandId.Rename, title: { value: localize('workbench.action.terminal.rename', "Rename..."), original: 'Rename...' }, f1: true, category, @@ -763,7 +763,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RENAME_INSTANCE, + id: TerminalCommandId.RenameInstance, title: { value: localize('workbench.action.terminal.renameInstance', "Rename..."), original: 'Rename...' }, f1: false, category, @@ -785,7 +785,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FIND_FOCUS, + id: TerminalCommandId.FindFocus, title: { value: localize('workbench.action.terminal.focusFind', "Focus Find"), original: 'Focus Find' }, f1: true, category, @@ -804,7 +804,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FIND_HIDE, + id: TerminalCommandId.FindHide, title: { value: localize('workbench.action.terminal.hideFind', "Hide Find"), original: 'Hide Find' }, f1: true, category, @@ -824,7 +824,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.ATTACH_TO_REMOTE_TERMINAL, + id: TerminalCommandId.AttachToRemoteTerminal, title: { value: localize('workbench.action.terminal.attachToRemote', "Attach to Session"), original: 'Attach to Session' }, f1: true, category @@ -836,7 +836,7 @@ export function registerTerminalActions() { const labelService = accessor.get(ILabelService); const remoteAgentService = accessor.get(IRemoteAgentService); const notificationService = accessor.get(INotificationService); - let offProcTerminalService = remoteAgentService.getConnection() ? accessor.get(IRemoteTerminalService) : accessor.get(ILocalTerminalService); + const offProcTerminalService = remoteAgentService.getConnection() ? accessor.get(IRemoteTerminalService) : accessor.get(ILocalTerminalService); const terms = await offProcTerminalService.listProcesses(); @@ -867,7 +867,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.QUICK_OPEN_TERM, + id: TerminalCommandId.QuickOpenTerm, title: { value: localize('quickAccessTerminal', "Switch Active Terminal"), original: 'Switch Active Terminal' }, f1: true, category, @@ -881,7 +881,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_TO_PREVIOUS_COMMAND, + id: TerminalCommandId.ScrollToPreviousCommand, title: { value: localize('workbench.action.terminal.scrollToPreviousCommand', "Scroll To Previous Command"), original: 'Scroll To Previous Command' }, f1: true, category, @@ -903,7 +903,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SCROLL_TO_NEXT_COMMAND, + id: TerminalCommandId.ScrollToNextCommand, title: { value: localize('workbench.action.terminal.scrollToNextCommand', "Scroll To Next Command"), original: 'Scroll To Next Command' }, f1: true, category, @@ -925,7 +925,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_COMMAND, + id: TerminalCommandId.SelectToPreviousCommand, title: { value: localize('workbench.action.terminal.selectToPreviousCommand', "Select To Previous Command"), original: 'Select To Previous Command' }, f1: true, category, @@ -947,7 +947,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND, + id: TerminalCommandId.SelectToNextCommand, title: { value: localize('workbench.action.terminal.selectToNextCommand', "Select To Next Command"), original: 'Select To Next Command' }, f1: true, category, @@ -969,7 +969,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_LINE, + id: TerminalCommandId.SelectToPreviousLine, title: { value: localize('workbench.action.terminal.selectToPreviousLine', "Select To Previous Line"), original: 'Select To Previous Line' }, f1: true, category, @@ -986,7 +986,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_TO_NEXT_LINE, + id: TerminalCommandId.SelectToNextLine, title: { value: localize('workbench.action.terminal.selectToNextLine', "Select To Next Line"), original: 'Select To Next Line' }, f1: true, category, @@ -1003,7 +1003,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.TOGGLE_ESCAPE_SEQUENCE_LOGGING, + id: TerminalCommandId.ToggleEscapeSequenceLogging, title: { value: localize('workbench.action.terminal.toggleEscapeSequenceLogging', "Toggle Escape Sequence Logging"), original: 'Toggle Escape Sequence Logging' }, f1: true, category, @@ -1018,7 +1018,7 @@ export function registerTerminalActions() { constructor() { const title = localize('workbench.action.terminal.sendSequence', "Send Custom Sequence To Terminal"); super({ - id: TERMINAL_COMMAND_ID.SEND_SEQUENCE, + id: TerminalCommandId.SendSequence, title: { value: title, original: 'Send Custom Sequence To Terminal' }, category, description: { @@ -1045,7 +1045,7 @@ export function registerTerminalActions() { constructor() { const title = localize('workbench.action.terminal.newWithCwd', "Create New Integrated Terminal Starting in a Custom Working Directory"); super({ - id: TERMINAL_COMMAND_ID.NEW_WITH_CWD, + id: TerminalCommandId.NewWithCwd, title: { value: title, original: 'Create New Integrated Terminal Starting in a Custom Working Directory' }, category, description: { @@ -1083,7 +1083,7 @@ export function registerTerminalActions() { constructor() { const title = localize('workbench.action.terminal.renameWithArg', "Rename the Currently Active Terminal"); super({ - id: TERMINAL_COMMAND_ID.RENAME_WITH_ARG, + id: TerminalCommandId.RenameWithArgs, title: { value: title, original: 'Rename the Currently Active Terminal' }, category, description: { @@ -1118,7 +1118,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX, + id: TerminalCommandId.ToggleFindRegex, title: { value: localize('workbench.action.terminal.toggleFindRegex', "Toggle Find Using Regex"), original: 'Toggle Find Using Regex' }, f1: true, category, @@ -1139,7 +1139,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD, + id: TerminalCommandId.ToggleFindWholeWord, title: { value: localize('workbench.action.terminal.toggleFindWholeWord', "Toggle Find Using Whole Word"), original: 'Toggle Find Using Whole Word' }, f1: true, category, @@ -1160,7 +1160,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE, + id: TerminalCommandId.ToggleFindCaseSensitive, title: { value: localize('workbench.action.terminal.toggleFindCaseSensitive', "Toggle Find Using Case Sensitive"), original: 'Toggle Find Using Case Sensitive' }, f1: true, category, @@ -1181,7 +1181,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FIND_NEXT, + id: TerminalCommandId.FindNext, title: { value: localize('workbench.action.terminal.findNext', "Find Next"), original: 'Find Next' }, f1: true, category, @@ -1208,7 +1208,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.FIND_PREVIOUS, + id: TerminalCommandId.FindPrevious, title: { value: localize('workbench.action.terminal.findPrevious', "Find Previous"), original: 'Find Previous' }, f1: true, category, @@ -1235,7 +1235,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SEARCH_WORKSPACE, + id: TerminalCommandId.SearchWorkspace, title: { value: localize('workbench.action.terminal.searchWorkspace', "Search Workspace"), original: 'Search Workspace' }, f1: true, category, @@ -1257,7 +1257,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.RELAUNCH, + id: TerminalCommandId.Relaunch, title: { value: localize('workbench.action.terminal.relaunch', "Relaunch Active Terminal"), original: 'Relaunch Active Terminal' }, f1: true, category, @@ -1271,7 +1271,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SHOW_ENVIRONMENT_INFORMATION, + id: TerminalCommandId.ShowEnvironmentInformation, title: { value: localize('workbench.action.terminal.showEnvironmentInformation', "Show Environment Information"), original: 'Show Environment Information' }, f1: true, category, @@ -1285,7 +1285,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SPLIT, + id: TerminalCommandId.Split, title: { value: localize('workbench.action.terminal.split', "Split Terminal"), original: 'Split Terminal' }, f1: true, category, @@ -1326,7 +1326,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SPLIT_INSTANCE, + id: TerminalCommandId.SplitInstance, title: { value: localize('workbench.action.terminal.split', "Split Terminal"), original: 'Split Terminal' }, f1: false, category, @@ -1356,7 +1356,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SPLIT_IN_ACTIVE_WORKSPACE, + id: TerminalCommandId.SplitInActiveWorkspace, title: { value: localize('workbench.action.terminal.splitInActiveWorkspace', "Split Terminal (In Active Workspace)"), original: 'Split Terminal (In Active Workspace)' }, f1: true, category, @@ -1375,7 +1375,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_ALL, + id: TerminalCommandId.SelectAll, title: { value: localize('workbench.action.terminal.selectAll', "Select All"), original: 'Select All' }, f1: true, category, @@ -1400,7 +1400,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.NEW, + id: TerminalCommandId.New, title: { value: localize('workbench.action.terminal.new', "Create New Integrated Terminal"), original: 'Create New Integrated Terminal' }, f1: true, category, @@ -1452,7 +1452,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.KILL, + id: TerminalCommandId.Kill, title: { value: localize('workbench.action.terminal.kill', "Kill the Active Terminal Instance"), original: 'Kill the Active Terminal Instance' }, f1: true, category, @@ -1464,7 +1464,7 @@ export function registerTerminalActions() { order: 3, when: ContextKeyAndExpr.create([ ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID), - ContextKeyExpr.not(`config.${TERMINAL_SETTING_ID.TabsEnabled}`) + ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`) ]) } }); @@ -1483,7 +1483,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.KILL_INSTANCE, + id: TerminalCommandId.KillInstance, title: { value: localize('workbench.action.terminal.kill.short', "Kill Terminal"), original: 'Kill Terminal' }, @@ -1513,7 +1513,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CLEAR, + id: TerminalCommandId.Clear, title: { value: localize('workbench.action.terminal.clear', "Clear"), original: 'Clear' }, f1: true, category, @@ -1538,7 +1538,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SELECT_DEFAULT_PROFILE, + id: TerminalCommandId.SelectDefaultProfile, title: { value: localize('workbench.action.terminal.selectDefaultProfile', "Select Default Profile"), original: 'Select Default Profile' }, f1: true, category, @@ -1553,8 +1553,8 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CREATE_WITH_PROFILE_BUTTON, - title: TERMINAL_COMMAND_ID.CREATE_WITH_PROFILE_BUTTON, + id: TerminalCommandId.CreateWithProfileButton, + title: TerminalCommandId.CreateWithProfileButton, f1: false, category, precondition: KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, @@ -1575,7 +1575,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.CONFIGURE_TERMINAL_SETTINGS, + id: TerminalCommandId.ConfigureTerminalSettings, title: { value: localize('workbench.action.terminal.openSettings', "Configure Terminal Settings"), original: 'Configure Terminal Settings' }, f1: true, category, @@ -1592,7 +1592,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.COPY_SELECTION, + id: TerminalCommandId.CopySelection, title: { value: localize('workbench.action.terminal.copySelection', "Copy Selection"), original: 'Copy Selection' }, f1: true, category, @@ -1617,7 +1617,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.PASTE, + id: TerminalCommandId.Paste, title: { value: localize('workbench.action.terminal.paste', "Paste into Active Terminal"), original: 'Paste into Active Terminal' }, f1: true, category, @@ -1641,7 +1641,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.PASTE_SELECTION, + id: TerminalCommandId.PasteSelection, title: { value: localize('workbench.action.terminal.pasteSelection', "Paste Selection into Active Terminal"), original: 'Paste Selection into Active Terminal' }, f1: true, category, @@ -1663,7 +1663,7 @@ export function registerTerminalActions() { registerAction2(class extends Action2 { constructor() { super({ - id: TERMINAL_COMMAND_ID.SWITCH_TERMINAL, + id: TerminalCommandId.SwitchTerminal, title: switchTerminalTitle, f1: true, category, @@ -1682,7 +1682,7 @@ export function registerTerminalActions() { return Promise.resolve(null); } if (item === switchTerminalShowTabsTitle) { - accessor.get(IConfigurationService).updateValue(TERMINAL_SETTING_ID.TabsEnabled, true); + accessor.get(IConfigurationService).updateValue(TerminalSettingId.TabsEnabled, true); return; } const indexMatches = terminalIndexRe.exec(item); @@ -1721,7 +1721,8 @@ interface IRemoteTerminalPick extends IQuickPickItem { function getSelectedInstances(accessor: ServicesAccessor): ITerminalInstance[] | undefined { const listService = accessor.get(IListService); - if (!listService.lastFocusedList?.getSelection()?.length) { + const terminalService = accessor.get(ITerminalService); + if (!listService.lastFocusedList?.getSelection()) { return undefined; } const selections = listService.lastFocusedList.getSelection(); @@ -1731,17 +1732,13 @@ function getSelectedInstances(accessor: ServicesAccessor): ITerminalInstance[] | if (focused.length === 1 && !selections.includes(focused[0])) { // focused length is always a max of 1 // if the focused one is not in the selected list, return that item - if ('instanceId' in focused[0]) { - instances.push(focused[0] as ITerminalInstance); - return instances; - } + instances.push(terminalService.getInstanceFromIndex(focused[0]) as ITerminalInstance); + return instances; } // multi-select - for (const instance of selections) { - if ('instanceId' in instance) { - instances.push(instance as ITerminalInstance); - } + for (const selection of selections) { + instances.push(terminalService.getInstanceFromIndex(selection) as ITerminalInstance); } return instances; } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts index fba304d7d48..dec49816588 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalConfigHelper.ts @@ -6,10 +6,10 @@ import * as nls from 'vs/nls'; import { EDITOR_FONT_DEFAULTS, IEditorOptions } from 'vs/editor/common/config/editorOptions'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; -import { ITerminalConfiguration, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, LinuxDistro, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_FONT_WEIGHT, DEFAULT_BOLD_FONT_WEIGHT, FontWeight, ITerminalFont } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalConfiguration, TERMINAL_CONFIG_SECTION, DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, MINIMUM_LETTER_SPACING, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_FONT_WEIGHT, DEFAULT_BOLD_FONT_WEIGHT, FontWeight, ITerminalFont } from 'vs/workbench/contrib/terminal/common/terminal'; import Severity from 'vs/base/common/severity'; import { INotificationService, NeverShowAgainScope } from 'vs/platform/notification/common/notification'; -import { IBrowserTerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IBrowserTerminalConfigHelper, LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal'; import { Emitter, Event } from 'vs/base/common/event'; import { basename } from 'vs/base/common/path'; import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement'; @@ -19,7 +19,7 @@ import { InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensio import { IProductService } from 'vs/platform/product/common/productService'; import { XTermCore } from 'vs/workbench/contrib/terminal/browser/xterm-private'; import { IShellLaunchConfig } from 'vs/platform/terminal/common/terminal'; -import { isWindows } from 'vs/base/common/platform'; +import { isLinux, isWindows } from 'vs/base/common/platform'; const MINIMUM_FONT_SIZE = 6; const MAXIMUM_FONT_SIZE = 25; @@ -29,23 +29,23 @@ const MAXIMUM_FONT_SIZE = 25; * specific test cases can be written. */ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { - public panelContainer: HTMLElement | undefined; + panelContainer: HTMLElement | undefined; private _charMeasureElement: HTMLElement | undefined; private _lastFontMeasurement: ITerminalFont | undefined; - private _linuxDistro: LinuxDistro = LinuxDistro.Unknown; - public config!: ITerminalConfiguration; + protected _linuxDistro: LinuxDistro = LinuxDistro.Unknown; + config!: ITerminalConfiguration; private readonly _onConfigChanged = new Emitter(); - public get onConfigChanged(): Event { return this._onConfigChanged.event; } + get onConfigChanged(): Event { return this._onConfigChanged.event; } - public constructor( + constructor( @IConfigurationService private readonly _configurationService: IConfigurationService, @IExtensionManagementService private readonly _extensionManagementService: IExtensionManagementService, @INotificationService private readonly _notificationService: INotificationService, - @ITelemetryService private readonly telemetryService: ITelemetryService, - @IInstantiationService private readonly instantiationService: IInstantiationService, - @IProductService private readonly productService: IProductService, + @ITelemetryService private readonly _telemetryService: ITelemetryService, + @IInstantiationService private readonly _instantiationService: IInstantiationService, + @IProductService private readonly _productService: IProductService, ) { this._updateConfig(); this._configurationService.onDidChangeConfiguration(e => { @@ -53,10 +53,13 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { this._updateConfig(); } }); - } - - public setLinuxDistro(linuxDistro: LinuxDistro) { - this._linuxDistro = linuxDistro; + if (isLinux) { + if (navigator.userAgent.includes('Ubuntu')) { + this._linuxDistro = LinuxDistro.Ubuntu; + } else if (navigator.userAgent.includes('Fedora')) { + this._linuxDistro = LinuxDistro.Fedora; + } + } } private _updateConfig(): void { @@ -68,18 +71,18 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { this._onConfigChanged.fire(); } - public configFontIsMonospace(): boolean { + configFontIsMonospace(): boolean { const fontSize = 15; const fontFamily = this.config.fontFamily || this._configurationService.getValue('editor').fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; - const i_rect = this._getBoundingRectFor('i', fontFamily, fontSize); - const w_rect = this._getBoundingRectFor('w', fontFamily, fontSize); + const iRect = this._getBoundingRectFor('i', fontFamily, fontSize); + const wRect = this._getBoundingRectFor('w', fontFamily, fontSize); // Check for invalid bounds, there is no reason to believe the font is not monospace - if (!i_rect || !w_rect || !i_rect.width || !w_rect.width) { + if (!iRect || !wRect || !iRect.width || !wRect.width) { return true; } - return i_rect.width === w_rect.width; + return iRect.width === wRect.width; } private _createCharMeasureElementIfNecessary(): HTMLElement { @@ -151,7 +154,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { * Gets the font information based on the terminal.integrated.fontFamily * terminal.integrated.fontSize, terminal.integrated.lineHeight configuration properties */ - public getFont(xtermCore?: XTermCore, excludeDimensions?: boolean): ITerminalFont { + getFont(xtermCore?: XTermCore, excludeDimensions?: boolean): ITerminalFont { const editorConfig = this._configurationService.getValue('editor'); let fontFamily = this.config.fontFamily || editorConfig.fontFamily || EDITOR_FONT_DEFAULTS.fontFamily; @@ -214,21 +217,21 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { return r; } - private recommendationsShown = false; + private _recommendationsShown = false; - public async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise { - if (this.recommendationsShown) { + async showRecommendations(shellLaunchConfig: IShellLaunchConfig): Promise { + if (this._recommendationsShown) { return; } - this.recommendationsShown = true; + this._recommendationsShown = true; if (isWindows && shellLaunchConfig.executable && basename(shellLaunchConfig.executable).toLowerCase() === 'wsl.exe') { - const exeBasedExtensionTips = this.productService.exeBasedExtensionTips; + const exeBasedExtensionTips = this._productService.exeBasedExtensionTips; if (!exeBasedExtensionTips || !exeBasedExtensionTips.wsl) { return; } const extId = Object.keys(exeBasedExtensionTips.wsl.recommendations).find(extId => exeBasedExtensionTips.wsl.recommendations[extId].important); - if (extId && ! await this.isExtensionInstalled(extId)) { + if (extId && ! await this._isExtensionInstalled(extId)) { this._notificationService.prompt( Severity.Info, nls.localize( @@ -243,8 +246,8 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { "extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'install', extId }); - this.instantiationService.createInstance(InstallRecommendedExtensionAction, extId).run(); + this._telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'install', extId }); + this._instantiationService.createInstance(InstallRecommendedExtensionAction, extId).run(); } } ], @@ -257,7 +260,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { "userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" } } */ - this.telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'cancelled' }); + this._telemetryService.publicLog('terminalLaunchRecommendation:popup', { userReaction: 'cancelled' }); } } ); @@ -265,7 +268,7 @@ export class TerminalConfigHelper implements IBrowserTerminalConfigHelper { } } - private async isExtensionInstalled(id: string): Promise { + private async _isExtensionInstalled(id: string): Promise { const extensions = await this._extensionManagementService.getInstalled(); return extensions.some(e => e.identifier.id === id); } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts index 038c3424f80..4d9ac4ed1f1 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalFindWidget.ts @@ -28,7 +28,7 @@ export class TerminalFindWidget extends SimpleFindWidget { this._findWidgetFocused = KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED.bindTo(this._contextKeyService); } - public find(previous: boolean) { + find(previous: boolean) { const instance = this._terminalService.getActiveInstance(); if (instance !== null) { if (previous) { @@ -39,7 +39,7 @@ export class TerminalFindWidget extends SimpleFindWidget { } } - public override hide() { + override hide() { super.hide(); const instance = this._terminalService.getActiveInstance(); if (instance) { @@ -47,7 +47,7 @@ export class TerminalFindWidget extends SimpleFindWidget { } } - protected onInputChanged() { + protected _onInputChanged() { // Ignore input changes for now const instance = this._terminalService.getActiveInstance(); if (instance !== null) { @@ -56,7 +56,7 @@ export class TerminalFindWidget extends SimpleFindWidget { return false; } - protected onFocusTrackerFocus() { + protected _onFocusTrackerFocus() { const instance = this._terminalService.getActiveInstance(); if (instance) { instance.notifyFindWidgetFocusChanged(true); @@ -64,7 +64,7 @@ export class TerminalFindWidget extends SimpleFindWidget { this._findWidgetFocused.set(true); } - protected onFocusTrackerBlur() { + protected _onFocusTrackerBlur() { const instance = this._terminalService.getActiveInstance(); if (instance) { instance.notifyFindWidgetFocusChanged(false); @@ -72,15 +72,15 @@ export class TerminalFindWidget extends SimpleFindWidget { this._findWidgetFocused.reset(); } - protected onFindInputFocusTrackerFocus() { + protected _onFindInputFocusTrackerFocus() { this._findInputFocused.set(true); } - protected onFindInputFocusTrackerBlur() { + protected _onFindInputFocusTrackerBlur() { this._findInputFocused.reset(); } - public findFirst() { + findFirst() { const instance = this._terminalService.getActiveInstance(); if (instance) { if (instance.hasSelection()) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts b/src/vs/workbench/contrib/terminal/browser/terminalGroup.ts similarity index 83% rename from src/vs/workbench/contrib/terminal/browser/terminalTab.ts rename to src/vs/workbench/contrib/terminal/browser/terminalGroup.ts index b8c3628e45f..6525aaa2a1d 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTab.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalGroup.ts @@ -9,7 +9,7 @@ import { IDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecyc import { SplitView, Orientation, IView, Sizing } from 'vs/base/browser/ui/splitview/splitview'; import { IWorkbenchLayoutService, Parts, Position } from 'vs/workbench/services/layout/browser/layoutService'; import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { ITerminalInstance, Direction, ITerminalTab, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { ITerminalInstance, Direction, ITerminalGroup, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ViewContainerLocation, IViewDescriptorService } from 'vs/workbench/common/views'; import { IShellLaunchConfig, ITerminalTabLayoutInfoById } from 'vs/platform/terminal/common/terminal'; @@ -23,7 +23,7 @@ class SplitPaneContainer extends Disposable { private _children: SplitPane[] = []; private _onDidChange: Event = Event.None; - public get onDidChange(): Event { return this._onDidChange; } + get onDidChange(): Event { return this._onDidChange; } constructor( private _container: HTMLElement, @@ -43,11 +43,11 @@ class SplitPaneContainer extends Disposable { this._splitViewDisposables.add(this._splitView.onDidSashReset(() => this._splitView.distributeViewSizes())); } - public split(instance: ITerminalInstance, index: number = this._children.length): void { + split(instance: ITerminalInstance, index: number = this._children.length): void { this._addChild(instance, index); } - public resizePane(index: number, direction: Direction, amount: number): void { + resizePane(index: number, direction: Direction, amount: number): void { const isHorizontal = (direction === Direction.Left) || (direction === Direction.Right); if ((isHorizontal && this.orientation !== Orientation.HORIZONTAL) || @@ -101,7 +101,7 @@ class SplitPaneContainer extends Disposable { } } - public resizePanes(relativeSizes: number[]): void { + resizePanes(relativeSizes: number[]): void { if (this._children.length <= 1) { return; } @@ -131,7 +131,7 @@ class SplitPaneContainer extends Disposable { this._onDidChange = Event.any(...this._children.map(c => c.onDidChange)); } - public remove(instance: ITerminalInstance): void { + remove(instance: ITerminalInstance): void { let index: number | null = null; for (let i = 0; i < this._children.length; i++) { if (this._children[i].instance === instance) { @@ -144,7 +144,7 @@ class SplitPaneContainer extends Disposable { } } - public layout(width: number, height: number): void { + layout(width: number, height: number): void { this._width = width; this._height = height; if (this.orientation === Orientation.HORIZONTAL) { @@ -156,7 +156,7 @@ class SplitPaneContainer extends Disposable { } } - public setOrientation(orientation: Orientation): void { + setOrientation(orientation: Orientation): void { if (this.orientation === orientation) { return; } @@ -189,13 +189,13 @@ class SplitPaneContainer extends Disposable { } class SplitPane implements IView { - public minimumSize: number = SPLIT_PANE_MIN_SIZE; - public maximumSize: number = Number.MAX_VALUE; + minimumSize: number = SPLIT_PANE_MIN_SIZE; + maximumSize: number = Number.MAX_VALUE; - public orientation: Orientation | undefined; + orientation: Orientation | undefined; private _onDidChange: Event = Event.None; - public get onDidChange(): Event { return this._onDidChange; } + get onDidChange(): Event { return this._onDidChange; } readonly element: HTMLElement; @@ -208,7 +208,7 @@ class SplitPane implements IView { this.instance.attachToElement(this.element); } - public layout(size: number): void { + layout(size: number): void { // Only layout when both sizes are known if (!size || !this.orthogonalSize) { return; @@ -221,32 +221,31 @@ class SplitPane implements IView { } } - public orthogonalLayout(size: number): void { + orthogonalLayout(size: number): void { this.orthogonalSize = size; } } -export class TerminalTab extends Disposable implements ITerminalTab { +export class TerminalGroup extends Disposable implements ITerminalGroup { private _terminalInstances: ITerminalInstance[] = []; private _splitPaneContainer: SplitPaneContainer | undefined; - private get splitPaneContainer(): SplitPaneContainer | undefined { return this._splitPaneContainer; } - private _tabElement: HTMLElement | undefined; + private _groupElement: HTMLElement | undefined; private _panelPosition: Position = Position.BOTTOM; private _terminalLocation: ViewContainerLocation = ViewContainerLocation.Panel; private _activeInstanceIndex: number; private _isVisible: boolean = false; - public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } + get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } private _initialRelativeSizes: number[] | undefined; - private readonly _onDisposed: Emitter = this._register(new Emitter()); - public readonly onDisposed: Event = this._onDisposed.event; + private readonly _onDisposed: Emitter = this._register(new Emitter()); + public readonly onDisposed: Event = this._onDisposed.event; private readonly _onInstancesChanged: Emitter = this._register(new Emitter()); - public readonly onInstancesChanged: Event = this._onInstancesChanged.event; + readonly onInstancesChanged: Event = this._onInstancesChanged.event; private readonly _onPanelMovedToSide = new Emitter(); - public get onPanelMovedToSide(): Event { return this._onPanelMovedToSide.event; } + get onPanelMovedToSide(): Event { return this._onPanelMovedToSide.event; } constructor( private _container: HTMLElement | undefined, shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance | undefined, @@ -265,7 +264,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { } } - public addInstance(shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance): void { + addInstance(shellLaunchConfigOrInstance: IShellLaunchConfig | ITerminalInstance): void { let instance: ITerminalInstance; if ('instanceId' in shellLaunchConfigOrInstance) { instance = shellLaunchConfigOrInstance; @@ -282,25 +281,25 @@ export class TerminalTab extends Disposable implements ITerminalTab { this._onInstancesChanged.fire(); } - public override dispose(): void { + override dispose(): void { super.dispose(); - if (this._container && this._tabElement) { - this._container.removeChild(this._tabElement); - this._tabElement = undefined; + if (this._container && this._groupElement) { + this._container.removeChild(this._groupElement); + this._groupElement = undefined; } this._terminalInstances = []; this._onInstancesChanged.fire(); } - public get activeInstance(): ITerminalInstance | null { + get activeInstance(): ITerminalInstance | null { if (this._terminalInstances.length === 0) { return null; } return this._terminalInstances[this._activeInstanceIndex]; } - public getLayoutInfo(isActive: boolean): ITerminalTabLayoutInfoById { - const isHorizontal = this.splitPaneContainer?.orientation === Orientation.HORIZONTAL; + getLayoutInfo(isActive: boolean): ITerminalTabLayoutInfoById { + const isHorizontal = this._splitPaneContainer?.orientation === Orientation.HORIZONTAL; const instances = this.terminalInstances.filter(instance => typeof instance.persistentProcessId === 'number' && instance.shouldPersist); const totalSize = instances.map(instance => isHorizontal ? instance.cols : instance.rows).reduce((totalValue, currentValue) => totalValue + currentValue, 0); return { @@ -332,7 +331,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { if (wasActiveInstance && this._terminalInstances.length > 0) { const newIndex = index < this._terminalInstances.length ? index : this._terminalInstances.length - 1; this.setActiveInstanceByIndex(newIndex); - // TODO: Only focus the new instance if the tab had focus? + // TODO: Only focus the new instance if the group had focus? if (this.activeInstance) { this.activeInstance.focus(true); } @@ -346,7 +345,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { this._splitPaneContainer.remove(instance); } - // Fire events and dispose tab if it was the last instance + // Fire events and dispose group if it was the last instance if (this._terminalInstances.length === 0) { this._onDisposed.fire(this); this.dispose(); @@ -372,7 +371,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { return terminalIndex; } - public setActiveInstanceByIndex(index: number): void { + setActiveInstanceByIndex(index: number): void { // Check for invalid value if (index < 0 || index >= this._terminalInstances.length) { return; @@ -386,31 +385,31 @@ export class TerminalTab extends Disposable implements ITerminalTab { } } - public attachToElement(element: HTMLElement): void { + attachToElement(element: HTMLElement): void { this._container = element; - // If we already have a tab element, we can reparent it - if (!this._tabElement) { - this._tabElement = document.createElement('div'); - this._tabElement.classList.add('terminal-tab'); + // If we already have a group element, we can reparent it + if (!this._groupElement) { + this._groupElement = document.createElement('div'); + this._groupElement.classList.add('terminal-group'); } - this._container.appendChild(this._tabElement); + this._container.appendChild(this._groupElement); if (!this._splitPaneContainer) { this._panelPosition = this._layoutService.getPanelPosition(); this._terminalLocation = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID)!; const orientation = this._terminalLocation === ViewContainerLocation.Panel && this._panelPosition === Position.BOTTOM ? Orientation.HORIZONTAL : Orientation.VERTICAL; - const newLocal = this._instantiationService.createInstance(SplitPaneContainer, this._tabElement, orientation); + const newLocal = this._instantiationService.createInstance(SplitPaneContainer, this._groupElement, orientation); this._splitPaneContainer = newLocal; this.terminalInstances.forEach(instance => this._splitPaneContainer!.split(instance)); } this.setVisible(this._isVisible); } - public get title(): string { + get title(): string { if (this._terminalInstances.length === 0) { - // Normally consumers should not call into title at all after the tab is disposed but - // this is required when the tab is used as part of a tree. + // Normally consumers should not call into title at all after the group is disposed but + // this is required when the group is used as part of a tree. return ''; } let title = this.terminalInstances[0].title; @@ -429,15 +428,15 @@ export class TerminalTab extends Disposable implements ITerminalTab { return title; } - public setVisible(visible: boolean): void { + setVisible(visible: boolean): void { this._isVisible = visible; - if (this._tabElement) { - this._tabElement.style.display = visible ? '' : 'none'; + if (this._groupElement) { + this._groupElement.style.display = visible ? '' : 'none'; } this.terminalInstances.forEach(i => i.setVisible(visible)); } - public split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { + split(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { const instance = this._terminalService.createInstance(undefined, shellLaunchConfig); this._terminalInstances.splice(this._activeInstanceIndex + 1, 0, instance); this._initInstanceListeners(instance); @@ -450,11 +449,11 @@ export class TerminalTab extends Disposable implements ITerminalTab { return instance; } - public addDisposable(disposable: IDisposable): void { + addDisposable(disposable: IDisposable): void { this._register(disposable); } - public layout(width: number, height: number): void { + layout(width: number, height: number): void { if (this._splitPaneContainer) { // Check if the panel position changed and rotate panes if so const newPanelPosition = this._layoutService.getPanelPosition(); @@ -477,17 +476,17 @@ export class TerminalTab extends Disposable implements ITerminalTab { } } - public focusPreviousPane(): void { + focusPreviousPane(): void { const newIndex = this._activeInstanceIndex === 0 ? this._terminalInstances.length - 1 : this._activeInstanceIndex - 1; this.setActiveInstanceByIndex(newIndex); } - public focusNextPane(): void { + focusNextPane(): void { const newIndex = this._activeInstanceIndex === this._terminalInstances.length - 1 ? 0 : this._activeInstanceIndex + 1; this.setActiveInstanceByIndex(newIndex); } - public resizePane(direction: Direction): void { + resizePane(direction: Direction): void { if (!this._splitPaneContainer) { return; } @@ -501,7 +500,7 @@ export class TerminalTab extends Disposable implements ITerminalTab { } } - public resizePanes(relativeSizes: number[]): void { + resizePanes(relativeSizes: number[]): void { if (!this._splitPaneContainer) { this._initialRelativeSizes = relativeSizes; return; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts index ee104d5b413..046becf93ec 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstance.ts @@ -24,14 +24,14 @@ import { activeContrastBorder, scrollbarSliderActiveBackground, scrollbarSliderB import { ICssStyleCollector, IColorTheme, IThemeService, registerThemingParticipant } from 'vs/platform/theme/common/themeService'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { TerminalWidgetManager } from 'vs/workbench/contrib/terminal/browser/widgets/widgetManager'; -import { ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, TERMINAL_CREATION_COMMANDS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, SUGGESTED_RENDERER_TYPE, ITerminalProfileResolverService, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProcessManager, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, NEVER_MEASURE_RENDER_TIME_STORAGE_KEY, ProcessState, TERMINAL_VIEW_ID, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, INavigationMode, TitleEventSource, DEFAULT_COMMANDS_TO_SKIP_SHELL, TERMINAL_CREATION_COMMANDS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, SUGGESTED_RENDERER_TYPE, ITerminalProfileResolverService, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { ansiColorIdentifiers, TERMINAL_BACKGROUND_COLOR, TERMINAL_CURSOR_BACKGROUND_COLOR, TERMINAL_CURSOR_FOREGROUND_COLOR, TERMINAL_FOREGROUND_COLOR, TERMINAL_SELECTION_BACKGROUND_COLOR } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalLinkManager } from 'vs/workbench/contrib/terminal/browser/links/terminalLinkManager'; import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; import { ITerminalInstanceService, ITerminalInstance, ITerminalExternalLinkProvider } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalProcessManager } from 'vs/workbench/contrib/terminal/browser/terminalProcessManager'; -import type { Terminal as XTermTerminal, IBuffer, ITerminalAddon, RendererType } from 'xterm'; +import type { Terminal as XTermTerminal, IBuffer, ITerminalAddon, RendererType, ITheme } from 'xterm'; import type { SearchAddon, ISearchOptions } from 'xterm-addon-search'; import type { Unicode11Addon } from 'xterm-addon-unicode11'; import type { WebglAddon } from 'xterm-addon-webgl'; @@ -85,8 +85,6 @@ interface IGridDimensions { } export class TerminalInstance extends Disposable implements ITerminalInstance { - private static readonly EOL_REGEX = /\r?\n/g; - private static _lastKnownCanvasDimensions: ICanvasDimensions | undefined; private static _lastKnownGridDimensions: IGridDimensions | undefined; private static _instanceIdCounter = 1; @@ -135,19 +133,19 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { private _timeoutDimension: dom.Dimension | undefined; - private hasHadInput: boolean; + private _hasHadInput: boolean; - public readonly statusList: ITerminalStatusList = new TerminalStatusList(); - public disableLayout: boolean; - public get instanceId(): number { return this._instanceId; } - public get resource(): URI { + readonly statusList: ITerminalStatusList = new TerminalStatusList(); + disableLayout: boolean; + get instanceId(): number { return this._instanceId; } + get resource(): URI { return URI.from({ scheme: Schemas.vscodeTerminal, path: this.title, fragment: this.instanceId.toString(), }); } - public get cols(): number { + get cols(): number { if (this._dimensionsOverride && this._dimensionsOverride.cols) { if (this._dimensionsOverride.forceExactSize) { return this._dimensionsOverride.cols; @@ -156,7 +154,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } return this._cols; } - public get rows(): number { + get rows(): number { if (this._dimensionsOverride && this._dimensionsOverride.rows) { if (this._dimensionsOverride.forceExactSize) { return this._dimensionsOverride.rows; @@ -165,54 +163,57 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } return this._rows; } - public get maxCols(): number { return this._cols; } - public get maxRows(): number { return this._rows; } + get maxCols(): number { return this._cols; } + get maxRows(): number { return this._rows; } // TODO: Ideally processId would be merged into processReady - public get processId(): number | undefined { return this._processManager.shellProcessId; } + get processId(): number | undefined { return this._processManager.shellProcessId; } // TODO: How does this work with detached processes? // TODO: Should this be an event as it can fire twice? - public get processReady(): Promise { return this._processManager.ptyProcessReady; } - public get areLinksReady(): boolean { return this._areLinksReady; } - public get initialDataEvents(): string[] | undefined { return this._initialDataEvents; } - public get exitCode(): number | undefined { return this._exitCode; } - public get title(): string { return this._title; } - public get hadFocusOnExit(): boolean { return this._hadFocusOnExit; } - public get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; } - public get shellLaunchConfig(): IShellLaunchConfig { return this._shellLaunchConfig; } - public get shellType(): TerminalShellType { return this._shellType; } - public get commandTracker(): CommandTrackerAddon | undefined { return this._commandTrackerAddon; } - public get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; } - public get isDisconnected(): boolean { return this._processManager.isDisconnected; } - public get icon(): Codicon | undefined { return this._getIcon(); } + get processReady(): Promise { return this._processManager.ptyProcessReady; } + get areLinksReady(): boolean { return this._areLinksReady; } + get initialDataEvents(): string[] | undefined { return this._initialDataEvents; } + get exitCode(): number | undefined { return this._exitCode; } + get title(): string { return this._title; } + get hadFocusOnExit(): boolean { return this._hadFocusOnExit; } + get isTitleSetByProcess(): boolean { return !!this._messageTitleDisposable; } + get shellLaunchConfig(): IShellLaunchConfig { return this._shellLaunchConfig; } + get shellType(): TerminalShellType { return this._shellType; } + get commandTracker(): CommandTrackerAddon | undefined { return this._commandTrackerAddon; } + get navigationMode(): INavigationMode | undefined { return this._navigationModeAddon; } + get isDisconnected(): boolean { return this._processManager.isDisconnected; } + get isRemote(): boolean { return this._processManager.remoteAuthority !== undefined; } + get icon(): Codicon | undefined { return this._getIcon(); } private readonly _onExit = new Emitter(); - public get onExit(): Event { return this._onExit.event; } + get onExit(): Event { return this._onExit.event; } private readonly _onDisposed = new Emitter(); - public get onDisposed(): Event { return this._onDisposed.event; } + get onDisposed(): Event { return this._onDisposed.event; } private readonly _onFocused = new Emitter(); - public get onFocused(): Event { return this._onFocused.event; } + get onFocused(): Event { return this._onFocused.event; } + private readonly _onDropped = new Emitter<{ instance: ITerminalInstance, dragEvent: DragEvent; }>(); + get onDropped(): Event<{ instance: ITerminalInstance, dragEvent: DragEvent; }> { return this._onDropped.event; } private readonly _onProcessIdReady = new Emitter(); - public get onProcessIdReady(): Event { return this._onProcessIdReady.event; } + get onProcessIdReady(): Event { return this._onProcessIdReady.event; } private readonly _onLinksReady = new Emitter(); - public get onLinksReady(): Event { return this._onLinksReady.event; } + get onLinksReady(): Event { return this._onLinksReady.event; } private readonly _onTitleChanged = new Emitter(); - public get onTitleChanged(): Event { return this._onTitleChanged.event; } + get onTitleChanged(): Event { return this._onTitleChanged.event; } private readonly _onData = new Emitter(); - public get onData(): Event { return this._onData.event; } + get onData(): Event { return this._onData.event; } private readonly _onBinary = new Emitter(); - public get onBinary(): Event { return this._onBinary.event; } + get onBinary(): Event { return this._onBinary.event; } private readonly _onLineData = new Emitter(); - public get onLineData(): Event { return this._onLineData.event; } + get onLineData(): Event { return this._onLineData.event; } private readonly _onRequestExtHostProcess = new Emitter(); - public get onRequestExtHostProcess(): Event { return this._onRequestExtHostProcess.event; } + get onRequestExtHostProcess(): Event { return this._onRequestExtHostProcess.event; } private readonly _onDimensionsChanged = new Emitter(); - public get onDimensionsChanged(): Event { return this._onDimensionsChanged.event; } + get onDimensionsChanged(): Event { return this._onDimensionsChanged.event; } private readonly _onMaximumDimensionsChanged = new Emitter(); - public get onMaximumDimensionsChanged(): Event { return this._onMaximumDimensionsChanged.event; } + get onMaximumDimensionsChanged(): Event { return this._onMaximumDimensionsChanged.event; } private readonly _onFocus = new Emitter(); - public get onFocus(): Event { return this._onFocus.event; } + get onFocus(): Event { return this._onFocus.event; } - public constructor( + constructor( private readonly _terminalFocusContextKey: IContextKey, private readonly _terminalShellTypeContextKey: IContextKey, private readonly _terminalAltBufferActiveContextKey: IContextKey, @@ -247,7 +248,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._isDisposed = false; this._instanceId = TerminalInstance._instanceIdCounter++; - this.hasHadInput = false; + this._hasHadInput = false; this._titleReadyPromise = new Promise(c => { this._titleReadyComplete = c; }); @@ -291,13 +292,13 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // supported. this.setVisible(this._isVisible); } - if (e.affectsConfiguration(TERMINAL_SETTING_ID.UnicodeVersion)) { + if (e.affectsConfiguration(TerminalSettingId.UnicodeVersion)) { this._updateUnicodeVersion(); } if (e.affectsConfiguration('editor.accessibilitySupport')) { this.updateAccessibilitySupport(); } - if (e.affectsConfiguration(TERMINAL_SETTING_ID.GpuAcceleration)) { + if (e.affectsConfiguration(TerminalSettingId.GpuAcceleration)) { this._storageService.remove(SUGGESTED_RENDERER_TYPE, StorageScope.GLOBAL); } })); @@ -326,7 +327,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return undefined; } - public addDisposable(disposable: IDisposable): void { + addDisposable(disposable: IDisposable): void { this._register(disposable); } @@ -430,8 +431,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return TerminalInstance._lastKnownCanvasDimensions; } - public get persistentProcessId(): number | undefined { return this._processManager.persistentProcessId; } - public get shouldPersist(): boolean { return this._processManager.shouldPersist; } + get persistentProcessId(): number | undefined { return this._processManager.persistentProcessId; } + get shouldPersist(): boolean { return this._processManager.shouldPersist; } private async _getXtermConstructor(): Promise { if (xtermConstructor) { @@ -490,8 +491,8 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._xtermCore = (xterm as any)._core as XTermCore; this._updateUnicodeVersion(); this.updateAccessibilitySupport(); - this._terminalInstanceService.getXtermSearchConstructor().then(Addon => { - this._xtermSearch = new Addon(); + this._terminalInstanceService.getXtermSearchConstructor().then(addonCtor => { + this._xtermSearch = new addonCtor(); xterm.loadAddon(this._xtermSearch); }); if (this._shellLaunchConfig.initialText) { @@ -557,7 +558,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return xterm; } - public reattachToElement(container: HTMLElement): void { + reattachToElement(container: HTMLElement): void { if (!this._wrapperElement) { throw new Error('The terminal instance has not been attached to a container yet'); } @@ -567,7 +568,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._container.appendChild(this._wrapperElement); } - public attachToElement(container: HTMLElement): void { + attachToElement(container: HTMLElement): void { // The container did not change, do nothing if (this._container === container) { return; @@ -585,7 +586,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._container.appendChild(this._wrapperElement); } - public async _attachToElement(container: HTMLElement): Promise { + private async _attachToElement(container: HTMLElement): Promise { const xterm = await this._xtermReadyPromise; if (this._wrapperElement) { @@ -644,7 +645,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { !event.ctrlKey && !event.shiftKey && !event.altKey) { - this.hasHadInput = true; + this._hasHadInput = true; } // for keyboard events that resolve to commands described @@ -652,7 +653,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { if (resolveResult && resolveResult.commandId && this._skipTerminalCommands.some(k => k === resolveResult.commandId) && !this._configHelper.config.sendKeybindingsToShell) { // don't alert when terminal is opened or closed if (this._storageService.getBoolean(SHOW_TERMINAL_CONFIG_PROMPT_KEY, StorageScope.GLOBAL, true) && - this.hasHadInput && + this._hasHadInput && !TERMINAL_CREATION_COMMANDS.includes(resolveResult.commandId)) { this._notificationService.prompt( Severity.Info, @@ -661,7 +662,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { { label: nls.localize('configureTerminalSettings', "Configure Terminal Settings"), run: () => { - this._preferencesService.openSettings(false, `@id:${TERMINAL_SETTING_ID.CommandsToSkipShell},${TERMINAL_SETTING_ID.SendKeybindingsToShell},${TERMINAL_SETTING_ID.AllowChords}`); + this._preferencesService.openSettings(false, `@id:${TerminalSettingId.CommandsToSkipShell},${TerminalSettingId.SendKeybindingsToShell},${TerminalSettingId.AllowChords}`); } } as IPromptChoice ] @@ -723,10 +724,16 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } this._onFocused.fire(this); })); + this._register(dom.addDisposableListener(xterm.textarea, 'blur', () => { this._terminalFocusContextKey.reset(); this._refreshSelectionContextKey(); })); + + this._register(dom.addDisposableListener(xterm.element, dom.EventType.DROP, (e: DragEvent) => { + this._onDropped.fire({ instance: this, dragEvent: e }); + })); + this._widgetManager.attachToElement(xterm.element); this._processManager.onProcessReady(() => this._linkManager?.setWidgetManager(this._widgetManager)); @@ -762,7 +769,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { const promptChoices: IPromptChoice[] = [ { label: nls.localize('yes', "Yes"), - run: () => this._configurationService.updateValue(TERMINAL_SETTING_ID.GpuAcceleration, 'off', ConfigurationTarget.USER) + run: () => this._configurationService.updateValue(TerminalSettingId.GpuAcceleration, 'off', ConfigurationTarget.USER) } as IPromptChoice, { label: nls.localize('no', "No"), @@ -795,11 +802,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { }; } - public hasSelection(): boolean { + hasSelection(): boolean { return this._xterm ? this._xterm.hasSelection() : false; } - public async copySelection(): Promise { + async copySelection(): Promise { const xterm = await this._xtermReadyPromise; if (this.hasSelection()) { await this._clipboardService.writeText(xterm.getSelection()); @@ -808,35 +815,35 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public get selection(): string | undefined { + get selection(): string | undefined { return this._xterm && this.hasSelection() ? this._xterm.getSelection() : undefined; } - public clearSelection(): void { + clearSelection(): void { this._xterm?.clearSelection(); } - public selectAll(): void { + selectAll(): void { // Focus here to ensure the terminal context key is set this._xterm?.focus(); this._xterm?.selectAll(); } - public findNext(term: string, searchOptions: ISearchOptions): boolean { + findNext(term: string, searchOptions: ISearchOptions): boolean { if (!this._xtermSearch) { return false; } return this._xtermSearch.findNext(term, searchOptions); } - public findPrevious(term: string, searchOptions: ISearchOptions): boolean { + findPrevious(term: string, searchOptions: ISearchOptions): boolean { if (!this._xtermSearch) { return false; } return this._xtermSearch.findPrevious(term, searchOptions); } - public notifyFindWidgetFocusChanged(isFocused: boolean): void { + notifyFindWidgetFocusChanged(isFocused: boolean): void { if (!this._xterm) { return; } @@ -848,7 +855,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._terminalAltBufferActiveContextKey.set(!!(this._xterm && this._xterm.buffer.active === this._xterm.buffer.alternate)); } - public override dispose(immediate?: boolean): void { + override dispose(immediate?: boolean): void { this._logService.trace(`terminalInstance#dispose (instanceId: ${this.instanceId})`); dispose(this._linkManager); @@ -891,11 +898,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { super.dispose(); } - public detachFromProcess(): void { + detachFromProcess(): void { this._processManager.detachFromProcess(); } - public forceRedraw(): void { + forceRedraw(): void { if (!this._xterm) { return; } @@ -903,7 +910,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // TODO: Do canvas renderer too? } - public focus(force?: boolean): void { + focus(force?: boolean): void { this._refreshAltBufferContextKey(); if (!this._xterm) { return; @@ -918,12 +925,12 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public async focusWhenReady(force?: boolean): Promise { + async focusWhenReady(force?: boolean): Promise { await this._xtermReadyPromise; this.focus(force); } - public async paste(): Promise { + async paste(): Promise { if (!this._xterm) { return; } @@ -931,7 +938,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._xterm.paste(await this._clipboardService.readText()); } - public async pasteSelection(): Promise { + async pasteSelection(): Promise { if (!this._xterm) { return; } @@ -939,9 +946,9 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._xterm.paste(await this._clipboardService.readText('selection')); } - public async sendText(text: string, addNewLine: boolean): Promise { + async sendText(text: string, addNewLine: boolean): Promise { // Normalize line endings to 'enter' press. - text = text.replace(TerminalInstance.EOL_REGEX, '\r'); + text = text.replace(/\r?\n/g, '\r'); if (addNewLine && text.substr(text.length - 1) !== '\r') { text += '\r'; } @@ -950,7 +957,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return this._processManager.write(text); } - public setVisible(visible: boolean): void { + setVisible(visible: boolean): void { this._isVisible = visible; if (this._wrapperElement) { this._wrapperElement.classList.toggle('active', visible); @@ -981,31 +988,31 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public scrollDownLine(): void { + scrollDownLine(): void { this._xterm?.scrollLines(1); } - public scrollDownPage(): void { + scrollDownPage(): void { this._xterm?.scrollPages(1); } - public scrollToBottom(): void { + scrollToBottom(): void { this._xterm?.scrollToBottom(); } - public scrollUpLine(): void { + scrollUpLine(): void { this._xterm?.scrollLines(-1); } - public scrollUpPage(): void { + scrollUpPage(): void { this._xterm?.scrollPages(-1); } - public scrollToTop(): void { + scrollToTop(): void { this._xterm?.scrollToTop(); } - public clear(): void { + clear(): void { this._xterm?.clear(); } @@ -1136,7 +1143,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - if (this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH) { + if (this._processManager.processState === ProcessState.KilledDuringLaunch) { if (commandLine) { exitCodeMessage = nls.localize('launchFailed.exitCodeAndCommandLine', "The terminal process \"{0}\" failed to launch (exit code: {1}).", commandLine, this._exitCode); break; @@ -1160,7 +1167,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { // Only trigger wait on exit when the exit was *not* triggered by the // user (via the `workbench.action.terminal.kill` command). - if (this._shellLaunchConfig.waitOnExit && this._processManager.processState !== ProcessState.KILLED_BY_USER) { + if (this._shellLaunchConfig.waitOnExit && this._processManager.processState !== ProcessState.KilledByUser) { this._xtermReadyPromise.then(xterm => { if (exitCodeMessage) { xterm.writeln(exitCodeMessage); @@ -1177,7 +1184,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } else { this.dispose(); if (exitCodeMessage) { - const failedDuringLaunch = this._processManager.processState === ProcessState.KILLED_DURING_LAUNCH; + const failedDuringLaunch = this._processManager.processState === ProcessState.KilledDuringLaunch; if (failedDuringLaunch || this._configHelper.config.showExitAlert) { // Always show launch failures this._notificationService.notify({ @@ -1227,7 +1234,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public reuseTerminal(shell: IShellLaunchConfig, reset: boolean = false): void { + reuseTerminal(shell: IShellLaunchConfig, reset: boolean = false): void { // Unsubscribe any key listener we may have. this._pressAnyKeyToCloseListener?.dispose(); this._pressAnyKeyToCloseListener = undefined; @@ -1277,7 +1284,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } @debounce(1000) - public relaunch(): void { + relaunch(): void { this.reuseTerminal(this._shellLaunchConfig, true); } @@ -1325,7 +1332,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } private async _onSelectionChange(): Promise { - if (this._configurationService.getValue(TERMINAL_SETTING_ID.CopyOnSelection)) { + if (this._configurationService.getValue(TerminalSettingId.CopyOnSelection)) { if (this.hasSelection()) { await this.copySelection(); } @@ -1342,7 +1349,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { return cwd; } - public updateConfig(): void { + updateConfig(): void { const config = this._configHelper.config; this._safeSetOption('altClickMovesCursor', config.altClickMovesCursor); this._setCursorBlink(config.cursorBlinking); @@ -1417,7 +1424,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._xterm.unicode.activeVersion = this._configHelper.config.unicodeVersion; } - public updateAccessibilitySupport(): void { + updateAccessibilitySupport(): void { const isEnabled = this._accessibilityService.isScreenReaderOptimized(); if (isEnabled) { this._navigationModeAddon = new NavigationModeAddon(this._terminalA11yTreeFocusContextKey); @@ -1467,7 +1474,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public layout(dimension: dom.Dimension): void { + layout(dimension: dom.Dimension): void { if (this.disableLayout) { return; } @@ -1552,7 +1559,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public setShellType(shellType: TerminalShellType) { + setShellType(shellType: TerminalShellType) { this._shellType = shellType; } @@ -1566,7 +1573,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public setTitle(title: string | undefined, eventSource: TitleEventSource): void { + setTitle(title: string | undefined, eventSource: TitleEventSource): void { if (!title) { return; } @@ -1605,11 +1612,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public waitForTitle(): Promise { + waitForTitle(): Promise { return this._titleReadyPromise; } - public setDimensions(dimensions: ITerminalDimensionsOverride | undefined, immediate: boolean = false): void { + setDimensions(dimensions: ITerminalDimensionsOverride | undefined, immediate: boolean = false): void { if (this._dimensionsOverride && this._dimensionsOverride.forceExactSize && !dimensions && this._rows === 0 && this._cols === 0) { // this terminal never had a real size => keep the last dimensions override exact size this._cols = this._dimensionsOverride.cols; @@ -1630,7 +1637,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { this._shellLaunchConfig.env = shellLaunchConfig.env; } - public showEnvironmentInfoHover(): void { + showEnvironmentInfoHover(): void { if (this._environmentInfo) { this._environmentInfo.widget.focus(); } @@ -1689,7 +1696,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - private _getXtermTheme(theme?: IColorTheme): any { + private _getXtermTheme(theme?: IColorTheme): ITheme { if (!theme) { theme = this._themeService.getColorTheme(); } @@ -1702,11 +1709,11 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { const selectionColor = theme.getColor(TERMINAL_SELECTION_BACKGROUND_COLOR); return { - background: backgroundColor ? backgroundColor.toString() : null, - foreground: foregroundColor ? foregroundColor.toString() : null, - cursor: cursorColor ? cursorColor.toString() : null, - cursorAccent: cursorAccentColor ? cursorAccentColor.toString() : null, - selection: selectionColor ? selectionColor.toString() : null, + background: backgroundColor ? backgroundColor.toString() : undefined, + foreground: foregroundColor ? foregroundColor.toString() : undefined, + cursor: cursorColor ? cursorColor.toString() : undefined, + cursorAccent: cursorAccentColor ? cursorAccentColor.toString() : undefined, + selection: selectionColor ? selectionColor.toString() : undefined, black: theme.getColor(ansiColorIdentifiers[0])!.toString(), red: theme.getColor(ansiColorIdentifiers[1])!.toString(), green: theme.getColor(ansiColorIdentifiers[2])!.toString(), @@ -1730,28 +1737,28 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { xterm.setOption('theme', this._getXtermTheme(theme)); } - public async toggleEscapeSequenceLogging(): Promise { + async toggleEscapeSequenceLogging(): Promise { const xterm = await this._xtermReadyPromise; const isDebug = xterm.getOption('logLevel') === 'debug'; xterm.setOption('logLevel', isDebug ? 'info' : 'debug'); } - public getInitialCwd(): Promise { + getInitialCwd(): Promise { return this._processManager.getInitialCwd(); } - public getCwd(): Promise { + getCwd(): Promise { return this._processManager.getCwd(); } - public registerLinkProvider(provider: ITerminalExternalLinkProvider): IDisposable { + registerLinkProvider(provider: ITerminalExternalLinkProvider): IDisposable { if (!this._linkManager) { throw new Error('TerminalInstance.registerLinkProvider before link manager was ready'); } return this._linkManager.registerExternalLinkProvider(this, provider); } - public async rename() { + async rename() { const name = await this._quickInputService.input({ value: this.title, prompt: nls.localize('workbench.action.terminal.rename.prompt', "Enter terminal name"), @@ -1761,7 +1768,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public async changeIcon() { + async changeIcon() { const items: IQuickPickItem[] = []; for (const icon of iconRegistry.all) { items.push({ label: `$(${icon.id})`, description: `${icon.id}` }); @@ -1776,7 +1783,7 @@ export class TerminalInstance extends Disposable implements ITerminalInstance { } } - public async configure(): Promise { + async configure(): Promise { const changeIcon: IQuickPickItem = { label: nls.localize('changeIconTerminal', 'Change Icon') }; const rename: IQuickPickItem = { label: nls.localize('renameTerminal', 'Rename') }; const result = await this._quickInputService.pick([changeIcon, rename], { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts index 64771ba0971..4659efeb644 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalInstanceService.ts @@ -4,13 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IDefaultShellAndArgsRequest } from 'vs/workbench/contrib/terminal/common/terminal'; import type { Terminal as XTermTerminal } from 'xterm'; import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; -import { IProcessEnvironment } from 'vs/base/common/platform'; -import { Emitter } from 'vs/base/common/event'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { Disposable } from 'vs/base/common/lifecycle'; @@ -20,42 +17,35 @@ let Unicode11Addon: typeof XTermUnicode11Addon; let WebglAddon: typeof XTermWebglAddon; export class TerminalInstanceService extends Disposable implements ITerminalInstanceService { - public _serviceBrand: undefined; + declare _serviceBrand: undefined; - protected readonly _onRequestDefaultShellAndArgs = this._register(new Emitter()); - readonly onRequestDefaultShellAndArgs = this._onRequestDefaultShellAndArgs.event; - - public async getXtermConstructor(): Promise { + async getXtermConstructor(): Promise { if (!Terminal) { Terminal = (await import('xterm')).Terminal; } return Terminal; } - public async getXtermSearchConstructor(): Promise { + async getXtermSearchConstructor(): Promise { if (!SearchAddon) { SearchAddon = (await import('xterm-addon-search')).SearchAddon; } return SearchAddon; } - public async getXtermUnicode11Constructor(): Promise { + async getXtermUnicode11Constructor(): Promise { if (!Unicode11Addon) { Unicode11Addon = (await import('xterm-addon-unicode11')).Unicode11Addon; } return Unicode11Addon; } - public async getXtermWebglConstructor(): Promise { + async getXtermWebglConstructor(): Promise { if (!WebglAddon) { WebglAddon = (await import('xterm-addon-webgl')).WebglAddon; } return WebglAddon; } - - public async getMainProcessParentEnv(): Promise { - return {}; - } } registerSingleton(ITerminalInstanceService, TerminalInstanceService, true); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts index 0242b6591e9..2b6df368975 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalMenus.ts @@ -6,7 +6,7 @@ import { localize } from 'vs/nls'; import { MenuRegistry, MenuId } from 'vs/platform/actions/common/actions'; import { ContextKeyAndExpr, ContextKeyEqualsExpr, ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey'; -import { KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, TERMINAL_COMMAND_ID, TERMINAL_SETTING_ID, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, TerminalCommandId, TerminalSettingId, TERMINAL_VIEW_ID } from 'vs/workbench/contrib/terminal/common/terminal'; const enum ContextMenuGroup { Create = '1_create', @@ -36,7 +36,7 @@ export function setupTerminalMenus(): void { id: MenuId.MenubarTerminalMenu, item: { group: TerminalMenuBarGroup.Create, command: { - id: TERMINAL_COMMAND_ID.NEW, + id: TerminalCommandId.New, title: localize({ key: 'miNewTerminal', comment: ['&& denotes a mnemonic'] }, "&&New Terminal") }, order: 1 @@ -46,7 +46,7 @@ export function setupTerminalMenus(): void { id: MenuId.MenubarTerminalMenu, item: { group: TerminalMenuBarGroup.Create, command: { - id: TERMINAL_COMMAND_ID.SPLIT, + id: TerminalCommandId.Split, title: localize({ key: 'miSplitTerminal', comment: ['&& denotes a mnemonic'] }, "&&Split Terminal"), precondition: ContextKeyExpr.has('terminalIsOpen') }, @@ -58,7 +58,7 @@ export function setupTerminalMenus(): void { id: MenuId.MenubarTerminalMenu, item: { group: TerminalMenuBarGroup.Run, command: { - id: TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE, + id: TerminalCommandId.RunActiveFile, title: localize({ key: 'miRunActiveFile', comment: ['&& denotes a mnemonic'] }, "Run &&Active File") }, order: 3, @@ -69,7 +69,7 @@ export function setupTerminalMenus(): void { id: MenuId.MenubarTerminalMenu, item: { group: TerminalMenuBarGroup.Run, command: { - id: TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT, + id: TerminalCommandId.RunSelectedText, title: localize({ key: 'miRunSelectedText', comment: ['&& denotes a mnemonic'] }, "Run &&Selected Text") }, order: 4, @@ -85,7 +85,7 @@ export function setupTerminalMenus(): void { id: MenuId.TerminalInstanceContext, item: { group: ContextMenuGroup.Create, command: { - id: TERMINAL_COMMAND_ID.SPLIT, + id: TerminalCommandId.Split, title: localize('workbench.action.terminal.split', "Split Terminal") } } @@ -93,7 +93,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.NEW, + id: TerminalCommandId.New, title: localize('workbench.action.terminal.new.short', "New Terminal") }, group: ContextMenuGroup.Create @@ -102,7 +102,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.KILL, + id: TerminalCommandId.Kill, title: localize('workbench.action.terminal.kill.short', "Kill Terminal") }, group: ContextMenuGroup.Kill @@ -111,7 +111,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.COPY_SELECTION, + id: TerminalCommandId.CopySelection, title: localize('workbench.action.terminal.copySelection.short', "Copy") }, group: ContextMenuGroup.Edit, @@ -121,7 +121,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.PASTE, + id: TerminalCommandId.Paste, title: localize('workbench.action.terminal.paste.short', "Paste") }, group: ContextMenuGroup.Edit, @@ -131,7 +131,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.CLEAR, + id: TerminalCommandId.Clear, title: localize('workbench.action.terminal.clear', "Clear") }, group: ContextMenuGroup.Clear, @@ -140,17 +140,17 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.SHOW_TABS, + id: TerminalCommandId.ShowTabs, title: localize('workbench.action.terminal.showsTabs', "Show Tabs") }, - when: ContextKeyExpr.not(`config.${TERMINAL_SETTING_ID.TabsEnabled}`), + when: ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`), group: ContextMenuGroup.Config } }, { id: MenuId.TerminalInstanceContext, item: { command: { - id: TERMINAL_COMMAND_ID.SELECT_ALL, + id: TerminalCommandId.SelectAll, title: localize('workbench.action.terminal.selectAll', "Select All"), }, group: ContextMenuGroup.Edit, @@ -165,7 +165,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabEmptyAreaContext, item: { command: { - id: TERMINAL_COMMAND_ID.NEW_WITH_PROFILE, + id: TerminalCommandId.NewWithProfile, title: localize('workbench.action.terminal.newWithProfile.short', "New Terminal With Profile") }, group: ContextMenuGroup.Create @@ -174,7 +174,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabEmptyAreaContext, item: { command: { - id: TERMINAL_COMMAND_ID.NEW, + id: TerminalCommandId.New, title: localize('workbench.action.terminal.new.short', "New Terminal") }, group: ContextMenuGroup.Create @@ -188,7 +188,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalNewDropdownContext, item: { command: { - id: TERMINAL_COMMAND_ID.SELECT_DEFAULT_PROFILE, + id: TerminalCommandId.SelectDefaultProfile, title: { value: localize('workbench.action.terminal.selectDefaultProfile', "Select Default Profile"), original: 'Select Default Profile' } }, group: TerminalTabContextMenuGroup.Configure @@ -197,7 +197,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalNewDropdownContext, item: { command: { - id: TERMINAL_COMMAND_ID.CONFIGURE_TERMINAL_SETTINGS, + id: TerminalCommandId.ConfigureTerminalSettings, title: localize('workbench.action.terminal.openSettings', "Configure Terminal Settings") }, group: TerminalTabContextMenuGroup.Configure @@ -212,27 +212,27 @@ export function setupTerminalMenus(): void { id: MenuId.ViewTitle, item: { group: 'navigation', command: { - id: TERMINAL_COMMAND_ID.SPLIT, + id: TerminalCommandId.Split, title: localize('workbench.action.terminal.split', "Split Terminal") }, order: 2, when: ContextKeyAndExpr.create([ ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID), - ContextKeyExpr.not(`config.${TERMINAL_SETTING_ID.TabsEnabled}`) + ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`) ]) } }, { id: MenuId.ViewTitle, item: { command: { - id: TERMINAL_COMMAND_ID.SWITCH_TERMINAL, + id: TerminalCommandId.SwitchTerminal, title: { value: localize('workbench.action.terminal.switchTerminal', "Switch Terminal"), original: 'Switch Terminal' } }, group: 'navigation', order: 0, when: ContextKeyAndExpr.create([ ContextKeyEqualsExpr.create('view', TERMINAL_VIEW_ID), - ContextKeyExpr.not(`config.${TERMINAL_SETTING_ID.TabsEnabled}`) + ContextKeyExpr.not(`config.${TerminalSettingId.TabsEnabled}`) ]), } } @@ -244,7 +244,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInlineTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.CHANGE_ICON, + id: TerminalCommandId.ChangeIcon, title: localize('workbench.action.terminal.changeIcon', "Change Icon...") }, group: ContextMenuGroup.Edit, @@ -254,7 +254,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInlineTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.RENAME, + id: TerminalCommandId.Rename, title: localize('workbench.action.terminal.rename', "Rename...") } } @@ -262,7 +262,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInlineTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.RENAME_INSTANCE, + id: TerminalCommandId.RenameInstance, title: localize('workbench.action.terminal.renameInstance', "Rename...") }, group: ContextMenuGroup.Edit @@ -272,7 +272,7 @@ export function setupTerminalMenus(): void { id: MenuId.TerminalInlineTabContext, item: { group: ContextMenuGroup.Create, command: { - id: TERMINAL_COMMAND_ID.SPLIT, + id: TerminalCommandId.Split, title: localize('workbench.action.terminal.split', "Split Terminal") } } @@ -280,7 +280,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalInlineTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.KILL, + id: TerminalCommandId.Kill, title: localize('workbench.action.terminal.kill.short', "Kill Terminal") }, group: ContextMenuGroup.Kill @@ -294,7 +294,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.RENAME_INSTANCE, + id: TerminalCommandId.RenameInstance, title: localize('workbench.action.terminal.renameInstance', "Rename...") }, group: ContextMenuGroup.Edit @@ -303,7 +303,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.CHANGE_ICON_INSTANCE, + id: TerminalCommandId.ChangeIconInstance, title: localize('workbench.action.terminal.changeIcon', "Change Icon...") }, group: ContextMenuGroup.Edit @@ -312,7 +312,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.SPLIT_INSTANCE, + id: TerminalCommandId.SplitInstance, title: localize('workbench.action.terminal.splitInstance', "Split Terminal"), }, group: ContextMenuGroup.Create @@ -321,7 +321,7 @@ export function setupTerminalMenus(): void { { id: MenuId.TerminalTabContext, item: { command: { - id: TERMINAL_COMMAND_ID.KILL_INSTANCE, + id: TerminalCommandId.KillInstance, title: localize('workbench.action.terminal.killInstance', "Kill Terminal") }, group: ContextMenuGroup.Kill, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts index b0b17bbfa0c..9e807659a6e 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessExtHostProxy.ts @@ -14,38 +14,38 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal readonly shouldPersist = false; private readonly _onProcessData = this._register(new Emitter()); - public readonly onProcessData: Event = this._onProcessData.event; + readonly onProcessData: Event = this._onProcessData.event; private readonly _onProcessExit = this._register(new Emitter()); - public readonly onProcessExit: Event = this._onProcessExit.event; + readonly onProcessExit: Event = this._onProcessExit.event; private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - public get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } + get onProcessReady(): Event<{ pid: number, cwd: string }> { return this._onProcessReady.event; } private readonly _onProcessTitleChanged = this._register(new Emitter()); - public readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; + readonly onProcessTitleChanged: Event = this._onProcessTitleChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter()); - public get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } + get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter()); - public get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessResolvedShellLaunchConfig.event; } + get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessResolvedShellLaunchConfig.event; } private readonly _onStart = this._register(new Emitter()); - public readonly onStart: Event = this._onStart.event; + readonly onStart: Event = this._onStart.event; private readonly _onInput = this._register(new Emitter()); - public readonly onInput: Event = this._onInput.event; + readonly onInput: Event = this._onInput.event; private readonly _onBinary = this._register(new Emitter()); - public readonly onBinary: Event = this._onBinary.event; + readonly onBinary: Event = this._onBinary.event; private readonly _onResize: Emitter<{ cols: number, rows: number }> = this._register(new Emitter<{ cols: number, rows: number }>()); - public readonly onResize: Event<{ cols: number, rows: number }> = this._onResize.event; + readonly onResize: Event<{ cols: number, rows: number }> = this._onResize.event; private readonly _onAcknowledgeDataEvent = this._register(new Emitter()); - public readonly onAcknowledgeDataEvent: Event = this._onAcknowledgeDataEvent.event; + readonly onAcknowledgeDataEvent: Event = this._onAcknowledgeDataEvent.event; private readonly _onShutdown = this._register(new Emitter()); - public readonly onShutdown: Event = this._onShutdown.event; + readonly onShutdown: Event = this._onShutdown.event; private readonly _onRequestInitialCwd = this._register(new Emitter()); - public readonly onRequestInitialCwd: Event = this._onRequestInitialCwd.event; + readonly onRequestInitialCwd: Event = this._onRequestInitialCwd.event; private readonly _onRequestCwd = this._register(new Emitter()); - public readonly onRequestCwd: Event = this._onRequestCwd.event; + readonly onRequestCwd: Event = this._onRequestCwd.event; private readonly _onRequestLatency = this._register(new Emitter()); - public readonly onRequestLatency: Event = this._onRequestLatency.event; + readonly onRequestLatency: Event = this._onRequestLatency.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); - public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; private _pendingInitialCwdRequests: ((value: string | PromiseLike) => void)[] = []; @@ -61,89 +61,89 @@ export class TerminalProcessExtHostProxy extends Disposable implements ITerminal super(); } - public emitData(data: string): void { + emitData(data: string): void { this._onProcessData.fire(data); } - public emitTitle(title: string): void { + emitTitle(title: string): void { this._onProcessTitleChanged.fire(title); } - public emitReady(pid: number, cwd: string): void { + emitReady(pid: number, cwd: string): void { this._onProcessReady.fire({ pid, cwd }); } - public emitExit(exitCode: number | undefined): void { + emitExit(exitCode: number | undefined): void { this._onProcessExit.fire(exitCode); this.dispose(); } - public emitOverrideDimensions(dimensions: ITerminalDimensions | undefined): void { + emitOverrideDimensions(dimensions: ITerminalDimensions | undefined): void { this._onProcessOverrideDimensions.fire(dimensions); } - public emitResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void { + emitResolvedShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig): void { this._onProcessResolvedShellLaunchConfig.fire(shellLaunchConfig); } - public emitInitialCwd(initialCwd: string): void { + emitInitialCwd(initialCwd: string): void { while (this._pendingInitialCwdRequests.length > 0) { this._pendingInitialCwdRequests.pop()!(initialCwd); } } - public emitCwd(cwd: string): void { + emitCwd(cwd: string): void { while (this._pendingCwdRequests.length > 0) { this._pendingCwdRequests.pop()!(cwd); } } - public emitLatency(latency: number): void { + emitLatency(latency: number): void { while (this._pendingLatencyRequests.length > 0) { this._pendingLatencyRequests.pop()!(latency); } } - public async start(): Promise { + async start(): Promise { return this._terminalService.requestStartExtensionTerminal(this, this._cols, this._rows); } - public shutdown(immediate: boolean): void { + shutdown(immediate: boolean): void { this._onShutdown.fire(immediate); } - public input(data: string): void { + input(data: string): void { this._onInput.fire(data); } - public resize(cols: number, rows: number): void { + resize(cols: number, rows: number): void { this._onResize.fire({ cols, rows }); } - public acknowledgeDataEvent(): void { + acknowledgeDataEvent(): void { // Flow control is disabled for extension terminals } - public async processBinary(data: string): Promise { + async processBinary(data: string): Promise { // Disabled for extension terminals this._onBinary.fire(data); } - public getInitialCwd(): Promise { + getInitialCwd(): Promise { return new Promise(resolve => { this._onRequestInitialCwd.fire(); this._pendingInitialCwdRequests.push(resolve); }); } - public getCwd(): Promise { + getCwd(): Promise { return new Promise(resolve => { this._onRequestCwd.fire(); this._pendingCwdRequests.push(resolve); }); } - public getLatency(): Promise { + getLatency(): Promise { return new Promise(resolve => { this._onRequestLatency.fire(); this._pendingLatencyRequests.push(resolve); diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts index 54d46754542..1db638d69c7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProcessManager.ts @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -import { ProcessState, ITerminalProcessManager, ITerminalConfigHelper, IBeforeProcessDataEvent, ITerminalProfileResolverService, ITerminalConfiguration, TERMINAL_CONFIG_SECTION, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ProcessState, ITerminalProcessManager, ITerminalConfigHelper, IBeforeProcessDataEvent, ITerminalProfileResolverService, ITerminalConfiguration, TERMINAL_CONFIG_SECTION, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { ILogService } from 'vs/platform/log/common/log'; import { Emitter, Event } from 'vs/base/common/event'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; @@ -15,7 +15,7 @@ import { Schemas } from 'vs/base/common/network'; import { getRemoteAuthority } from 'vs/platform/remote/common/remoteHosts'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IProductService } from 'vs/platform/product/common/productService'; -import { IRemoteTerminalService, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IRemoteTerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle'; import { withNullAsUndefined } from 'vs/base/common/types'; @@ -52,14 +52,14 @@ enum ProcessType { * - Shell Process: The pseudoterminal child process (ie. the shell) */ export class TerminalProcessManager extends Disposable implements ITerminalProcessManager { - public processState: ProcessState = ProcessState.UNINITIALIZED; - public ptyProcessReady: Promise; - public shellProcessId: number | undefined; - public remoteAuthority: string | undefined; - public os: OperatingSystem | undefined; - public userHome: string | undefined; - public isDisconnected: boolean = false; - public environmentVariableInfo: IEnvironmentVariableInfo | undefined; + processState: ProcessState = ProcessState.Uninitialized; + ptyProcessReady: Promise; + shellProcessId: number | undefined; + remoteAuthority: string | undefined; + os: OperatingSystem | undefined; + userHome: string | undefined; + isDisconnected: boolean = false; + environmentVariableInfo: IEnvironmentVariableInfo | undefined; private _isDisposed: boolean = false; private _process: ITerminalChildProcess | null = null; @@ -81,32 +81,32 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce private _isScreenReaderModeEnabled: boolean = false; private readonly _onPtyDisconnect = this._register(new Emitter()); - public get onPtyDisconnect(): Event { return this._onPtyDisconnect.event; } + get onPtyDisconnect(): Event { return this._onPtyDisconnect.event; } private readonly _onPtyReconnect = this._register(new Emitter()); - public get onPtyReconnect(): Event { return this._onPtyReconnect.event; } + get onPtyReconnect(): Event { return this._onPtyReconnect.event; } private readonly _onProcessReady = this._register(new Emitter()); - public get onProcessReady(): Event { return this._onProcessReady.event; } + get onProcessReady(): Event { return this._onProcessReady.event; } private readonly _onBeforeProcessData = this._register(new Emitter()); - public get onBeforeProcessData(): Event { return this._onBeforeProcessData.event; } + get onBeforeProcessData(): Event { return this._onBeforeProcessData.event; } private readonly _onProcessData = this._register(new Emitter()); - public get onProcessData(): Event { return this._onProcessData.event; } + get onProcessData(): Event { return this._onProcessData.event; } private readonly _onProcessTitle = this._register(new Emitter()); - public get onProcessTitle(): Event { return this._onProcessTitle.event; } + get onProcessTitle(): Event { return this._onProcessTitle.event; } private readonly _onProcessShellTypeChanged = this._register(new Emitter()); - public get onProcessShellTypeChanged(): Event { return this._onProcessShellTypeChanged.event; } + get onProcessShellTypeChanged(): Event { return this._onProcessShellTypeChanged.event; } private readonly _onProcessExit = this._register(new Emitter()); - public get onProcessExit(): Event { return this._onProcessExit.event; } + get onProcessExit(): Event { return this._onProcessExit.event; } private readonly _onProcessOverrideDimensions = this._register(new Emitter()); - public get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } + get onProcessOverrideDimensions(): Event { return this._onProcessOverrideDimensions.event; } private readonly _onProcessOverrideShellLaunchConfig = this._register(new Emitter()); - public get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessOverrideShellLaunchConfig.event; } + get onProcessResolvedShellLaunchConfig(): Event { return this._onProcessOverrideShellLaunchConfig.event; } private readonly _onEnvironmentVariableInfoChange = this._register(new Emitter()); - public get onEnvironmentVariableInfoChanged(): Event { return this._onEnvironmentVariableInfoChange.event; } + get onEnvironmentVariableInfoChanged(): Event { return this._onEnvironmentVariableInfoChange.event; } - public get persistentProcessId(): number | undefined { return this._process?.id; } - public get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; } - public get hasWrittenData(): boolean { return this._hasWrittenData; } + get persistentProcessId(): number | undefined { return this._process?.id; } + get shouldPersist(): boolean { return this._process ? this._process.shouldPersist : false; } + get hasWrittenData(): boolean { return this._hasWrittenData; } private readonly _localTerminalService?: ILocalTerminalService; @@ -120,7 +120,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce @IConfigurationResolverService private readonly _configurationResolverService: IConfigurationResolverService, @IWorkbenchEnvironmentService private readonly _workbenchEnvironmentService: IWorkbenchEnvironmentService, @IProductService private readonly _productService: IProductService, - @ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService, @IRemoteAgentService private readonly _remoteAgentService: IRemoteAgentService, @IPathService private readonly _pathService: IPathService, @IEnvironmentVariableService private readonly _environmentVariableService: IEnvironmentVariableService, @@ -147,13 +146,13 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce }); } - public override dispose(immediate: boolean = false): void { + override dispose(immediate: boolean = false): void { this._isDisposed = true; if (this._process) { // If the process was still connected this dispose came from // within VS Code, not the process, so mark the process as // killed by the user. - this.processState = ProcessState.KILLED_BY_USER; + this.processState = ProcessState.KilledByUser; this._process.shutdown(immediate); this._process = null; } @@ -170,13 +169,13 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce }); } - public detachFromProcess(): void { + detachFromProcess(): void { if (this._process?.detach) { this._process.detach(); } } - public async createProcess( + async createProcess( shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number, @@ -204,7 +203,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // Create variable resolver const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(); const lastActiveWorkspace = activeWorkspaceRootUri ? withNullAsUndefined(this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined; - const variableResolver = terminalEnvironment.createVariableResolver(lastActiveWorkspace, await this._terminalProfileResolverService.getShellEnvironment(this.remoteAuthority), this._configurationResolverService); + const variableResolver = terminalEnvironment.createVariableResolver(lastActiveWorkspace, await this._terminalProfileResolverService.getEnvironment(this.remoteAuthority), this._configurationResolverService); // resolvedUserHome is needed here as remote resolvers can launch local terminals before // they're connected to the remote. @@ -239,20 +238,19 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce }); const terminalConfig = this._configurationService.getValue(TERMINAL_CONFIG_SECTION); const configuration: ICompleteTerminalConfiguration = { - 'terminal.integrated.automationShell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.AutomationShellWindows) as string, - 'terminal.integrated.automationShell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.AutomationShellMacOs) as string, - 'terminal.integrated.automationShell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.AutomationShellLinux) as string, - 'terminal.integrated.shell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellWindows) as string, - 'terminal.integrated.shell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellMacOs) as string, - 'terminal.integrated.shell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellLinux) as string, - 'terminal.integrated.shellArgs.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellArgsWindows) as string | string[], - 'terminal.integrated.shellArgs.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellArgsMacOs) as string | string[], - 'terminal.integrated.shellArgs.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.ShellArgsLinux) as string | string[], - 'terminal.integrated.env.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.EnvWindows) as ITerminalEnvironment, - 'terminal.integrated.env.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.EnvMacOs) as ITerminalEnvironment, - 'terminal.integrated.env.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.EnvLinux) as ITerminalEnvironment, - 'terminal.integrated.inheritEnv': terminalConfig.inheritEnv, - 'terminal.integrated.cwd': this._terminalProfileResolverService.getSafeConfigValueFullKey(TERMINAL_SETTING_ID.Cwd) as string, + 'terminal.integrated.automationShell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.AutomationShellWindows) as string, + 'terminal.integrated.automationShell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.AutomationShellMacOs) as string, + 'terminal.integrated.automationShell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.AutomationShellLinux) as string, + 'terminal.integrated.shell.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellWindows) as string, + 'terminal.integrated.shell.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellMacOs) as string, + 'terminal.integrated.shell.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellLinux) as string, + 'terminal.integrated.shellArgs.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellArgsWindows) as string | string[], + 'terminal.integrated.shellArgs.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellArgsMacOs) as string | string[], + 'terminal.integrated.shellArgs.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.ShellArgsLinux) as string | string[], + 'terminal.integrated.env.windows': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.EnvWindows) as ITerminalEnvironment, + 'terminal.integrated.env.osx': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.EnvMacOs) as ITerminalEnvironment, + 'terminal.integrated.env.linux': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.EnvLinux) as ITerminalEnvironment, + 'terminal.integrated.cwd': this._terminalProfileResolverService.getSafeConfigValueFullKey(TerminalSettingId.Cwd) as string, 'terminal.integrated.detectLocale': terminalConfig.detectLocale }; newProcess = await this._remoteTerminalService.createProcess(shellLaunchConfig, configuration, activeWorkspaceRootUri, cols, rows, shouldPersist, this._configHelper); @@ -290,7 +288,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce this._process = newProcess; - this.processState = ProcessState.LAUNCHING; + this.processState = ProcessState.Launching; this._dataFilter.newProcess(this._process, reset); @@ -321,8 +319,8 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } setTimeout(() => { - if (this.processState === ProcessState.LAUNCHING) { - this.processState = ProcessState.RUNNING; + if (this.processState === ProcessState.Launching) { + this.processState = ProcessState.Running; } }, LAUNCHING_DURATION); @@ -335,7 +333,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce return undefined; } - public async relaunch(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number, isScreenReaderModeEnabled: boolean, reset: boolean): Promise { + async relaunch(shellLaunchConfig: IShellLaunchConfig, cols: number, rows: number, isScreenReaderModeEnabled: boolean, reset: boolean): Promise { this.ptyProcessReady = this._createPtyProcessReadyPromise(); this._logService.trace(`Relaunching terminal instance ${this._instanceId}`); @@ -358,9 +356,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // this._configurationService.getValue(`terminal.integrated.env.${platformKey}`); const envFromConfigValue = this._terminalProfileResolverService.getSafeConfigValue('env', OS) as ITerminalEnvironment | undefined; this._configHelper.showRecommendations(shellLaunchConfig); - const baseEnv = await (this._configHelper.config.inheritEnv - ? this._terminalProfileResolverService.getShellEnvironment(this.remoteAuthority) - : this._terminalInstanceService.getMainProcessParentEnv()); + const baseEnv = await this._terminalProfileResolverService.getEnvironment(this.remoteAuthority); const env = terminalEnvironment.createTerminalEnvironment(shellLaunchConfig, envFromConfigValue, variableResolver, this._productService.version, this._configHelper.config.detectLocale, baseEnv); if (!shellLaunchConfig.strictEnv && !shellLaunchConfig.hideFromUser) { @@ -410,7 +406,6 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce const useConpty = this._configHelper.config.windowsEnableConpty && !isScreenReaderModeEnabled; const shouldPersist = this._configHelper.config.enablePersistentSessions && !shellLaunchConfig.isFeatureTerminal; - return await localTerminalService.createProcess(shellLaunchConfig, initialCwd, cols, rows, env, useConpty, shouldPersist); } @@ -453,7 +448,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } else { // For normal terminals write a message indicating what happened and relaunch // using the previous shellLaunchConfig - let message = localize('ptyHostRelaunch', "Restarting the terminal because the connection to the shell process was lost..."); + const message = localize('ptyHostRelaunch', "Restarting the terminal because the connection to the shell process was lost..."); this._onProcessData.fire({ data: formatMessageForTerminal(message), trackCommit: false }); await this.relaunch(this._shellLaunchConfig, this._dimensions.cols, this._dimensions.rows, this._isScreenReaderModeEnabled, false); } @@ -461,10 +456,10 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce })); } - public setDimensions(cols: number, rows: number): Promise; - public setDimensions(cols: number, rows: number, sync: false): Promise; - public setDimensions(cols: number, rows: number, sync: true): void; - public setDimensions(cols: number, rows: number, sync?: boolean): Promise | void { + setDimensions(cols: number, rows: number): Promise; + setDimensions(cols: number, rows: number, sync: false): Promise; + setDimensions(cols: number, rows: number, sync: true): void; + setDimensions(cols: number, rows: number, sync?: boolean): Promise | void { if (sync) { this._resize(cols, rows); return; @@ -490,7 +485,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce this._dimensions.rows = rows; } - public async write(data: string): Promise { + async write(data: string): Promise { await this.ptyProcessReady; this._dataFilter.disableSeamlessRelaunch(); this._hasWrittenData = true; @@ -505,25 +500,25 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce } } - public async processBinary(data: string): Promise { + async processBinary(data: string): Promise { await this.ptyProcessReady; this._dataFilter.disableSeamlessRelaunch(); this._hasWrittenData = true; this._process?.processBinary(data); } - public getInitialCwd(): Promise { + getInitialCwd(): Promise { return Promise.resolve(this._initialCwd ? this._initialCwd : ''); } - public getCwd(): Promise { + getCwd(): Promise { if (!this._process) { return Promise.resolve(''); } return this._process.getCwd(); } - public async getLatency(): Promise { + async getLatency(): Promise { await this.ptyProcessReady; if (!this._process) { return Promise.resolve(0); @@ -536,7 +531,7 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce return Promise.resolve(this._latency); } - public acknowledgeDataEvent(charCount: number): void { + acknowledgeDataEvent(charCount: number): void { this._ackDataBufferer.ack(charCount); } @@ -546,14 +541,14 @@ export class TerminalProcessManager extends Disposable implements ITerminalProce // If the process is marked as launching then mark the process as killed // during launch. This typically means that there is a problem with the // shell and args. - if (this.processState === ProcessState.LAUNCHING) { - this.processState = ProcessState.KILLED_DURING_LAUNCH; + if (this.processState === ProcessState.Launching) { + this.processState = ProcessState.KilledDuringLaunch; } // If TerminalInstance did not know about the process exit then it was // triggered by the process, not on VS Code's side. - if (this.processState === ProcessState.RUNNING) { - this.processState = ProcessState.KILLED_BY_PROCESS; + if (this.processState === ProcessState.Running) { + this.processState = ProcessState.KilledByProcess; } this._onProcessExit.fire(exitCode); @@ -614,7 +609,7 @@ class SeamlessRelaunchDataFilter extends Disposable { private _swapTimeout?: number; private readonly _onProcessData = this._register(new Emitter()); - public get onProcessData(): Event { return this._onProcessData.event; } + get onProcessData(): Event { return this._onProcessData.event; } constructor( @ILogService private readonly _logService: ILogService diff --git a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts index 533868ddb08..6edaaabd893 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalProfileResolverService.ts @@ -14,13 +14,13 @@ import { IConfigurationResolverService } from 'vs/workbench/services/configurati import { IHistoryService } from 'vs/workbench/services/history/common/history'; import { IProcessEnvironment, OperatingSystem } from 'vs/base/common/platform'; import { IShellLaunchConfig } from 'vs/platform/terminal/common/terminal'; -import { IShellLaunchConfigResolveOptions, ITerminalProfile, ITerminalProfileResolverService, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { IShellLaunchConfigResolveOptions, ITerminalProfile, ITerminalProfileResolverService, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import * as path from 'vs/base/common/path'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; export interface IProfileContextProvider { getDefaultSystemShell: (remoteAuthority: string | undefined, os: OperatingSystem) => Promise; - getShellEnvironment: (remoteAuthority: string | undefined) => Promise; + getEnvironment: (remoteAuthority: string | undefined) => Promise; } const generatedProfileName = 'Generated'; @@ -96,8 +96,8 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro return this._resolveProfile(await this._getUnresolvedDefaultProfile(options), options); } - getShellEnvironment(remoteAuthority: string | undefined): Promise { - return this._context.getShellEnvironment(remoteAuthority); + getEnvironment(remoteAuthority: string | undefined): Promise { + return this._context.getEnvironment(remoteAuthority); } private async _getUnresolvedDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise { @@ -185,7 +185,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro // Change Sysnative to System32 if the OS is Windows but NOT WoW64. It's // safe to assume that this was used by accident as Sysnative does not // exist and will break the terminal in non-WoW64 environments. - const env = await this._context.getShellEnvironment(options.remoteAuthority); + const env = await this._context.getEnvironment(options.remoteAuthority); const isWoW64 = !!env.hasOwnProperty('PROCESSOR_ARCHITEW6432'); const windir = env.windir; if (!isWoW64 && windir) { @@ -202,7 +202,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro } // Resolve path variables - const env = await this._context.getShellEnvironment(options.remoteAuthority); + const env = await this._context.getEnvironment(options.remoteAuthority); const activeWorkspaceRootUri = this._historyService.getLastActiveWorkspaceRoot(Schemas.file); const lastActiveWorkspace = activeWorkspaceRootUri ? withNullAsUndefined(this._workspaceContextService.getWorkspaceFolder(activeWorkspaceRootUri)) : undefined; profile.path = this._resolveVariables(profile.path, env, lastActiveWorkspace); @@ -280,7 +280,7 @@ export abstract class BaseTerminalProfileResolverService implements ITerminalPro return this.getSafeConfigValueFullKey(`terminal.integrated.${key}.${this._getOsKey(os)}`); } getSafeConfigValueFullKey(key: string): unknown | undefined { - const isWorkspaceConfigAllowed = this._configurationService.getValue(TERMINAL_SETTING_ID.AllowWorkspaceConfiguration); + const isWorkspaceConfigAllowed = this._configurationService.getValue(TerminalSettingId.AllowWorkspaceConfiguration); if (isWorkspaceConfigAllowed) { return this._configurationService.getValue(key); } else { @@ -318,11 +318,11 @@ export class BrowserTerminalProfileResolverService extends BaseTerminalProfileRe } return remoteTerminalService.getDefaultSystemShell(os); }, - getShellEnvironment: async (remoteAuthority) => { + getEnvironment: async (remoteAuthority) => { if (!remoteAuthority) { return env; } - return remoteTerminalService.getShellEnvironment(); + return remoteTerminalService.getEnvironment(); } }, configurationService, diff --git a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts index d5c6644c2e5..d5fd6d9db0a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalQuickAccess.ts @@ -9,7 +9,7 @@ import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction } from import { matchesFuzzy } from 'vs/base/common/filters'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { killTerminalIcon, renameTerminalIcon } from 'vs/workbench/contrib/terminal/browser/terminalIcons'; @@ -18,21 +18,21 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider { + protected _getPicks(filter: string): Array { const terminalPicks: Array = []; - const terminalTabs = this.terminalService.terminalTabs; - for (let tabIndex = 0; tabIndex < terminalTabs.length; tabIndex++) { - const terminalTab = terminalTabs[tabIndex]; - for (let terminalIndex = 0; terminalIndex < terminalTab.terminalInstances.length; terminalIndex++) { - const terminal = terminalTab.terminalInstances[terminalIndex]; - const label = `$(${terminal.icon?.id}) ${tabIndex + 1}.${terminalIndex + 1}: ${terminal.title}`; + const terminalGroups = this._terminalService.terminalGroups; + for (let groupIndex = 0; groupIndex < terminalGroups.length; groupIndex++) { + const terminalGroup = terminalGroups[groupIndex]; + for (let terminalIndex = 0; terminalIndex < terminalGroup.terminalInstances.length; terminalIndex++) { + const terminal = terminalGroup.terminalInstances[terminalIndex]; + const label = `$(${terminal.icon?.id}) ${groupIndex + 1}.${terminalIndex + 1}: ${terminal.title}`; const highlights = matchesFuzzy(filter, label, true); if (highlights) { @@ -52,7 +52,7 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider { switch (buttonIndex) { case 0: - this.commandService.executeCommand(TERMINAL_COMMAND_ID.RENAME, terminal); + this._commandService.executeCommand(TerminalCommandId.Rename, terminal); return TriggerAction.NO_ACTION; case 1: terminal.dispose(true); @@ -62,8 +62,8 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider { - this.terminalService.setActiveInstance(terminal); - this.terminalService.showPanel(!event.inBackground); + this._terminalService.setActiveInstance(terminal); + this._terminalService.showPanel(!event.inBackground); } }); } @@ -78,13 +78,13 @@ export class TerminalQuickAccessProvider extends PickerQuickAccessProvider this.commandService.executeCommand(TERMINAL_COMMAND_ID.NEW) + accept: () => this._commandService.executeCommand(TerminalCommandId.New) }); const createWithProfileLabel = localize("workbench.action.terminal.newWithProfilePlus", "Create New Terminal With Profile"); terminalPicks.push({ label: `$(plus) ${createWithProfileLabel}`, ariaLabel: createWithProfileLabel, - accept: () => this.commandService.executeCommand(TERMINAL_COMMAND_ID.NEW_WITH_PROFILE) + accept: () => this._commandService.executeCommand(TerminalCommandId.NewWithProfile) }); return terminalPicks; diff --git a/src/vs/workbench/contrib/terminal/browser/terminalService.ts b/src/vs/workbench/contrib/terminal/browser/terminalService.ts index aed0db0d030..412cc81f407 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalService.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalService.ts @@ -9,6 +9,8 @@ import { Emitter, Event } from 'vs/base/common/event'; import { IDisposable } from 'vs/base/common/lifecycle'; import { basename } from 'vs/base/common/path'; import { isMacintosh, isWeb, isWindows, OperatingSystem } from 'vs/base/common/platform'; +import { URI } from 'vs/base/common/uri'; +import { DataTransfers } from 'vs/base/browser/dnd'; import { FindReplaceState } from 'vs/editor/contrib/find/findState'; import * as nls from 'vs/nls'; import { ConfigurationTarget, IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -20,13 +22,12 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { ILocalTerminalService, IShellLaunchConfig, ITerminalLaunchError, ITerminalsLayoutInfo, ITerminalsLayoutInfoById, TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal'; import { ThemeIcon } from 'vs/platform/theme/common/themeService'; import { IViewDescriptorService, IViewsService, ViewContainerLocation } from 'vs/workbench/common/views'; -import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalTab, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; +import { IRemoteTerminalService, ITerminalExternalLinkProvider, ITerminalInstance, ITerminalService, ITerminalGroup, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminalInstance'; -import { TerminalTab } from 'vs/workbench/contrib/terminal/browser/terminalTab'; +import { TerminalGroup } from 'vs/workbench/contrib/terminal/browser/terminalGroup'; import { TerminalViewPane } from 'vs/workbench/contrib/terminal/browser/terminalView'; -import { IAvailableProfilesRequest, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalNativeWindowsDelegate, ITerminalProcessExtHostProxy, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, LinuxDistro, TERMINAL_VIEW_ID, ITerminalProfileObject, ITerminalTypeContribution, KEYBINDING_CONTEXT_TERMINAL_COUNT, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; -import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; +import { IAvailableProfilesRequest, IRemoteTerminalAttachTarget, ITerminalProfile, IStartExtensionTerminalRequest, ITerminalConfigHelper, ITerminalProcessExtHostProxy, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, TERMINAL_VIEW_ID, ITerminalProfileObject, ITerminalTypeContribution, KEYBINDING_CONTEXT_TERMINAL_COUNT, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions'; import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService'; @@ -37,11 +38,11 @@ import { equals } from 'vs/base/common/objects'; import { Codicon, iconRegistry } from 'vs/base/common/codicons'; import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints'; import { ICommandService } from 'vs/platform/commands/common/commands'; -import { URI } from 'vs/base/common/uri'; import { ILabelService } from 'vs/platform/label/common/label'; import { Schemas } from 'vs/base/common/network'; import { VirtualWorkspaceContext } from 'vs/workbench/browser/contextkeys'; import { formatMessageForTerminal } from 'vs/workbench/contrib/terminal/common/terminalStrings'; +import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment'; interface IExtHostReadyEntry { promise: Promise; @@ -49,83 +50,82 @@ interface IExtHostReadyEntry { } export class TerminalService implements ITerminalService { - public _serviceBrand: undefined; + declare _serviceBrand: undefined; private _isShuttingDown: boolean; private _terminalFocusContextKey: IContextKey; private _terminalCountContextKey: IContextKey; private _terminalShellTypeContextKey: IContextKey; private _terminalAltBufferActiveContextKey: IContextKey; - private _terminalTabs: ITerminalTab[] = []; + private _terminalGroups: ITerminalGroup[] = []; private _backgroundedTerminalInstances: ITerminalInstance[] = []; private get _terminalInstances(): ITerminalInstance[] { - return this._terminalTabs.reduce((p, c) => p.concat(c.terminalInstances), []); + return this._terminalGroups.reduce((p, c) => p.concat(c.terminalInstances), []); } private _findState: FindReplaceState; private _extHostsReady: { [authority: string]: IExtHostReadyEntry | undefined } = {}; - private _activeTabIndex: number; + private _activeGroupIndex: number; private _linkProviders: Set = new Set(); private _linkProviderDisposables: Map = new Map(); private _processSupportContextKey: IContextKey; - public get activeTabIndex(): number { return this._activeTabIndex; } + public get activeTabIndex(): number { return this._activeGroupIndex; } public get terminalInstances(): ITerminalInstance[] { return this._terminalInstances; } - public get terminalTabs(): ITerminalTab[] { return this._terminalTabs; } + public get terminalGroups(): ITerminalGroup[] { return this._terminalGroups; } public get isProcessSupportRegistered(): boolean { return !!this._processSupportContextKey.get(); } private _configHelper: TerminalConfigHelper; private _terminalContainer: HTMLElement | undefined; - private _nativeWindowsDelegate: ITerminalNativeWindowsDelegate | undefined; private _remoteTerminalsInitPromise: Promise | undefined; private _localTerminalsInitPromise: Promise | undefined; private _connectionState: TerminalConnectionState; - public get connectionState(): TerminalConnectionState { return this._connectionState; } + get connectionState(): TerminalConnectionState { return this._connectionState; } private readonly _localTerminalService?: ILocalTerminalService; private _availableProfiles: ITerminalProfile[] | undefined; - public get availableProfiles(): ITerminalProfile[] { + get availableProfiles(): ITerminalProfile[] { this._refreshAvailableProfiles(); return this._availableProfiles || []; } - public get configHelper(): ITerminalConfigHelper { return this._configHelper; } + get configHelper(): ITerminalConfigHelper { return this._configHelper; } private readonly _onActiveTabChanged = new Emitter(); - public get onActiveTabChanged(): Event { return this._onActiveTabChanged.event; } + get onActiveTabChanged(): Event { return this._onActiveTabChanged.event; } private readonly _onInstanceCreated = new Emitter(); - public get onInstanceCreated(): Event { return this._onInstanceCreated.event; } + get onInstanceCreated(): Event { return this._onInstanceCreated.event; } private readonly _onInstanceDisposed = new Emitter(); - public get onInstanceDisposed(): Event { return this._onInstanceDisposed.event; } + get onInstanceDisposed(): Event { return this._onInstanceDisposed.event; } private readonly _onInstanceProcessIdReady = new Emitter(); - public get onInstanceProcessIdReady(): Event { return this._onInstanceProcessIdReady.event; } + get onInstanceProcessIdReady(): Event { return this._onInstanceProcessIdReady.event; } private readonly _onInstanceLinksReady = new Emitter(); - public get onInstanceLinksReady(): Event { return this._onInstanceLinksReady.event; } + get onInstanceLinksReady(): Event { return this._onInstanceLinksReady.event; } private readonly _onInstanceRequestStartExtensionTerminal = new Emitter(); - public get onInstanceRequestStartExtensionTerminal(): Event { return this._onInstanceRequestStartExtensionTerminal.event; } + get onInstanceRequestStartExtensionTerminal(): Event { return this._onInstanceRequestStartExtensionTerminal.event; } private readonly _onInstanceDimensionsChanged = new Emitter(); - public get onInstanceDimensionsChanged(): Event { return this._onInstanceDimensionsChanged.event; } + get onInstanceDimensionsChanged(): Event { return this._onInstanceDimensionsChanged.event; } private readonly _onInstanceMaximumDimensionsChanged = new Emitter(); - public get onInstanceMaximumDimensionsChanged(): Event { return this._onInstanceMaximumDimensionsChanged.event; } + get onInstanceMaximumDimensionsChanged(): Event { return this._onInstanceMaximumDimensionsChanged.event; } private readonly _onInstancesChanged = new Emitter(); - public get onInstancesChanged(): Event { return this._onInstancesChanged.event; } + get onInstancesChanged(): Event { return this._onInstancesChanged.event; } private readonly _onInstanceTitleChanged = new Emitter(); - public get onInstanceTitleChanged(): Event { return this._onInstanceTitleChanged.event; } + get onInstanceTitleChanged(): Event { return this._onInstanceTitleChanged.event; } private readonly _onActiveInstanceChanged = new Emitter(); - public get onActiveInstanceChanged(): Event { return this._onActiveInstanceChanged.event; } + get onActiveInstanceChanged(): Event { return this._onActiveInstanceChanged.event; } private readonly _onInstancePrimaryStatusChanged = new Emitter(); public get onInstancePrimaryStatusChanged(): Event { return this._onInstancePrimaryStatusChanged.event; } - private readonly _onTabDisposed = new Emitter(); - public get onTabDisposed(): Event { return this._onTabDisposed.event; } + private readonly _onTabDisposed = new Emitter(); + public get onTabDisposed(): Event { return this._onTabDisposed.event; } private readonly _onRequestAvailableProfiles = new Emitter(); - public get onRequestAvailableProfiles(): Event { return this._onRequestAvailableProfiles.event; } + get onRequestAvailableProfiles(): Event { return this._onRequestAvailableProfiles.event; } private readonly _onDidRegisterProcessSupport = new Emitter(); - public get onDidRegisterProcessSupport(): Event { return this._onDidRegisterProcessSupport.event; } + get onDidRegisterProcessSupport(): Event { return this._onDidRegisterProcessSupport.event; } private readonly _onDidChangeConnectionState = new Emitter(); - public get onDidChangeConnectionState(): Event { return this._onDidChangeConnectionState.event; } + get onDidChangeConnectionState(): Event { return this._onDidChangeConnectionState.event; } private readonly _onDidChangeAvailableProfiles = new Emitter(); - public get onDidChangeAvailableProfiles(): Event { return this._onDidChangeAvailableProfiles.event; } + get onDidChangeAvailableProfiles(): Event { return this._onDidChangeAvailableProfiles.event; } private readonly _onPanelMovedToSide = new Emitter(); - public get onPanelMovedToSide(): Event { return this._onPanelMovedToSide.event; } + get onPanelMovedToSide(): Event { return this._onPanelMovedToSide.event; } constructor( @IContextKeyService private _contextKeyService: IContextKeyService, @@ -149,7 +149,7 @@ export class TerminalService implements ITerminalService { ) { this._localTerminalService = localTerminalService; - this._activeTabIndex = 0; + this._activeGroupIndex = 0; this._isShuttingDown = false; this._findState = new FindReplaceState(); lifecycleService.onBeforeShutdown(async e => e.veto(this._onBeforeShutdown(e.reason), 'veto.terminal')); @@ -159,7 +159,7 @@ export class TerminalService implements ITerminalService { this._terminalShellTypeContextKey = KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE.bindTo(this._contextKeyService); this._terminalAltBufferActiveContextKey = KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE.bindTo(this._contextKeyService); this._configHelper = this._instantiationService.createInstance(TerminalConfigHelper); - this.onTabDisposed(tab => this._removeTab(tab)); + this.onTabDisposed(group => this._removeTab(group)); this.onActiveTabChanged(() => { const instance = this.getActiveInstance(); this._onActiveInstanceChanged.fire(instance ? instance : undefined); @@ -174,13 +174,13 @@ export class TerminalService implements ITerminalService { this._processSupportContextKey.set(!isWeb || this._remoteAgentService.getConnection() !== null); this._configurationService.onDidChangeConfiguration(async e => { - if (e.affectsConfiguration(TERMINAL_SETTING_ID.ProfilesWindows) || - e.affectsConfiguration(TERMINAL_SETTING_ID.ProfilesMacOs) || - e.affectsConfiguration(TERMINAL_SETTING_ID.ProfilesLinux) || - e.affectsConfiguration(TERMINAL_SETTING_ID.DefaultProfileWindows) || - e.affectsConfiguration(TERMINAL_SETTING_ID.DefaultProfileMacOs) || - e.affectsConfiguration(TERMINAL_SETTING_ID.DefaultProfileLinux) || - e.affectsConfiguration(TERMINAL_SETTING_ID.UseWslProfiles)) { + if (e.affectsConfiguration(TerminalSettingId.ProfilesWindows) || + e.affectsConfiguration(TerminalSettingId.ProfilesMacOs) || + e.affectsConfiguration(TerminalSettingId.ProfilesLinux) || + e.affectsConfiguration(TerminalSettingId.DefaultProfileWindows) || + e.affectsConfiguration(TerminalSettingId.DefaultProfileMacOs) || + e.affectsConfiguration(TerminalSettingId.DefaultProfileLinux) || + e.affectsConfiguration(TerminalSettingId.UseWslProfiles)) { this._refreshAvailableProfiles(); } }); @@ -237,7 +237,7 @@ export class TerminalService implements ITerminalService { this._telemetryService.publicLog('terminalReconnection', data); // now that terminals have been restored, // attach listeners to update remote when terminals are changed - this.attachProcessLayoutListeners(true); + this._attachProcessLayoutListeners(true); } private async _reconnectToLocalTerminals(): Promise { @@ -251,49 +251,49 @@ export class TerminalService implements ITerminalService { } // now that terminals have been restored, // attach listeners to update local state when terminals are changed - this.attachProcessLayoutListeners(false); + this._attachProcessLayoutListeners(false); } private _recreateTerminalTabs(layoutInfo?: ITerminalsLayoutInfo): number { let reconnectCounter = 0; - let activeTab: ITerminalTab | undefined; + let activeTab: ITerminalGroup | undefined; if (layoutInfo) { - layoutInfo.tabs.forEach(tabLayout => { - const terminalLayouts = tabLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan); + layoutInfo.tabs.forEach(groupLayout => { + const terminalLayouts = groupLayout.terminals.filter(t => t.terminal && t.terminal.isOrphan); if (terminalLayouts.length) { reconnectCounter += terminalLayouts.length; let terminalInstance: ITerminalInstance | undefined; - let tab: ITerminalTab | undefined; + let group: ITerminalGroup | undefined; terminalLayouts.forEach((terminalLayout) => { if (!terminalInstance) { - // create tab and terminal + // create group and terminal terminalInstance = this.createTerminal({ attachPersistentProcess: terminalLayout.terminal! }); - tab = this.getTabForInstance(terminalInstance); - if (tabLayout.isActive) { - activeTab = tab; + group = this.getGroupForInstance(terminalInstance); + if (groupLayout.isActive) { + activeTab = group; } } else { - // add split terminals to this tab + // add split terminals to this group this.splitInstance(terminalInstance, { attachPersistentProcess: terminalLayout.terminal! }); } }); const activeInstance = this.terminalInstances.find(t => { - return t.shellLaunchConfig.attachPersistentProcess?.id === tabLayout.activePersistentProcessId; + return t.shellLaunchConfig.attachPersistentProcess?.id === groupLayout.activePersistentProcessId; }); if (activeInstance) { this.setActiveInstance(activeInstance); } - tab?.resizePanes(tabLayout.terminals.map(terminal => terminal.relativeSize)); + group?.resizePanes(groupLayout.terminals.map(terminal => terminal.relativeSize)); } }); if (layoutInfo.tabs.length) { - this.setActiveTabByIndex(activeTab ? this.terminalTabs.indexOf(activeTab) : 0); + this.setActiveTabByIndex(activeTab ? this.terminalGroups.indexOf(activeTab) : 0); } } return reconnectCounter; } - private attachProcessLayoutListeners(isRemote: boolean): void { + private _attachProcessLayoutListeners(isRemote: boolean): void { this.onActiveTabChanged(() => isRemote ? this._updateRemoteState() : this._updateLocalState()); this.onActiveInstanceChanged(() => isRemote ? this._updateRemoteState() : this._updateLocalState()); this.onInstancesChanged(() => isRemote ? this._updateRemoteState() : this._updateLocalState()); @@ -302,14 +302,6 @@ export class TerminalService implements ITerminalService { this.onInstanceProcessIdReady(() => isRemote ? this._updateRemoteState() : this._updateLocalState()); } - public setNativeWindowsDelegate(delegate: ITerminalNativeWindowsDelegate): void { - this._nativeWindowsDelegate = delegate; - } - - public setLinuxDistro(linuxDistro: LinuxDistro): void { - this._configHelper.setLinuxDistro(linuxDistro); - } - private _handleInstanceContextKeys(): void { const terminalIsOpenContext = KEYBINDING_CONTEXT_TERMINAL_IS_OPEN.bindTo(this._contextKeyService); const updateTerminalContextKeys = () => { @@ -318,19 +310,19 @@ export class TerminalService implements ITerminalService { this.onInstancesChanged(() => updateTerminalContextKeys()); } - public getActiveOrCreateInstance(): ITerminalInstance { + getActiveOrCreateInstance(): ITerminalInstance { const activeInstance = this.getActiveInstance(); return activeInstance ? activeInstance : this.createTerminal(undefined); } - public requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise { + requestStartExtensionTerminal(proxy: ITerminalProcessExtHostProxy, cols: number, rows: number): Promise { // The initial request came from the extension host, no need to wait for it return new Promise(callback => { this._onInstanceRequestStartExtensionTerminal.fire({ proxy, cols, rows, callback }); }); } - public async extHostReady(remoteAuthority: string): Promise { + async extHostReady(remoteAuthority: string): Promise { this._createExtHostReadyEntry(remoteAuthority); this._extHostsReady[remoteAuthority]!.resolve(); } @@ -409,12 +401,12 @@ export class TerminalService implements ITerminalService { } public getTabLabels(): string[] { - return this._terminalTabs.filter(tab => tab.terminalInstances.length > 0).map((tab, index) => { - return `${index + 1}: ${tab.title ? tab.title : ''}`; + return this._terminalGroups.filter(group => group.terminalInstances.length > 0).map((group, index) => { + return `${index + 1}: ${group.title ? group.title : ''}`; }); } - public getFindState(): FindReplaceState { + getFindState(): FindReplaceState { return this._findState; } @@ -422,7 +414,7 @@ export class TerminalService implements ITerminalService { private _updateRemoteState(): void { if (!!this._environmentService.remoteAuthority) { const state: ITerminalsLayoutInfoById = { - tabs: this.terminalTabs.map(t => t.getLayoutInfo(t === this.getActiveTab())) + tabs: this.terminalGroups.map(t => t.getLayoutInfo(t === this.getActiveGroup())) }; this._remoteTerminalService.setTerminalLayoutInfo(state); } @@ -431,38 +423,38 @@ export class TerminalService implements ITerminalService { @debounce(500) private _updateLocalState(): void { const state: ITerminalsLayoutInfoById = { - tabs: this.terminalTabs.map(t => t.getLayoutInfo(t === this.getActiveTab())) + tabs: this.terminalGroups.map(t => t.getLayoutInfo(t === this.getActiveGroup())) }; this._localTerminalService!.setTerminalLayoutInfo(state); } - private _removeTab(tab: ITerminalTab): void { - // Get the index of the tab and remove it from the list - const index = this._terminalTabs.indexOf(tab); - const activeTab = this.getActiveTab(); - const activeTabIndex = activeTab ? this._terminalTabs.indexOf(activeTab) : -1; - const wasActiveTab = tab === activeTab; + private _removeTab(group: ITerminalGroup): void { + // Get the index of the group and remove it from the list + const index = this._terminalGroups.indexOf(group); + const activeTab = this.getActiveGroup(); + const activeTabIndex = activeTab ? this._terminalGroups.indexOf(activeTab) : -1; + const wasActiveTab = group === activeTab; if (index !== -1) { - this._terminalTabs.splice(index, 1); + this._terminalGroups.splice(index, 1); } - // Adjust focus if the tab was active - if (wasActiveTab && this._terminalTabs.length > 0) { - const newIndex = index < this._terminalTabs.length ? index : this._terminalTabs.length - 1; + // Adjust focus if the group was active + if (wasActiveTab && this._terminalGroups.length > 0) { + const newIndex = index < this._terminalGroups.length ? index : this._terminalGroups.length - 1; this.setActiveTabByIndex(newIndex); const activeInstance = this.getActiveInstance(); if (activeInstance) { activeInstance.focus(true); } - } else if (activeTabIndex >= this._terminalTabs.length) { - const newIndex = this._terminalTabs.length - 1; + } else if (activeTabIndex >= this._terminalGroups.length) { + const newIndex = this._terminalGroups.length - 1; this.setActiveTabByIndex(newIndex); } // Hide the panel if there are no more instances, provided that VS Code is not shutting // down. When shutting down the panel is locked in place so that it is restored upon next // launch. - if (this._terminalTabs.length === 0 && !this._isShuttingDown) { + if (this._terminalGroups.length === 0 && !this._isShuttingDown) { this.hidePanel(); this._onActiveInstanceChanged.fire(undefined); } @@ -474,34 +466,34 @@ export class TerminalService implements ITerminalService { } } - public refreshActiveTab(): void { + refreshActiveTab(): void { // Fire active instances changed this._onActiveTabChanged.fire(); } - public getActiveTab(): ITerminalTab | null { - if (this._activeTabIndex < 0 || this._activeTabIndex >= this._terminalTabs.length) { + public getActiveGroup(): ITerminalGroup | null { + if (this._activeGroupIndex < 0 || this._activeGroupIndex >= this._terminalGroups.length) { return null; } - return this._terminalTabs[this._activeTabIndex]; + return this._terminalGroups[this._activeGroupIndex]; } public getActiveInstance(): ITerminalInstance | null { - const tab = this.getActiveTab(); - if (!tab) { + const group = this.getActiveGroup(); + if (!group) { return null; } - return tab.activeInstance; + return group.activeInstance; } - public doWithActiveInstance(callback: (terminal: ITerminalInstance) => T): T | void { + doWithActiveInstance(callback: (terminal: ITerminalInstance) => T): T | void { const instance = this.getActiveInstance(); if (instance) { return callback(instance); } } - public getInstanceFromId(terminalId: number): ITerminalInstance | undefined { + getInstanceFromId(terminalId: number): ITerminalInstance | undefined { let bgIndex = -1; this._backgroundedTerminalInstances.forEach((terminalInstance, i) => { if (terminalInstance.instanceId === terminalId) { @@ -518,58 +510,58 @@ export class TerminalService implements ITerminalService { } } - public getInstanceFromIndex(terminalIndex: number): ITerminalInstance { + getInstanceFromIndex(terminalIndex: number): ITerminalInstance { return this.terminalInstances[terminalIndex]; } - public setActiveInstance(terminalInstance: ITerminalInstance): void { + setActiveInstance(terminalInstance: ITerminalInstance): void { // If this was a hideFromUser terminal created by the API this was triggered by show, - // in which case we need to create the terminal tab + // in which case we need to create the terminal group if (terminalInstance.shellLaunchConfig.hideFromUser) { this._showBackgroundTerminal(terminalInstance); } this.setActiveInstanceByIndex(this._getIndexFromId(terminalInstance.instanceId)); } - public setActiveTabByIndex(tabIndex: number): void { - if (tabIndex >= this._terminalTabs.length) { + setActiveTabByIndex(groupIndex: number): void { + if (groupIndex >= this._terminalGroups.length) { return; } - const didTabChange = this._activeTabIndex !== tabIndex; - this._activeTabIndex = tabIndex; + const didTabChange = this._activeGroupIndex !== groupIndex; + this._activeGroupIndex = groupIndex; - this._terminalTabs.forEach((t, i) => t.setVisible(i === this._activeTabIndex)); + this._terminalGroups.forEach((g, i) => g.setVisible(i === this._activeGroupIndex)); if (didTabChange) { this._onActiveTabChanged.fire(); } } - public isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean { + isAttachedToTerminal(remoteTerm: IRemoteTerminalAttachTarget): boolean { return this.terminalInstances.some(term => term.processId === remoteTerm.pid); } - public async initializeTerminals(): Promise { + async initializeTerminals(): Promise { if (this._remoteTerminalsInitPromise) { await this._remoteTerminalsInitPromise; } else if (this._localTerminalsInitPromise) { await this._localTerminalsInitPromise; } - if (this.terminalTabs.length === 0 && this.isProcessSupportRegistered) { + if (this.terminalGroups.length === 0 && this.isProcessSupportRegistered) { this.createTerminal(); } } - private _getInstanceFromGlobalInstanceIndex(index: number): { tab: ITerminalTab, tabIndex: number, instance: ITerminalInstance, localInstanceIndex: number } | null { + private _getInstanceFromGlobalInstanceIndex(index: number): { group: ITerminalGroup, groupIndex: number, instance: ITerminalInstance, localInstanceIndex: number } | null { let currentTabIndex = 0; - while (index >= 0 && currentTabIndex < this._terminalTabs.length) { - const tab = this._terminalTabs[currentTabIndex]; - const count = tab.terminalInstances.length; + while (index >= 0 && currentTabIndex < this._terminalGroups.length) { + const group = this._terminalGroups[currentTabIndex]; + const count = group.terminalInstances.length; if (index < count) { return { - tab, - tabIndex: currentTabIndex, - instance: tab.terminalInstances[index], + group, + groupIndex: currentTabIndex, + instance: group.terminalInstances[index], localInstanceIndex: index }; } @@ -579,16 +571,16 @@ export class TerminalService implements ITerminalService { return null; } - public setActiveInstanceByIndex(terminalIndex: number): void { + setActiveInstanceByIndex(terminalIndex: number): void { const query = this._getInstanceFromGlobalInstanceIndex(terminalIndex); if (!query) { return; } - query.tab.setActiveInstanceByIndex(query.localInstanceIndex); - const didTabChange = this._activeTabIndex !== query.tabIndex; - this._activeTabIndex = query.tabIndex; - this._terminalTabs.forEach((t, i) => t.setVisible(i === query.tabIndex)); + query.group.setActiveInstanceByIndex(query.localInstanceIndex); + const didTabChange = this._activeGroupIndex !== query.groupIndex; + this._activeGroupIndex = query.groupIndex; + this._terminalGroups.forEach((g, i) => g.setVisible(i === query.groupIndex)); // Only fire the event if there was a change if (didTabChange) { @@ -596,42 +588,42 @@ export class TerminalService implements ITerminalService { } } - public setActiveTabToNext(): void { - if (this._terminalTabs.length <= 1) { + setActiveTabToNext(): void { + if (this._terminalGroups.length <= 1) { return; } - let newIndex = this._activeTabIndex + 1; - if (newIndex >= this._terminalTabs.length) { + let newIndex = this._activeGroupIndex + 1; + if (newIndex >= this._terminalGroups.length) { newIndex = 0; } this.setActiveTabByIndex(newIndex); } - public setActiveTabToPrevious(): void { - if (this._terminalTabs.length <= 1) { + setActiveTabToPrevious(): void { + if (this._terminalGroups.length <= 1) { return; } - let newIndex = this._activeTabIndex - 1; + let newIndex = this._activeGroupIndex - 1; if (newIndex < 0) { - newIndex = this._terminalTabs.length - 1; + newIndex = this._terminalGroups.length - 1; } this.setActiveTabByIndex(newIndex); } - public splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance | null; - public splitInstance(instanceToSplit: ITerminalInstance, profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance | null - public splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile = {}, cwd?: string | URI): ITerminalInstance | null { - const tab = this.getTabForInstance(instanceToSplit); - if (!tab) { + splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance | null; + splitInstance(instanceToSplit: ITerminalInstance, profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance | null + splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile = {}, cwd?: string | URI): ITerminalInstance | null { + const group = this.getGroupForInstance(instanceToSplit); + if (!group) { return null; } const shellLaunchConfig = this._convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile, cwd); - const instance = tab.split(shellLaunchConfig); + const instance = group.split(shellLaunchConfig); this._initInstanceListeners(instance); this._onInstancesChanged.fire(); - this._terminalTabs.forEach((t, i) => t.setVisible(i === this._activeTabIndex)); + this._terminalGroups.forEach((g, i) => g.setVisible(i === this._activeGroupIndex)); return instance; } @@ -649,9 +641,38 @@ export class TerminalService implements ITerminalService { })); instance.addDisposable(instance.onMaximumDimensionsChanged(() => this._onInstanceMaximumDimensionsChanged.fire(instance))); instance.addDisposable(instance.onFocus(this._onActiveInstanceChanged.fire, this._onActiveInstanceChanged)); + instance.addDisposable(instance.onDropped(async (e) => { + const dragEvent = e.dragEvent; + if (!dragEvent.dataTransfer) { + return; + } + + // Check if files were dragged from the tree explorer + let path: string | undefined; + const resources = dragEvent.dataTransfer.getData(DataTransfers.RESOURCES); + if (resources) { + path = URI.parse(JSON.parse(resources)[0]).fsPath; + } else if (dragEvent.dataTransfer.files?.[0].path /* Electron only */) { + // Check if the file was dragged from the filesystem + path = URI.file(dragEvent.dataTransfer.files[0].path).fsPath; + } + + if (!path) { + return; + } + + const instance = e.instance; + if (!instance.shellLaunchConfig.executable) { + return; + } + const preparedPath = await this.preparePathForTerminalAsync(path, instance.shellLaunchConfig.executable, instance.title, instance.shellType, instance.isRemote); + + instance.sendText(preparedPath, false); + instance.focus(); + })); } - public registerProcessSupport(isSupported: boolean): void { + registerProcessSupport(isSupported: boolean): void { if (!isSupported) { return; } @@ -659,7 +680,7 @@ export class TerminalService implements ITerminalService { this._onDidRegisterProcessSupport.fire(); } - public registerLinkProvider(linkProvider: ITerminalExternalLinkProvider): IDisposable { + registerLinkProvider(linkProvider: ITerminalExternalLinkProvider): IDisposable { const disposables: IDisposable[] = []; this._linkProviders.add(linkProvider); for (const instance of this.terminalInstances) { @@ -687,11 +708,11 @@ export class TerminalService implements ITerminalService { } } - public getTabForInstance(instance: ITerminalInstance): ITerminalTab | undefined { - return this._terminalTabs.find(tab => tab.terminalInstances.indexOf(instance) !== -1); + getGroupForInstance(instance: ITerminalInstance): ITerminalGroup | undefined { + return this._terminalGroups.find(group => group.terminalInstances.indexOf(instance) !== -1); } - public async showPanel(focus?: boolean): Promise { + async showPanel(focus?: boolean): Promise { const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID) as TerminalViewPane; if (!pane) { await this._viewsService.openView(TERMINAL_VIEW_ID, focus); @@ -707,14 +728,14 @@ export class TerminalService implements ITerminalService { } } - public async focusTabs(): Promise { + async focusTabs(): Promise { await this.showPanel(true); const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); pane?.terminalTabbedView?.focusTabs(); } - public showTabs() { - this._configurationService.updateValue(TERMINAL_SETTING_ID.TabsEnabled, true); + showTabs() { + this._configurationService.updateValue(TerminalSettingId.TabsEnabled, true); } private _getIndexFromId(terminalId: number): number { @@ -744,7 +765,7 @@ export class TerminalService implements ITerminalService { return !res.confirmed; } - public preparePathForTerminalAsync(originalPath: string, executable: string, title: string, shellType: TerminalShellType): Promise { + preparePathForTerminalAsync(originalPath: string, executable: string, title: string, shellType: TerminalShellType, isRemote: boolean): Promise { return new Promise(c => { if (!executable) { c(originalPath); @@ -776,28 +797,22 @@ export class TerminalService implements ITerminalService { if (shellType !== undefined) { if (shellType === WindowsShellType.GitBash) { c(originalPath.replace(/\\/g, '/')); - return; } else if (shellType === WindowsShellType.Wsl) { - if (this._nativeWindowsDelegate && this._nativeWindowsDelegate.getWindowsBuildNumber() >= 17063) { - c(this._nativeWindowsDelegate.getWslPath(originalPath)); - } else { - c(originalPath.replace(/\\/g, '/')); - } - return; + const offProcService = isRemote ? this._remoteTerminalService : this._localTerminalService; + c(offProcService?.getWslPath(originalPath) || originalPath); } - if (hasSpace) { + else if (hasSpace) { c('"' + originalPath + '"'); } else { c(originalPath); } } else { const lowerExecutable = executable.toLowerCase(); - if (this._nativeWindowsDelegate && this._nativeWindowsDelegate.getWindowsBuildNumber() >= 17063 && - (lowerExecutable.indexOf('wsl') !== -1 || (lowerExecutable.indexOf('bash.exe') !== -1 && lowerExecutable.toLowerCase().indexOf('git') === -1))) { - c(this._nativeWindowsDelegate.getWslPath(originalPath)); - return; + if (lowerExecutable.indexOf('wsl') !== -1 || (lowerExecutable.indexOf('bash.exe') !== -1 && lowerExecutable.toLowerCase().indexOf('git') === -1)) { + const offProcService = isRemote ? this._remoteTerminalService : this._localTerminalService; + c(offProcService?.getWslPath(originalPath) || originalPath); } else if (hasSpace) { c('"' + originalPath + '"'); } else { @@ -820,7 +835,7 @@ export class TerminalService implements ITerminalService { return isWindows ? 'windows' : (isMacintosh ? 'osx' : 'linux'); } - public async showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise { + async showProfileQuickPick(type: 'setDefault' | 'createInstance', cwd?: string | URI): Promise { let keyMods: IKeyMods | undefined; const profiles = await this._detectProfiles(false); const platformKey = await this._getPlatformKey(); @@ -952,7 +967,7 @@ export class TerminalService implements ITerminalService { return { label, description: profile.path, profile, buttons }; } - public createInstance(container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { + createInstance(container: HTMLElement | undefined, shellLaunchConfig: IShellLaunchConfig): ITerminalInstance { const instance = this._instantiationService.createInstance(TerminalInstance, this._terminalFocusContextKey, this._terminalShellTypeContextKey, @@ -991,9 +1006,9 @@ export class TerminalService implements ITerminalService { return {}; } - public createTerminal(shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance; - public createTerminal(profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance; - public createTerminal(shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile, cwd?: string | URI): ITerminalInstance { + createTerminal(shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance; + createTerminal(profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance; + createTerminal(shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile, cwd?: string | URI): ITerminalInstance { const shellLaunchConfig = this._convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile); if (cwd) { @@ -1019,14 +1034,14 @@ export class TerminalService implements ITerminalService { shellLaunchConfig.description = nls.localize('localTerminalDescription', "Local"); } - const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, shellLaunchConfig); - this._terminalTabs.push(terminalTab); - terminalTab.onPanelMovedToSide(() => this._onPanelMovedToSide.fire()); + const terminalGroup = this._instantiationService.createInstance(TerminalGroup, this._terminalContainer, shellLaunchConfig); + this._terminalGroups.push(terminalGroup); + terminalGroup.onPanelMovedToSide(() => this._onPanelMovedToSide.fire()); - const instance = terminalTab.terminalInstances[0]; + const instance = terminalGroup.terminalInstances[0]; - terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); - terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); + terminalGroup.addDisposable(terminalGroup.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); + terminalGroup.addDisposable(terminalGroup.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); this._initInstanceListeners(instance); this._onInstancesChanged.fire(); if (this.terminalInstances.length === 1) { @@ -1040,10 +1055,10 @@ export class TerminalService implements ITerminalService { protected _showBackgroundTerminal(instance: ITerminalInstance): void { this._backgroundedTerminalInstances.splice(this._backgroundedTerminalInstances.indexOf(instance), 1); instance.shellLaunchConfig.hideFromUser = false; - const terminalTab = this._instantiationService.createInstance(TerminalTab, this._terminalContainer, instance); - this._terminalTabs.push(terminalTab); - terminalTab.addDisposable(terminalTab.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); - terminalTab.addDisposable(terminalTab.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); + const terminalGroup = this._instantiationService.createInstance(TerminalGroup, this._terminalContainer, instance); + this._terminalGroups.push(terminalGroup); + terminalGroup.addDisposable(terminalGroup.onDisposed(this._onTabDisposed.fire, this._onTabDisposed)); + terminalGroup.addDisposable(terminalGroup.onInstancesChanged(this._onInstancesChanged.fire, this._onInstancesChanged)); if (this.terminalInstances.length === 1) { // It's the first instance so it should be made active automatically this.setActiveInstanceByIndex(0); @@ -1051,18 +1066,18 @@ export class TerminalService implements ITerminalService { this._onInstancesChanged.fire(); } - public async focusFindWidget(): Promise { + async focusFindWidget(): Promise { await this.showPanel(false); const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); pane?.terminalTabbedView?.focusFindWidget(); } - public hideFindWidget(): void { + hideFindWidget(): void { const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); pane?.terminalTabbedView?.hideFindWidget(); } - public findNext(): void { + findNext(): void { const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); if (pane?.terminalTabbedView) { pane.terminalTabbedView.showFindWidget(); @@ -1070,7 +1085,7 @@ export class TerminalService implements ITerminalService { } } - public findPrevious(): void { + findPrevious(): void { const pane = this._viewsService.getActiveViewWithId(TERMINAL_VIEW_ID); if (pane?.terminalTabbedView) { pane.terminalTabbedView.showFindWidget(); @@ -1078,13 +1093,13 @@ export class TerminalService implements ITerminalService { } } - public async setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): Promise { + async setContainers(panelContainer: HTMLElement, terminalContainer: HTMLElement): Promise { this._configHelper.panelContainer = panelContainer; this._terminalContainer = terminalContainer; - this._terminalTabs.forEach(tab => tab.attachToElement(terminalContainer)); + this._terminalGroups.forEach(group => group.attachToElement(terminalContainer)); } - public hidePanel(): void { + hidePanel(): void { // Hide the panel if the terminal is in the panel and it has no sibling views const location = this._viewDescriptorService.getViewLocationById(TERMINAL_VIEW_ID); if (location === ViewContainerLocation.Panel) { diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts index 2c902f5ffa8..972dbf21fd7 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabbedView.ts @@ -9,7 +9,7 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; import { ITerminalInstance, ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal'; import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget'; -import { DEFAULT_TABS_WIDGET_WIDTH, MIDPOINT_WIDGET_WIDTH, MIN_TABS_WIDGET_WIDTH, TerminalTabsWidget } from 'vs/workbench/contrib/terminal/browser/terminalTabsWidget'; +import { DEFAULT_TABS_WIDGET_WIDTH, MIDPOINT_WIDGET_WIDTH, MIN_TABS_WIDGET_WIDTH, TerminalTabList } from 'vs/workbench/contrib/terminal/browser/terminalTabsList'; import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService'; import { isLinux, isMacintosh } from 'vs/base/common/platform'; import * as dom from 'vs/base/browser/dom'; @@ -23,9 +23,8 @@ import { Action, IAction, Separator } from 'vs/base/common/actions'; import { IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IContextMenuService } from 'vs/platform/contextview/browser/contextView'; -import { KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_IS_TABS_NARROW_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_IS_TABS_NARROW_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; -import { ILogService } from 'vs/platform/log/common/log'; import { localize } from 'vs/nls'; const $ = dom.$; @@ -45,7 +44,7 @@ export class TerminalTabbedView extends Disposable { private _parentElement: HTMLElement; private _tabTreeContainer: HTMLElement; - private _tabsWidget: TerminalTabsWidget; + private _tabList: TerminalTabList; private _findWidget: TerminalFindWidget; private _sashDisposables: IDisposable[] | undefined; @@ -77,7 +76,6 @@ export class TerminalTabbedView extends Disposable { @IConfigurationService private readonly _configurationService: IConfigurationService, @IMenuService menuService: IMenuService, @IStorageService private readonly _storageService: IStorageService, - @ILogService private readonly _logService: ILogService, @IContextKeyService contextKeyService: IContextKeyService, ) { super(); @@ -94,7 +92,7 @@ export class TerminalTabbedView extends Disposable { this._tabsWidgetMenu = this._register(menuService.createMenu(MenuId.TerminalTabContext, contextKeyService)); this._tabsWidgetEmptyMenu = this._register(menuService.createMenu(MenuId.TerminalTabEmptyAreaContext, contextKeyService)); - this._register(this._tabsWidget = this._instantiationService.createInstance(TerminalTabsWidget, this._terminalTabTree)); + this._register(this._tabList = this._instantiationService.createInstance(TerminalTabList, this._terminalTabTree)); this._register(this._findWidget = this._instantiationService.createInstance(TerminalFindWidget, this._terminalService.getFindState())); parentElement.appendChild(this._findWidget.getDomNode()); @@ -113,10 +111,10 @@ export class TerminalTabbedView extends Disposable { this._terminalTabsFocusContextKey = KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS.bindTo(contextKeyService); _configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(TERMINAL_SETTING_ID.TabsEnabled) || - e.affectsConfiguration(TERMINAL_SETTING_ID.TabsHideCondition)) { + if (e.affectsConfiguration(TerminalSettingId.TabsEnabled) || + e.affectsConfiguration(TerminalSettingId.TabsHideCondition)) { this._refreshShowTabs(); - } else if (e.affectsConfiguration(TERMINAL_SETTING_ID.TabsLocation)) { + } else if (e.affectsConfiguration(TerminalSettingId.TabsLocation)) { this._tabTreeIndex = this._terminalService.configHelper.config.tabs.location === 'left' ? 0 : 1; this._terminalContainerIndex = this._terminalService.configHelper.config.tabs.location === 'left' ? 1 : 0; if (this._shouldShowTabs()) { @@ -206,12 +204,12 @@ export class TerminalTabbedView extends Disposable { // Size to include padding, icon, status icon (if any), split annotation (if any), + a little more const additionalWidth = 30; const statusIconWidth = instance.statusList.statuses.length > 0 ? STATUS_ICON_WIDTH : 0; - const splitAnnotationWidth = (this._terminalService.getTabForInstance(instance)?.terminalInstances.length || 0) > 1 ? SPLIT_ANNOTATION_WIDTH : 0; + const splitAnnotationWidth = (this._terminalService.getGroupForInstance(instance)?.terminalInstances.length || 0) > 1 ? SPLIT_ANNOTATION_WIDTH : 0; return additionalWidth + splitAnnotationWidth + statusIconWidth; } private _handleOnDidSashChange(): void { - let widgetWidth = this._splitView.getViewSize(this._tabTreeIndex); + const widgetWidth = this._splitView.getViewSize(this._tabTreeIndex); if (!this._width || widgetWidth <= 0) { return; } @@ -239,7 +237,7 @@ export class TerminalTabbedView extends Disposable { } this._splitView.addView({ element: this._terminalContainer, - layout: width => this._terminalService.terminalTabs.forEach(tab => tab.layout(width, this._height || 0)), + layout: width => this._terminalService.terminalGroups.forEach(tab => tab.layout(width, this._height || 0)), minimumSize: 120, maximumSize: Number.POSITIVE_INFINITY, onDidChange: () => Disposable.None, @@ -254,7 +252,7 @@ export class TerminalTabbedView extends Disposable { private _addTabTree() { this._splitView.addView({ element: this._tabTreeContainer, - layout: width => this._tabsWidget.layout(this._height || 0, width), + layout: width => this._tabList.layout(this._height || 0, width), minimumSize: MIN_TABS_WIDGET_WIDTH, maximumSize: MAX_TABS_WIDGET_WIDTH, onDidChange: () => Disposable.None, @@ -267,13 +265,7 @@ export class TerminalTabbedView extends Disposable { const hasText = this._tabTreeContainer.clientWidth > MIDPOINT_WIDGET_WIDTH; this._tabTreeContainer.classList.toggle('has-text', hasText); this._terminalIsTabsNarrowContextKey.set(!hasText); - for (const instance of this._terminalService.terminalInstances) { - try { - this._tabsWidget.rerender(instance); - } catch (e) { - this._logService.warn('Exception when rerendering new tab widget', e); - } - } + this._tabList.rerender(); } private _addSashListener() { @@ -422,7 +414,7 @@ export class TerminalTabbedView extends Disposable { const terminal = this._terminalService.getActiveInstance(); if (terminal) { - const preparedPath = await this._terminalService.preparePathForTerminalAsync(path, terminal.shellLaunchConfig.executable, terminal.title, terminal.shellType); + const preparedPath = await this._terminalService.preparePathForTerminalAsync(path, terminal.shellLaunchConfig.executable, terminal.title, terminal.shellType, terminal.isRemote); terminal.sendText(preparedPath, false); terminal.focus(); } @@ -439,7 +431,7 @@ export class TerminalTabbedView extends Disposable { if (parent === this._terminalContainer) { menu = this._instanceMenu; } else { - menu = this._tabsWidget.getFocus().length === 0 ? this._tabsWidgetEmptyMenu : this._tabsWidgetMenu; + menu = this._tabList.getFocus().length === 0 ? this._tabsWidgetEmptyMenu : this._tabsWidgetMenu; } const actionsDisposable = createAndFillInContextMenuActions(menu, undefined, actions); @@ -460,29 +452,29 @@ export class TerminalTabbedView extends Disposable { private _getTabActions(): Action[] { return [ new Separator(), - this._configurationService.inspect(TERMINAL_SETTING_ID.TabsLocation).userValue === 'left' ? + this._configurationService.inspect(TerminalSettingId.TabsLocation).userValue === 'left' ? new Action('moveRight', localize('moveTabsRight', "Move Tabs Right"), undefined, undefined, async () => { - this._configurationService.updateValue(TERMINAL_SETTING_ID.TabsLocation, 'right'); + this._configurationService.updateValue(TerminalSettingId.TabsLocation, 'right'); }) : new Action('moveLeft', localize('moveTabsLeft', "Move Tabs Left"), undefined, undefined, async () => { - this._configurationService.updateValue(TERMINAL_SETTING_ID.TabsLocation, 'left'); + this._configurationService.updateValue(TerminalSettingId.TabsLocation, 'left'); }), new Action('hideTabs', localize('hideTabs', "Hide Tabs"), undefined, undefined, async () => { - this._configurationService.updateValue(TERMINAL_SETTING_ID.TabsEnabled, false); + this._configurationService.updateValue(TerminalSettingId.TabsEnabled, false); }) ]; } - public focusTabs(): void { + focusTabs(): void { this._terminalTabsFocusContextKey.set(true); - const selected = this._tabsWidget.getSelection(); - this._tabsWidget.domFocus(); + const selected = this._tabList.getSelection(); + this._tabList.domFocus(); if (selected) { - this._tabsWidget.setFocus(selected); + this._tabList.setFocus(selected); } } - public focusFindWidget() { + focusFindWidget() { this._findWidgetVisible.set(true); const activeInstance = this._terminalService.getActiveInstance(); if (activeInstance && activeInstance.hasSelection() && activeInstance.selection!.indexOf('\n') === -1) { @@ -492,13 +484,13 @@ export class TerminalTabbedView extends Disposable { } } - public hideFindWidget() { + hideFindWidget() { this._findWidgetVisible.reset(); this.focus(); this._findWidget!.hide(); } - public showFindWidget() { + showFindWidget() { const activeInstance = this._terminalService.getActiveInstance(); if (activeInstance && activeInstance.hasSelection() && activeInstance.selection!.indexOf('\n') === -1) { this._findWidget!.show(activeInstance.selection); @@ -507,10 +499,10 @@ export class TerminalTabbedView extends Disposable { } } - public getFindWidget(): TerminalFindWidget { + getFindWidget(): TerminalFindWidget { return this._findWidget!; } - public focus() { + focus() { if (this._terminalService.connectionState === TerminalConnectionState.Connecting) { // If the terminal is waiting to reconnect to remote terminals, then there is no TerminalInstance yet that can // be focused. So wait for connection to finish, then focus. diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTabsWidget.ts b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts similarity index 80% rename from src/vs/workbench/contrib/terminal/browser/terminalTabsWidget.ts rename to src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts index 2c54a1d6ce4..586a375436a 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTabsWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTabsList.ts @@ -3,10 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IListService, WorkbenchObjectTree } from 'vs/platform/list/browser/listService'; -import { ITreeNode, ITreeRenderer } from 'vs/base/browser/ui/tree/tree'; -import { DefaultStyleController, IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; -import { IAccessibilityService } from 'vs/platform/accessibility/common/accessibility'; +import { IListService, WorkbenchList } from 'vs/platform/list/browser/listService'; +import { IListAccessibilityProvider } from 'vs/base/browser/ui/list/listWidget'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding'; @@ -18,7 +16,7 @@ import { IInstantiationService } from 'vs/platform/instantiation/common/instanti import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar'; import { MenuItemAction } from 'vs/platform/actions/common/actions'; import { MenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem'; -import { KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, TERMINAL_COMMAND_ID, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, TerminalCommandId, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { Codicon } from 'vs/base/common/codicons'; import { Action } from 'vs/base/common/actions'; import { MarkdownString } from 'vs/base/common/htmlContent'; @@ -28,6 +26,7 @@ import { IDecorationsService } from 'vs/workbench/services/decorations/browser/d import { IHoverAction, IHoverService } from 'vs/workbench/services/hover/browser/hover'; import Severity from 'vs/base/common/severity'; import { DisposableStore } from 'vs/base/common/lifecycle'; +import { IListRenderer } from 'vs/base/browser/ui/list/list'; const $ = DOM.$; const TAB_HEIGHT = 22; @@ -35,7 +34,7 @@ export const MIN_TABS_WIDGET_WIDTH = 46; export const DEFAULT_TABS_WIDGET_WIDTH = 80; export const MIDPOINT_WIDGET_WIDTH = (MIN_TABS_WIDGET_WIDTH + DEFAULT_TABS_WIDGET_WIDTH) / 2; -export class TerminalTabsWidget extends WorkbenchObjectTree { +export class TerminalTabList extends WorkbenchList { private _decorationsProvider: TerminalDecorationsProvider | undefined; private _terminalTabsSingleSelectedContextKey: IContextKey; @@ -46,7 +45,6 @@ export class TerminalTabsWidget extends WorkbenchObjectTree @IThemeService themeService: IThemeService, @IConfigurationService configurationService: IConfigurationService, @IKeybindingService keybindingService: IKeybindingService, - @IAccessibilityService accessibilityService: IAccessibilityService, @ITerminalService private readonly _terminalService: ITerminalService, @IInstantiationService instantiationService: IInstantiationService, @IDecorationsService _decorationsService: IDecorationsService @@ -56,7 +54,7 @@ export class TerminalTabsWidget extends WorkbenchObjectTree getHeight: () => TAB_HEIGHT, getTemplateId: () => 'terminal.tabs' }, - [instantiationService.createInstance(TerminalTabsRenderer, container, instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER), () => this.getSelection())], + [instantiationService.createInstance(TerminalTabsRenderer, container, instantiationService.createInstance(ResourceLabels, DEFAULT_LABELS_CONTAINER), () => this.getSelectedElements())], { horizontalScrolling: false, supportDynamicHeights: false, @@ -64,27 +62,23 @@ export class TerminalTabsWidget extends WorkbenchObjectTree getId: e => e?.instanceId }, accessibilityProvider: instantiationService.createInstance(TerminalTabsAccessibilityProvider), - styleController: id => new DefaultStyleController(DOM.createStyleSheet(container), id), - filter: undefined, smoothScrolling: configurationService.getValue('workbench.list.smoothScrolling'), multipleSelectionSupport: true, - expandOnlyOnTwistieClick: true, - selectionNavigation: true, additionalScrollHeight: TAB_HEIGHT }, contextKeyService, listService, themeService, configurationService, - keybindingService, - accessibilityService, + keybindingService ); this._terminalService.onInstancesChanged(() => this._render()); this._terminalService.onInstanceTitleChanged(() => this._render()); this._terminalService.onActiveInstanceChanged(e => { if (e) { - this.setSelection([e]); - this.reveal(e); + const i = this._terminalService.terminalInstances.indexOf(e); + this.setSelection([i]); + this.reveal(i); } }); @@ -96,25 +90,29 @@ export class TerminalTabsWidget extends WorkbenchObjectTree } }); + // on left click, if focus mode = single click, focus the element + // unless multi-selection is in progress this.onMouseClick(e => { - // If focus mode is single click focus the element unless a multi-select in happening - const focusMode = configurationService.getValue<'singleClick' | 'doubleClick'>(TERMINAL_SETTING_ID.TabsFocusMode); - if (focusMode === 'singleClick') { + const focusMode = configurationService.getValue<'singleClick' | 'doubleClick'>(TerminalSettingId.TabsFocusMode); + if (e.browserEvent.altKey && e.element) { + this._terminalService.splitInstance(e.element); + } else if (focusMode === 'singleClick') { if (this.getSelection().length <= 1) { e.element?.focus(true); } } }); - // Set the selection to whatever is right clicked if it is not inside the selection + // on right click, set the focus to that element + // unless multi-selection is in progress this.onContextMenu(e => { if (!e.element) { - this.setSelection([null]); + this.setSelection([]); return; } - const selection = this.getSelection(); + const selection = this.getSelectedElements(); if (!selection || !selection.find(s => e.element === s)) { - this.setSelection([e.element]); + this.setFocus(e.index !== undefined ? [e.index] : []); } }); @@ -154,23 +152,17 @@ export class TerminalTabsWidget extends WorkbenchObjectTree } private _render(): void { - this.setChildren(null, this._terminalService.terminalInstances.map(instance => { - return { - element: instance, - collapsed: true, - collapsible: false - }; - })); + this.splice(0, this.length, this._terminalService.terminalInstances); } } -class TerminalTabsRenderer implements ITreeRenderer { +class TerminalTabsRenderer implements IListRenderer { templateId = 'terminal.tabs'; constructor( private readonly _container: HTMLElement, private readonly _labels: ResourceLabels, - private readonly _getSelection: () => (ITerminalInstance | null)[], + private readonly _getSelection: () => ITerminalInstance[], @IInstantiationService private readonly _instantiationService: IInstantiationService, @ITerminalService private readonly _terminalService: ITerminalService, @IHoverService private readonly _hoverService: IHoverService, @@ -181,8 +173,6 @@ class TerminalTabsRenderer implements ITreeRenderer, index: number, template: ITerminalTabEntryTemplate): void { - let instance = node.element; - - const tab = this._terminalService.getTabForInstance(instance); - if (!tab) { - throw new Error(`Could not find tab for instance "${instance.instanceId}"`); + renderElement(instance: ITerminalInstance, index: number, template: ITerminalTabEntryTemplate): void { + const group = this._terminalService.getGroupForInstance(instance); + if (!group) { + throw new Error(`Could not find group for instance "${instance.instanceId}"`); } const hasText = !this.shouldHideText(); template.element.classList.toggle('has-text', hasText); let prefix: string = ''; - if (tab.terminalInstances.length > 1) { - const terminalIndex = tab.terminalInstances.indexOf(instance); + if (group.terminalInstances.length > 1) { + const terminalIndex = group.terminalInstances.indexOf(instance); if (terminalIndex === 0) { prefix = `┌ `; - } else if (terminalIndex === tab!.terminalInstances.length - 1) { + } else if (terminalIndex === group!.terminalInstances.length - 1) { prefix = `└ `; } else { prefix = `├ `; @@ -301,7 +289,7 @@ class TerminalTabsRenderer implements ITreeRenderer, index: number, templateData: ITerminalTabEntryTemplate): void { + disposeElement(instance: ITerminalInstance, index: number, templateData: ITerminalTabEntryTemplate): void { templateData.elementDispoables?.dispose(); templateData.elementDispoables = undefined; } @@ -312,10 +300,10 @@ class TerminalTabsRenderer implements ITreeRenderer { + new Action(TerminalCommandId.SplitInstance, localize('terminal.split', "Split"), ThemeIcon.asClassName(Codicon.splitHorizontal), true, async () => { this._runForSelectionOrInstance(instance, e => this._terminalService.splitInstance(e)); }), - new Action(TERMINAL_COMMAND_ID.KILL_INSTANCE, localize('terminal.kill', "Kill"), ThemeIcon.asClassName(Codicon.trashcan), true, async () => { + new Action(TerminalCommandId.KillInstance, localize('terminal.kill', "Kill"), ThemeIcon.asClassName(Codicon.trashcan), true, async () => { this._runForSelectionOrInstance(instance, e => e.dispose()); }) ]; @@ -362,7 +350,7 @@ class TerminalTabsAccessibilityProvider implements IListAccessibilityProvider 1) { const terminalIndex = tab.terminalInstances.indexOf(instance); ariaLabel = localize({ diff --git a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts index eff79fded36..e47c26ef786 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalTypeAheadAddon.ts @@ -65,61 +65,65 @@ class Cursor implements ICoordinate { private _y = 1; private _baseY = 1; - public get x() { + get x() { return this._x; } - public get y() { + get y() { return this._y; } - public get baseY() { + get baseY() { return this._baseY; } - public get coordinate(): ICoordinate { + get coordinate(): ICoordinate { return { x: this._x, y: this._y, baseY: this._baseY }; } - constructor(public readonly rows: number, public readonly cols: number, private readonly buffer: IBuffer) { - this._x = buffer.cursorX; - this._y = buffer.cursorY; - this._baseY = buffer.baseY; + constructor( + readonly rows: number, + readonly cols: number, + private readonly _buffer: IBuffer + ) { + this._x = _buffer.cursorX; + this._y = _buffer.cursorY; + this._baseY = _buffer.baseY; } - public getLine() { - return this.buffer.getLine(this._y + this._baseY); + getLine() { + return this._buffer.getLine(this._y + this._baseY); } - public getCell(loadInto?: IBufferCell) { + getCell(loadInto?: IBufferCell) { return this.getLine()?.getCell(this._x, loadInto); } - public moveTo(coordinate: ICoordinate) { + moveTo(coordinate: ICoordinate) { this._x = coordinate.x; this._y = (coordinate.y + coordinate.baseY) - this._baseY; return this.moveInstruction(); } - public clone() { - const c = new Cursor(this.rows, this.cols, this.buffer); + clone() { + const c = new Cursor(this.rows, this.cols, this._buffer); c.moveTo(this); return c; } - public move(x: number, y: number) { + move(x: number, y: number) { this._x = x; this._y = y; return this.moveInstruction(); } - public shift(x: number = 0, y: number = 0) { + shift(x: number = 0, y: number = 0) { this._x += x; this._y += y; return this.moveInstruction(); } - public moveInstruction() { + moveInstruction() { if (this._y >= this.rows) { this._baseY += this._y - (this.rows - 1); this._y = this.rows - 1; @@ -215,27 +219,29 @@ export interface IPrediction { } class StringReader { - public index = 0; + index = 0; - public get remaining() { - return this.input.length - this.index; + get remaining() { + return this._input.length - this.index; } - public get eof() { - return this.index === this.input.length; + get eof() { + return this.index === this._input.length; } - public get rest() { - return this.input.slice(this.index); + get rest() { + return this._input.slice(this.index); } - constructor(private readonly input: string) { } + constructor( + private readonly _input: string + ) { } /** * Advances the reader and returns the character if it matches. */ - public eatChar(char: string) { - if (this.input[this.index] !== char) { + eatChar(char: string) { + if (this._input[this.index] !== char) { return; } @@ -246,8 +252,8 @@ class StringReader { /** * Advances the reader and returns the string if it matches. */ - public eatStr(substr: string) { - if (this.input.slice(this.index, substr.length) !== substr) { + eatStr(substr: string) { + if (this._input.slice(this.index, substr.length) !== substr) { return; } @@ -260,8 +266,8 @@ class StringReader { * before the substring is consumed, it will buffer. Index is not moved * if it's not a match. */ - public eatGradually(substr: string): MatchResult { - let prevIndex = this.index; + eatGradually(substr: string): MatchResult { + const prevIndex = this.index; for (let i = 0; i < substr.length; i++) { if (i > 0 && this.eof) { return MatchResult.Buffer; @@ -279,8 +285,8 @@ class StringReader { /** * Advances the reader and returns the regex if it matches. */ - public eatRe(re: RegExp) { - const match = re.exec(this.input.slice(this.index)); + eatRe(re: RegExp) { + const match = re.exec(this._input.slice(this.index)); if (!match) { return; } @@ -292,8 +298,8 @@ class StringReader { /** * Advances the reader and returns the character if the code matches. */ - public eatCharCode(min = 0, max = min + 1) { - const code = this.input.charCodeAt(this.index); + eatCharCode(min = 0, max = min + 1) { + const code = this._input.charCodeAt(this.index); if (code < min || code >= max) { return undefined; } @@ -308,21 +314,21 @@ class StringReader { * after it. */ class HardBoundary implements IPrediction { - public readonly clearAfterTimeout = false; + readonly clearAfterTimeout = false; - public apply() { + apply() { return ''; } - public rollback() { + rollback() { return ''; } - public rollForwards() { + rollForwards() { return ''; } - public matches() { + matches() { return MatchResult.Failure; } } @@ -332,30 +338,30 @@ class HardBoundary implements IPrediction { * through its `matches` request. */ class TentativeBoundary implements IPrediction { - private appliedCursor?: Cursor; + private _appliedCursor?: Cursor; - constructor(public readonly inner: IPrediction) { } + constructor(readonly inner: IPrediction) { } - public apply(buffer: IBuffer, cursor: Cursor) { - this.appliedCursor = cursor.clone(); - this.inner.apply(buffer, this.appliedCursor); + apply(buffer: IBuffer, cursor: Cursor) { + this._appliedCursor = cursor.clone(); + this.inner.apply(buffer, this._appliedCursor); return ''; } - public rollback(cursor: Cursor) { + rollback(cursor: Cursor) { this.inner.rollback(cursor.clone()); return ''; } - public rollForwards(cursor: Cursor, withInput: string) { - if (this.appliedCursor) { - cursor.moveTo(this.appliedCursor); + rollForwards(cursor: Cursor, withInput: string) { + if (this._appliedCursor) { + cursor.moveTo(this._appliedCursor); } return withInput; } - public matches(input: StringReader) { + matches(input: StringReader) { return this.inner.matches(input); } } @@ -367,17 +373,17 @@ export const isTenativeCharacterPrediction = (p: unknown): p is (TentativeBounda * Prediction for a single alphanumeric character. */ class CharacterPrediction implements IPrediction { - public readonly affectsStyle = true; + readonly affectsStyle = true; - public appliedAt?: { + appliedAt?: { pos: ICoordinate; oldAttributes: string; oldChar: string; }; - constructor(private readonly style: TypeAheadStyle, private readonly char: string) { } + constructor(private readonly _style: TypeAheadStyle, private readonly _char: string) { } - public apply(_: IBuffer, cursor: Cursor) { + apply(_: IBuffer, cursor: Cursor) { const cell = cursor.getCell(); this.appliedAt = cell ? { pos: cursor.coordinate, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() } @@ -385,10 +391,10 @@ class CharacterPrediction implements IPrediction { cursor.shift(1); - return this.style.apply + this.char + this.style.undo; + return this._style.apply + this._char + this._style.undo; } - public rollback(cursor: Cursor) { + rollback(cursor: Cursor) { if (!this.appliedAt) { return ''; // not applied } @@ -398,7 +404,7 @@ class CharacterPrediction implements IPrediction { return r; } - public rollForwards(cursor: Cursor, input: string) { + rollForwards(cursor: Cursor, input: string) { if (!this.appliedAt) { return ''; // not applied } @@ -406,8 +412,8 @@ class CharacterPrediction implements IPrediction { return cursor.clone().moveTo(this.appliedAt.pos) + input; } - public matches(input: StringReader, lookBehind?: IPrediction) { - let startIndex = input.index; + matches(input: StringReader, lookBehind?: IPrediction) { + const startIndex = input.index; // remove any styling CSI before checking the char while (input.eatRe(CSI_STYLE_RE)) { } @@ -416,13 +422,13 @@ class CharacterPrediction implements IPrediction { return MatchResult.Buffer; } - if (input.eatChar(this.char)) { + if (input.eatChar(this._char)) { return MatchResult.Success; } if (lookBehind instanceof CharacterPrediction) { // see #112842 - const sillyZshOutcome = input.eatGradually(`\b${lookBehind.char}${this.char}`); + const sillyZshOutcome = input.eatGradually(`\b${lookBehind._char}${this._char}`); if (sillyZshOutcome !== MatchResult.Failure) { return sillyZshOutcome; } @@ -434,48 +440,48 @@ class CharacterPrediction implements IPrediction { } class BackspacePrediction implements IPrediction { - protected appliedAt?: { + protected _appliedAt?: { pos: ICoordinate; oldAttributes: string; oldChar: string; isLastChar: boolean; }; - constructor(private readonly terminal: Terminal) { } + constructor(private readonly _terminal: Terminal) { } - public apply(_: IBuffer, cursor: Cursor) { + apply(_: IBuffer, cursor: Cursor) { // at eol if everything to the right is whitespace (zsh will emit a "clear line" code in this case) // todo: can be optimized if `getTrimmedLength` is exposed from xterm const isLastChar = !cursor.getLine()?.translateToString(undefined, cursor.x).trim(); const pos = cursor.coordinate; const move = cursor.shift(-1); const cell = cursor.getCell(); - this.appliedAt = cell + this._appliedAt = cell ? { isLastChar, pos, oldAttributes: attributesToSeq(cell), oldChar: cell.getChars() } : { isLastChar, pos, oldAttributes: '', oldChar: '' }; return move + DELETE_CHAR; } - public rollback(cursor: Cursor) { - if (!this.appliedAt) { + rollback(cursor: Cursor) { + if (!this._appliedAt) { return ''; // not applied } - const { oldAttributes, oldChar, pos } = this.appliedAt; + const { oldAttributes, oldChar, pos } = this._appliedAt; if (!oldChar) { return cursor.moveTo(pos) + DELETE_CHAR; } - return oldAttributes + oldChar + cursor.moveTo(pos) + attributesToSeq(core(this.terminal)._inputHandler._curAttrData); + return oldAttributes + oldChar + cursor.moveTo(pos) + attributesToSeq(core(this._terminal)._inputHandler._curAttrData); } - public rollForwards() { + rollForwards() { return ''; } - public matches(input: StringReader) { - if (this.appliedAt?.isLastChar) { + matches(input: StringReader) { + if (this._appliedAt?.isLastChar) { const r1 = input.eatGradually(`\b${CSI}K`); if (r1 !== MatchResult.Failure) { return r1; @@ -492,23 +498,23 @@ class BackspacePrediction implements IPrediction { } class NewlinePrediction implements IPrediction { - protected prevPosition?: ICoordinate; + protected _prevPosition?: ICoordinate; - public apply(_: IBuffer, cursor: Cursor) { - this.prevPosition = cursor.coordinate; + apply(_: IBuffer, cursor: Cursor) { + this._prevPosition = cursor.coordinate; cursor.move(0, cursor.y + 1); return '\r\n'; } - public rollback(cursor: Cursor) { - return this.prevPosition ? cursor.moveTo(this.prevPosition) : ''; + rollback(cursor: Cursor) { + return this._prevPosition ? cursor.moveTo(this._prevPosition) : ''; } - public rollForwards() { + rollForwards() { return ''; // does not need to rewrite } - public matches(input: StringReader) { + matches(input: StringReader) { return input.eatGradually('\r\n'); } } @@ -518,13 +524,13 @@ class NewlinePrediction implements IPrediction { * prediction, but shells handle it slightly differently. */ class LinewrapPrediction extends NewlinePrediction implements IPrediction { - public override apply(_: IBuffer, cursor: Cursor) { - this.prevPosition = cursor.coordinate; + override apply(_: IBuffer, cursor: Cursor) { + this._prevPosition = cursor.coordinate; cursor.move(0, cursor.y + 1); return ' \r'; } - public override matches(input: StringReader) { + override matches(input: StringReader) { // bash and zshell add a space which wraps in the terminal, then a CR const r = input.eatGradually(' \r'); if (r !== MatchResult.Failure) { @@ -538,7 +544,7 @@ class LinewrapPrediction extends NewlinePrediction implements IPrediction { } class CursorMovePrediction implements IPrediction { - private applied?: { + private _applied?: { rollForward: string; prevPosition: number; prevAttrs: string; @@ -546,17 +552,17 @@ class CursorMovePrediction implements IPrediction { }; constructor( - private readonly direction: CursorMoveDirection, - private readonly moveByWords: boolean, - private readonly amount: number, + private readonly _direction: CursorMoveDirection, + private readonly _moveByWords: boolean, + private readonly _amount: number, ) { } - public apply(buffer: IBuffer, cursor: Cursor) { + apply(buffer: IBuffer, cursor: Cursor) { const prevPosition = cursor.x; const currentCell = cursor.getCell(); const prevAttrs = currentCell ? attributesToSeq(currentCell) : ''; - const { amount, direction, moveByWords } = this; + const { _amount: amount, _direction: direction, _moveByWords: moveByWords } = this; const delta = direction === CursorMoveDirection.Back ? -1 : 1; const target = cursor.clone(); @@ -568,35 +574,35 @@ class CursorMovePrediction implements IPrediction { target.shift(delta * amount); } - this.applied = { + this._applied = { amount: Math.abs(cursor.x - target.x), prevPosition, prevAttrs, rollForward: cursor.moveTo(target), }; - return this.applied.rollForward; + return this._applied.rollForward; } - public rollback(cursor: Cursor) { - if (!this.applied) { + rollback(cursor: Cursor) { + if (!this._applied) { return ''; } - return cursor.move(this.applied.prevPosition, cursor.y) + this.applied.prevAttrs; + return cursor.move(this._applied.prevPosition, cursor.y) + this._applied.prevAttrs; } - public rollForwards() { + rollForwards() { return ''; // does not need to rewrite } - public matches(input: StringReader) { - if (!this.applied) { + matches(input: StringReader) { + if (!this._applied) { return MatchResult.Failure; } - const direction = this.direction; - const { amount, rollForward } = this.applied; + const direction = this._direction; + const { amount, rollForward } = this._applied; // arg can be omitted to move one character. We don't eatGradually() here @@ -627,38 +633,38 @@ class CursorMovePrediction implements IPrediction { } export class PredictionStats extends Disposable { - private readonly stats: [latency: number, correct: boolean][] = []; - private index = 0; - private readonly addedAtTime = new WeakMap(); - private readonly changeEmitter = new Emitter(); - public readonly onChange = this.changeEmitter.event; + private readonly _stats: [latency: number, correct: boolean][] = []; + private _index = 0; + private readonly _addedAtTime = new WeakMap(); + private readonly _changeEmitter = new Emitter(); + readonly onChange = this._changeEmitter.event; /** * Gets the percent (0-1) of predictions that were accurate. */ - public get accuracy() { + get accuracy() { let correctCount = 0; - for (const [, correct] of this.stats) { + for (const [, correct] of this._stats) { if (correct) { correctCount++; } } - return correctCount / (this.stats.length || 1); + return correctCount / (this._stats.length || 1); } /** * Gets the number of recorded stats. */ - public get sampleSize() { - return this.stats.length; + get sampleSize() { + return this._stats.length; } /** * Gets latency stats of successful predictions. */ - public get latency() { - const latencies = this.stats.filter(([, correct]) => correct).map(([s]) => s).sort(); + get latency() { + const latencies = this._stats.filter(([, correct]) => correct).map(([s]) => s).sort(); return { count: latencies.length, @@ -671,9 +677,9 @@ export class PredictionStats extends Disposable { /** * Gets the maximum observed latency. */ - public get maxLatency() { + get maxLatency() { let max = -Infinity; - for (const [latency, correct] of this.stats) { + for (const [latency, correct] of this._stats) { if (correct) { max = Math.max(latency, max); } @@ -684,16 +690,16 @@ export class PredictionStats extends Disposable { constructor(timeline: PredictionTimeline) { super(); - this._register(timeline.onPredictionAdded(p => this.addedAtTime.set(p, Date.now()))); - this._register(timeline.onPredictionSucceeded(this.pushStat.bind(this, true))); - this._register(timeline.onPredictionFailed(this.pushStat.bind(this, false))); + this._register(timeline.onPredictionAdded(p => this._addedAtTime.set(p, Date.now()))); + this._register(timeline.onPredictionSucceeded(this._pushStat.bind(this, true))); + this._register(timeline.onPredictionFailed(this._pushStat.bind(this, false))); } - private pushStat(correct: boolean, prediction: IPrediction) { - const started = this.addedAtTime.get(prediction)!; - this.stats[this.index] = [Date.now() - started, correct]; - this.index = (this.index + 1) % statsBufferSize; - this.changeEmitter.fire(); + private _pushStat(correct: boolean, prediction: IPrediction) { + const started = this._addedAtTime.get(prediction)!; + this._stats[this._index] = [Date.now() - started, correct]; + this._index = (this._index + 1) % statsBufferSize; + this._changeEmitter.fire(); } } @@ -702,12 +708,12 @@ export class PredictionTimeline { * Expected queue of events. Only predictions for the lowest are * written into the terminal. */ - private expected: ({ gen: number; p: IPrediction })[] = []; + private _expected: ({ gen: number; p: IPrediction })[] = []; /** * Current prediction generation. */ - private currentGen = 0; + private _currentGen = 0; /** * Current cursor position -- kept outside the buffer since it can be ahead @@ -728,58 +734,58 @@ export class PredictionTimeline { * Previously sent data that was buffered and should be prepended to the * next input. */ - private inputBuffer?: string; + private _inputBuffer?: string; /** * Whether predictions are echoed to the terminal. If false, predictions * will still be computed internally for latency metrics, but input will * never be adjusted. */ - private showPredictions = false; + private _showPredictions = false; /** * The last successfully-made prediction. */ - private lookBehind?: IPrediction; + private _lookBehind?: IPrediction; - private readonly addedEmitter = new Emitter(); - public readonly onPredictionAdded = this.addedEmitter.event; - private readonly failedEmitter = new Emitter(); - public readonly onPredictionFailed = this.failedEmitter.event; - private readonly succeededEmitter = new Emitter(); - public readonly onPredictionSucceeded = this.succeededEmitter.event; + private readonly _addedEmitter = new Emitter(); + readonly onPredictionAdded = this._addedEmitter.event; + private readonly _failedEmitter = new Emitter(); + readonly onPredictionFailed = this._failedEmitter.event; + private readonly _succeededEmitter = new Emitter(); + readonly onPredictionSucceeded = this._succeededEmitter.event; - private get currentGenerationPredictions() { - return this.expected.filter(({ gen }) => gen === this.expected[0].gen).map(({ p }) => p); + private get _currentGenerationPredictions() { + return this._expected.filter(({ gen }) => gen === this._expected[0].gen).map(({ p }) => p); } - public get isShowingPredictions() { - return this.showPredictions; + get isShowingPredictions() { + return this._showPredictions; } - public get length() { - return this.expected.length; + get length() { + return this._expected.length; } - constructor(public readonly terminal: Terminal, private readonly style: TypeAheadStyle) { } + constructor(readonly terminal: Terminal, private readonly _style: TypeAheadStyle) { } - public setShowPredictions(show: boolean) { - if (show === this.showPredictions) { + setShowPredictions(show: boolean) { + if (show === this._showPredictions) { return; } // console.log('set predictions:', show); - this.showPredictions = show; + this._showPredictions = show; - const buffer = this.getActiveBuffer(); + const buffer = this._getActiveBuffer(); if (!buffer) { return; } - const toApply = this.currentGenerationPredictions; + const toApply = this._currentGenerationPredictions; if (show) { this.clearCursor(); - this.style.expectIncomingStyle(toApply.reduce((count, p) => p.affectsStyle ? count + 1 : count, 0)); + this._style.expectIncomingStyle(toApply.reduce((count, p) => p.affectsStyle ? count + 1 : count, 0)); this.terminal.write(toApply.map(p => p.apply(buffer, this.physicalCursor(buffer))).join('')); } else { this.terminal.write(toApply.reverse().map(p => p.rollback(this.physicalCursor(buffer))).join('')); @@ -789,41 +795,41 @@ export class PredictionTimeline { /** * Undoes any predictions written and resets expectations. */ - public undoAllPredictions() { - const buffer = this.getActiveBuffer(); - if (this.showPredictions && buffer) { - this.terminal.write(this.currentGenerationPredictions.reverse() + undoAllPredictions() { + const buffer = this._getActiveBuffer(); + if (this._showPredictions && buffer) { + this.terminal.write(this._currentGenerationPredictions.reverse() .map(p => p.rollback(this.physicalCursor(buffer))).join('')); } - this.expected = []; + this._expected = []; } /** * Should be called when input is incoming to the temrinal. */ - public beforeServerInput(input: string): string { + beforeServerInput(input: string): string { const originalInput = input; - if (this.inputBuffer) { - input = this.inputBuffer + input; - this.inputBuffer = undefined; + if (this._inputBuffer) { + input = this._inputBuffer + input; + this._inputBuffer = undefined; } - if (!this.expected.length) { - this.clearPredictionState(); + if (!this._expected.length) { + this._clearPredictionState(); return input; } - const buffer = this.getActiveBuffer(); + const buffer = this._getActiveBuffer(); if (!buffer) { - this.clearPredictionState(); + this._clearPredictionState(); return input; } let output = ''; const reader = new StringReader(input); - const startingGen = this.expected[0].gen; + const startingGen = this._expected[0].gen; const emitPredictionOmitted = () => { const omit = reader.eatRe(PREDICTION_OMIT_RE); if (omit) { @@ -831,13 +837,13 @@ export class PredictionTimeline { } }; - ReadLoop: while (this.expected.length && reader.remaining > 0) { + ReadLoop: while (this._expected.length && reader.remaining > 0) { emitPredictionOmitted(); - const { p: prediction, gen } = this.expected[0]; + const { p: prediction, gen } = this._expected[0]; const cursor = this.physicalCursor(buffer); - let beforeTestReaderIndex = reader.index; - switch (prediction.matches(reader, this.lookBehind)) { + const beforeTestReaderIndex = reader.index; + switch (prediction.matches(reader, this._lookBehind)) { case MatchResult.Success: // if the input character matches what the next prediction expected, undo // the prediction and write the real character out. @@ -849,28 +855,28 @@ export class PredictionTimeline { output += eaten; } - this.succeededEmitter.fire(prediction); - this.lookBehind = prediction; - this.expected.shift(); + this._succeededEmitter.fire(prediction); + this._lookBehind = prediction; + this._expected.shift(); break; case MatchResult.Buffer: // on a buffer, store the remaining data and completely read data // to be output as normal. - this.inputBuffer = input.slice(beforeTestReaderIndex); + this._inputBuffer = input.slice(beforeTestReaderIndex); reader.index = input.length; break ReadLoop; case MatchResult.Failure: // on a failure, roll back all remaining items in this generation // and clear predictions, since they are no longer valid - const rollback = this.expected.filter(p => p.gen === startingGen).reverse(); + const rollback = this._expected.filter(p => p.gen === startingGen).reverse(); output += rollback.map(({ p }) => p.rollback(this.physicalCursor(buffer))).join(''); if (rollback.some(r => r.p.affectsStyle)) { // reading the current style should generally be safe, since predictions // always restore the style if they modify it. output += attributesToSeq(core(this.terminal)._inputHandler._curAttrData); } - this.clearPredictionState(); - this.failedEmitter.fire(prediction); + this._clearPredictionState(); + this._failedEmitter.fire(prediction); break ReadLoop; } } @@ -881,24 +887,24 @@ export class PredictionTimeline { // reset the cursor if (!reader.eof) { output += reader.rest; - this.clearPredictionState(); + this._clearPredictionState(); } // If we passed a generation boundary, apply the current generation's predictions - if (this.expected.length && startingGen !== this.expected[0].gen) { - for (const { p, gen } of this.expected) { - if (gen !== this.expected[0].gen) { + if (this._expected.length && startingGen !== this._expected[0].gen) { + for (const { p, gen } of this._expected) { + if (gen !== this._expected[0].gen) { break; } if (p.affectsStyle) { - this.style.expectIncomingStyle(); + this._style.expectIncomingStyle(); } output += p.apply(buffer, this.physicalCursor(buffer)); } } - if (!this.showPredictions) { + if (!this._showPredictions) { return originalInput; } @@ -920,20 +926,20 @@ export class PredictionTimeline { * Clears any expected predictions and stored state. Should be called when * the pty gives us something we don't recognize. */ - private clearPredictionState() { - this.expected = []; + private _clearPredictionState() { + this._expected = []; this.clearCursor(); - this.lookBehind = undefined; + this._lookBehind = undefined; } /** * Appends a typeahead prediction. */ - public addPrediction(buffer: IBuffer, prediction: IPrediction) { - this.expected.push({ gen: this.currentGen, p: prediction }); - this.addedEmitter.fire(prediction); + addPrediction(buffer: IBuffer, prediction: IPrediction) { + this._expected.push({ gen: this._currentGen, p: prediction }); + this._addedEmitter.fire(prediction); - if (this.currentGen !== this.expected[0].gen) { + if (this._currentGen !== this._expected[0].gen) { prediction.apply(buffer, this.tentativeCursor(buffer)); return false; } @@ -941,9 +947,9 @@ export class PredictionTimeline { const text = prediction.apply(buffer, this.physicalCursor(buffer)); this._tenativeCursor = undefined; // next read will get or clone the physical cursor - if (this.showPredictions && text) { + if (this._showPredictions && text) { if (prediction.affectsStyle) { - this.style.expectIncomingStyle(); + this._style.expectIncomingStyle(); } // console.log('predict:', JSON.stringify(text)); this.terminal.write(text); @@ -957,9 +963,9 @@ export class PredictionTimeline { * after this one will only be displayed after the give prediction matches * pty output/ */ - public addBoundary(): void; - public addBoundary(buffer: IBuffer, prediction: IPrediction): boolean; - public addBoundary(buffer?: IBuffer, prediction?: IPrediction) { + addBoundary(): void; + addBoundary(buffer: IBuffer, prediction: IPrediction): boolean; + addBoundary(buffer?: IBuffer, prediction?: IPrediction) { let applied = false; if (buffer && prediction) { // We apply the prediction so that it's matched against, but wrapped @@ -968,30 +974,30 @@ export class PredictionTimeline { applied = this.addPrediction(buffer, new TentativeBoundary(prediction)); prediction.apply(buffer, this.tentativeCursor(buffer)); } - this.currentGen++; + this._currentGen++; return applied; } /** * Peeks the last prediction written. */ - public peekEnd(): IPrediction | undefined { - return this.expected[this.expected.length - 1]?.p; + peekEnd(): IPrediction | undefined { + return this._expected[this._expected.length - 1]?.p; } /** * Peeks the first pending prediction. */ - public peekStart(): IPrediction | undefined { - return this.expected[0]?.p; + peekStart(): IPrediction | undefined { + return this._expected[0]?.p; } /** * Current position of the cursor in the terminal. */ - public physicalCursor(buffer: IBuffer) { + physicalCursor(buffer: IBuffer) { if (!this._physicalCursor) { - if (this.showPredictions) { + if (this._showPredictions) { flushOutput(this.terminal); } this._physicalCursor = new Cursor(this.terminal.rows, this.terminal.cols, buffer); @@ -1004,7 +1010,7 @@ export class PredictionTimeline { * Cursor position if all predictions and boundaries that have been inserted * so far turn out to be successfully predicted. */ - public tentativeCursor(buffer: IBuffer) { + tentativeCursor(buffer: IBuffer) { if (!this._tenativeCursor) { this._tenativeCursor = this.physicalCursor(buffer).clone(); } @@ -1012,12 +1018,12 @@ export class PredictionTimeline { return this._tenativeCursor; } - public clearCursor() { + clearCursor() { this._physicalCursor = undefined; this._tenativeCursor = undefined; } - private getActiveBuffer() { + private _getActiveBuffer() { const buffer = this.terminal.buffer.active; return buffer.type === 'normal' ? buffer : undefined; } @@ -1104,7 +1110,7 @@ const getColorWidth = (params: (number | number[])[], pos: number) => { }; class TypeAheadStyle implements IDisposable { - private static compileArgs(args: ReadonlyArray) { + private static _compileArgs(args: ReadonlyArray) { return `${CSI}${args.join(';')}m`; } @@ -1112,16 +1118,16 @@ class TypeAheadStyle implements IDisposable { * Number of typeahead style arguments we expect to read. If this is 0 and * we see a style coming in, we know that the PTY actually wanted to update. */ - private expectedIncomingStyles = 0; - private applyArgs!: ReadonlyArray; - private originalUndoArgs!: ReadonlyArray; - private undoArgs!: ReadonlyArray; + private _expectedIncomingStyles = 0; + private _applyArgs!: ReadonlyArray; + private _originalUndoArgs!: ReadonlyArray; + private _undoArgs!: ReadonlyArray; - public apply!: string; - public undo!: string; - private csiHandler?: IDisposable; + apply!: string; + undo!: string; + private _csiHandler?: IDisposable; - constructor(value: ITerminalConfiguration['localEchoStyle'], private readonly terminal: Terminal) { + constructor(value: ITerminalConfiguration['localEchoStyle'], private readonly _terminal: Terminal) { this.onUpdate(value); } @@ -1129,18 +1135,18 @@ class TypeAheadStyle implements IDisposable { * Signals that a style was written to the terminal and we should watch * for it coming in. */ - public expectIncomingStyle(n = 1) { - this.expectedIncomingStyles += n * 2; + expectIncomingStyle(n = 1) { + this._expectedIncomingStyles += n * 2; } /** * Starts tracking for CSI changes in the terminal. */ - public startTracking() { - this.expectedIncomingStyles = 0; - this.onDidWriteSGR(attributesToArgs(core(this.terminal)._inputHandler._curAttrData)); - this.csiHandler = this.terminal.parser.registerCsiHandler({ final: 'm' }, args => { - this.onDidWriteSGR(args); + startTracking() { + this._expectedIncomingStyles = 0; + this._onDidWriteSGR(attributesToArgs(core(this._terminal)._inputHandler._curAttrData)); + this._csiHandler = this._terminal.parser.registerCsiHandler({ final: 'm' }, args => { + this._onDidWriteSGR(args); return false; }); } @@ -1149,69 +1155,69 @@ class TypeAheadStyle implements IDisposable { * Stops tracking terminal CSI changes. */ @debounce(2000) - public debounceStopTracking() { - this.stopTracking(); + debounceStopTracking() { + this._stopTracking(); } /** * @inheritdoc */ - public dispose() { - this.stopTracking(); + dispose() { + this._stopTracking(); } - private stopTracking() { - this.csiHandler?.dispose(); - this.csiHandler = undefined; + private _stopTracking() { + this._csiHandler?.dispose(); + this._csiHandler = undefined; } - private onDidWriteSGR(args: (number | number[])[]) { - const originalUndo = this.undoArgs; + private _onDidWriteSGR(args: (number | number[])[]) { + const originalUndo = this._undoArgs; for (let i = 0; i < args.length;) { const px = args[i]; const p = typeof px === 'number' ? px : px[0]; - if (this.expectedIncomingStyles) { - if (arrayHasPrefixAt(args, i, this.undoArgs)) { - this.expectedIncomingStyles--; - i += this.undoArgs.length; + if (this._expectedIncomingStyles) { + if (arrayHasPrefixAt(args, i, this._undoArgs)) { + this._expectedIncomingStyles--; + i += this._undoArgs.length; continue; } - if (arrayHasPrefixAt(args, i, this.applyArgs)) { - this.expectedIncomingStyles--; - i += this.applyArgs.length; + if (arrayHasPrefixAt(args, i, this._applyArgs)) { + this._expectedIncomingStyles--; + i += this._applyArgs.length; continue; } } const width = p === 38 || p === 48 || p === 58 ? getColorWidth(args, i) : 1; - switch (this.applyArgs[0]) { + switch (this._applyArgs[0]) { case 1: if (p === 2) { - this.undoArgs = [22, 2]; + this._undoArgs = [22, 2]; } else if (p === 22 || p === 0) { - this.undoArgs = [22]; + this._undoArgs = [22]; } break; case 2: if (p === 1) { - this.undoArgs = [22, 1]; + this._undoArgs = [22, 1]; } else if (p === 22 || p === 0) { - this.undoArgs = [22]; + this._undoArgs = [22]; } break; case 38: if (p === 0 || p === 39 || p === 100) { - this.undoArgs = [39]; + this._undoArgs = [39]; } else if ((p >= 30 && p <= 38) || (p >= 90 && p <= 97)) { - this.undoArgs = args.slice(i, i + width) as number[]; + this._undoArgs = args.slice(i, i + width) as number[]; } break; default: - if (p === this.applyArgs[0]) { - this.undoArgs = this.applyArgs; + if (p === this._applyArgs[0]) { + this._undoArgs = this._applyArgs; } else if (p === 0) { - this.undoArgs = this.originalUndoArgs; + this._undoArgs = this._originalUndoArgs; } // no-op } @@ -1219,23 +1225,23 @@ class TypeAheadStyle implements IDisposable { i += width; } - if (originalUndo !== this.undoArgs) { - this.undo = TypeAheadStyle.compileArgs(this.undoArgs); + if (originalUndo !== this._undoArgs) { + this.undo = TypeAheadStyle._compileArgs(this._undoArgs); } } /** * Updates the current typeahead style. */ - public onUpdate(style: ITerminalConfiguration['localEchoStyle']) { - const { applyArgs, undoArgs } = this.getArgs(style); - this.applyArgs = applyArgs; - this.undoArgs = this.originalUndoArgs = undoArgs; - this.apply = TypeAheadStyle.compileArgs(this.applyArgs); - this.undo = TypeAheadStyle.compileArgs(this.undoArgs); + onUpdate(style: ITerminalConfiguration['localEchoStyle']) { + const { applyArgs, undoArgs } = this._getArgs(style); + this._applyArgs = applyArgs; + this._undoArgs = this._originalUndoArgs = undoArgs; + this.apply = TypeAheadStyle._compileArgs(this._applyArgs); + this.undo = TypeAheadStyle._compileArgs(this._undoArgs); } - private getArgs(style: ITerminalConfiguration['localEchoStyle']) { + private _getArgs(style: ITerminalConfiguration['localEchoStyle']) { switch (style) { case 'bold': return { applyArgs: [1], undoArgs: [22] }; @@ -1267,64 +1273,64 @@ export const enum CharPredictState { } export class TypeAheadAddon extends Disposable implements ITerminalAddon { - private typeaheadStyle?: TypeAheadStyle; - private typeaheadThreshold = this.config.config.localEchoLatencyThreshold; - private excludeProgramRe = compileExcludeRegexp(this.config.config.localEchoExcludePrograms); - protected lastRow?: { y: number; startingX: number; endingX: number; charState: CharPredictState }; - protected timeline?: PredictionTimeline; - private terminalTitle = ''; - public stats?: PredictionStats; + private _typeaheadStyle?: TypeAheadStyle; + private _typeaheadThreshold = this._config.config.localEchoLatencyThreshold; + private _excludeProgramRe = compileExcludeRegexp(this._config.config.localEchoExcludePrograms); + protected _lastRow?: { y: number; startingX: number; endingX: number; charState: CharPredictState }; + protected _timeline?: PredictionTimeline; + private _terminalTitle = ''; + stats?: PredictionStats; /** * Debounce that clears predictions after a timeout if the PTY doesn't apply them. */ - private clearPredictionDebounce?: IDisposable; + private _clearPredictionDebounce?: IDisposable; constructor( - private processManager: ITerminalProcessManager, - private readonly config: TerminalConfigHelper, - @ITelemetryService private readonly telemetryService: ITelemetryService, + private _processManager: ITerminalProcessManager, + private readonly _config: TerminalConfigHelper, + @ITelemetryService private readonly _telemetryService: ITelemetryService, ) { super(); - this._register(toDisposable(() => this.clearPredictionDebounce?.dispose())); + this._register(toDisposable(() => this._clearPredictionDebounce?.dispose())); } - public activate(terminal: Terminal): void { - const style = this.typeaheadStyle = this._register(new TypeAheadStyle(this.config.config.localEchoStyle, terminal)); - const timeline = this.timeline = new PredictionTimeline(terminal, this.typeaheadStyle); - const stats = this.stats = this._register(new PredictionStats(this.timeline)); + activate(terminal: Terminal): void { + const style = this._typeaheadStyle = this._register(new TypeAheadStyle(this._config.config.localEchoStyle, terminal)); + const timeline = this._timeline = new PredictionTimeline(terminal, this._typeaheadStyle); + const stats = this.stats = this._register(new PredictionStats(this._timeline)); - timeline.setShowPredictions(this.typeaheadThreshold === 0); - this._register(terminal.onData(e => this.onUserData(e))); + timeline.setShowPredictions(this._typeaheadThreshold === 0); + this._register(terminal.onData(e => this._onUserData(e))); this._register(terminal.onTitleChange(title => { - this.terminalTitle = title; - this.reevaluatePredictorState(stats, timeline); + this._terminalTitle = title; + this._reevaluatePredictorState(stats, timeline); })); this._register(terminal.onResize(() => { timeline.setShowPredictions(false); timeline.clearCursor(); - this.reevaluatePredictorState(stats, timeline); + this._reevaluatePredictorState(stats, timeline); })); - this._register(this.config.onConfigChanged(() => { - style.onUpdate(this.config.config.localEchoStyle); - this.typeaheadThreshold = this.config.config.localEchoLatencyThreshold; - this.excludeProgramRe = compileExcludeRegexp(this.config.config.localEchoExcludePrograms); - this.reevaluatePredictorState(stats, timeline); + this._register(this._config.onConfigChanged(() => { + style.onUpdate(this._config.config.localEchoStyle); + this._typeaheadThreshold = this._config.config.localEchoLatencyThreshold; + this._excludeProgramRe = compileExcludeRegexp(this._config.config.localEchoExcludePrograms); + this._reevaluatePredictorState(stats, timeline); })); - this._register(this.timeline.onPredictionSucceeded(p => { - if (this.lastRow?.charState === CharPredictState.HasPendingChar && isTenativeCharacterPrediction(p) && p.inner.appliedAt) { - if (p.inner.appliedAt.pos.y + p.inner.appliedAt.pos.baseY === this.lastRow.y) { - this.lastRow.charState = CharPredictState.Validated; + this._register(this._timeline.onPredictionSucceeded(p => { + if (this._lastRow?.charState === CharPredictState.HasPendingChar && isTenativeCharacterPrediction(p) && p.inner.appliedAt) { + if (p.inner.appliedAt.pos.y + p.inner.appliedAt.pos.baseY === this._lastRow.y) { + this._lastRow.charState = CharPredictState.Validated; } } })); - this._register(this.processManager.onBeforeProcessData(e => this.onBeforeProcessData(e))); + this._register(this._processManager.onBeforeProcessData(e => this._onBeforeProcessData(e))); let nextStatsSend: any; this._register(stats.onChange(() => { if (!nextStatsSend) { nextStatsSend = setTimeout(() => { - this.sendLatencyStats(stats); + this._sendLatencyStats(stats); nextStatsSend = undefined; }, statsSendTelemetryEvery); } @@ -1333,30 +1339,30 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { style.debounceStopTracking(); } - this.reevaluatePredictorState(stats, timeline); + this._reevaluatePredictorState(stats, timeline); })); } - public reset() { - this.lastRow = undefined; + reset() { + this._lastRow = undefined; } - private deferClearingPredictions() { - if (!this.stats || !this.timeline) { + private _deferClearingPredictions() { + if (!this.stats || !this._timeline) { return; } - this.clearPredictionDebounce?.dispose(); - if (this.timeline.length === 0 || this.timeline.peekStart()?.clearAfterTimeout === false) { - this.clearPredictionDebounce = undefined; + this._clearPredictionDebounce?.dispose(); + if (this._timeline.length === 0 || this._timeline.peekStart()?.clearAfterTimeout === false) { + this._clearPredictionDebounce = undefined; return; } - this.clearPredictionDebounce = disposableTimeout( + this._clearPredictionDebounce = disposableTimeout( () => { - this.timeline?.undoAllPredictions(); - if (this.lastRow?.charState === CharPredictState.HasPendingChar) { - this.lastRow.charState = CharPredictState.Unknown; + this._timeline?.undoAllPredictions(); + if (this._lastRow?.charState === CharPredictState.HasPendingChar) { + this._lastRow.charState = CharPredictState.Unknown; } }, Math.max(500, this.stats.maxLatency * 3 / 2), @@ -1371,28 +1377,28 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { * terminal cursor is not updated, causes issues. */ @debounce(100) - protected reevaluatePredictorState(stats: PredictionStats, timeline: PredictionTimeline) { - this.reevaluatePredictorStateNow(stats, timeline); + protected _reevaluatePredictorState(stats: PredictionStats, timeline: PredictionTimeline) { + this._reevaluatePredictorStateNow(stats, timeline); } - protected reevaluatePredictorStateNow(stats: PredictionStats, timeline: PredictionTimeline) { - if (this.excludeProgramRe.test(this.terminalTitle)) { + protected _reevaluatePredictorStateNow(stats: PredictionStats, timeline: PredictionTimeline) { + if (this._excludeProgramRe.test(this._terminalTitle)) { timeline.setShowPredictions(false); - } else if (this.typeaheadThreshold < 0) { + } else if (this._typeaheadThreshold < 0) { timeline.setShowPredictions(false); - } else if (this.typeaheadThreshold === 0) { + } else if (this._typeaheadThreshold === 0) { timeline.setShowPredictions(true); } else if (stats.sampleSize > statsMinSamplesToTurnOn && stats.accuracy > statsMinAccuracyToTurnOn) { const latency = stats.latency.median; - if (latency >= this.typeaheadThreshold) { + if (latency >= this._typeaheadThreshold) { timeline.setShowPredictions(true); - } else if (latency < this.typeaheadThreshold / statsToggleOffThreshold) { + } else if (latency < this._typeaheadThreshold / statsToggleOffThreshold) { timeline.setShowPredictions(false); } } } - private sendLatencyStats(stats: PredictionStats) { + private _sendLatencyStats(stats: PredictionStats) { /* __GDPR__ "terminalLatencyStats" : { "min" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true }, @@ -1402,20 +1408,20 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { "predictionAccuracy" : { "classification": "SystemMetaData", "purpose": "PerformanceAndHealth", "isMeasurement": true } } */ - this.telemetryService.publicLog('terminalLatencyStats', { + this._telemetryService.publicLog('terminalLatencyStats', { ...stats.latency, predictionAccuracy: stats.accuracy, }); } - private onUserData(data: string): void { - if (this.timeline?.terminal.buffer.active.type !== 'normal') { + private _onUserData(data: string): void { + if (this._timeline?.terminal.buffer.active.type !== 'normal') { return; } // console.log('user data:', JSON.stringify(data)); - const terminal = this.timeline.terminal; + const terminal = this._timeline.terminal; const buffer = terminal.buffer.active; // Detect programs like git log/less that use the normal buffer but don't @@ -1430,44 +1436,44 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { // arrow or backspace-into the prompt. Record the lowest X value at which // the user gave input, and mark all additions before that as tentative. const actualY = buffer.baseY + buffer.cursorY; - if (actualY !== this.lastRow?.y) { - this.lastRow = { y: actualY, startingX: buffer.cursorX, endingX: buffer.cursorX, charState: CharPredictState.Unknown }; + if (actualY !== this._lastRow?.y) { + this._lastRow = { y: actualY, startingX: buffer.cursorX, endingX: buffer.cursorX, charState: CharPredictState.Unknown }; } else { - this.lastRow.startingX = Math.min(this.lastRow.startingX, buffer.cursorX); - this.lastRow.endingX = Math.max(this.lastRow.endingX, this.timeline.physicalCursor(buffer).x); + this._lastRow.startingX = Math.min(this._lastRow.startingX, buffer.cursorX); + this._lastRow.endingX = Math.max(this._lastRow.endingX, this._timeline.physicalCursor(buffer).x); } const addLeftNavigating = (p: IPrediction) => - this.timeline!.tentativeCursor(buffer).x <= this.lastRow!.startingX - ? this.timeline!.addBoundary(buffer, p) - : this.timeline!.addPrediction(buffer, p); + this._timeline!.tentativeCursor(buffer).x <= this._lastRow!.startingX + ? this._timeline!.addBoundary(buffer, p) + : this._timeline!.addPrediction(buffer, p); const addRightNavigating = (p: IPrediction) => - this.timeline!.tentativeCursor(buffer).x >= this.lastRow!.endingX - 1 - ? this.timeline!.addBoundary(buffer, p) - : this.timeline!.addPrediction(buffer, p); + this._timeline!.tentativeCursor(buffer).x >= this._lastRow!.endingX - 1 + ? this._timeline!.addBoundary(buffer, p) + : this._timeline!.addPrediction(buffer, p); /** @see https://github.com/xtermjs/xterm.js/blob/1913e9512c048e3cf56bb5f5df51bfff6899c184/src/common/input/Keyboard.ts */ const reader = new StringReader(data); while (reader.remaining > 0) { if (reader.eatCharCode(127)) { // backspace - const previous = this.timeline.peekEnd(); + const previous = this._timeline.peekEnd(); if (previous && previous instanceof CharacterPrediction) { - this.timeline.addBoundary(); + this._timeline.addBoundary(); } // backspace must be able to read the previously-written character in // the event that it needs to undo it - if (this.timeline.isShowingPredictions) { - flushOutput(this.timeline.terminal); + if (this._timeline.isShowingPredictions) { + flushOutput(this._timeline.terminal); } - if (this.timeline.tentativeCursor(buffer).x <= this.lastRow!.startingX) { - this.timeline.addBoundary(buffer, new BackspacePrediction(this.timeline.terminal)); + if (this._timeline.tentativeCursor(buffer).x <= this._lastRow!.startingX) { + this._timeline.addBoundary(buffer, new BackspacePrediction(this._timeline.terminal)); } else { // Backspace decrements our ability to go right. - this.lastRow.endingX--; - this.timeline!.addPrediction(buffer, new BackspacePrediction(this.timeline.terminal)); + this._lastRow.endingX--; + this._timeline!.addPrediction(buffer, new BackspacePrediction(this._timeline.terminal)); } continue; @@ -1475,16 +1481,16 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { if (reader.eatCharCode(32, 126)) { // alphanum const char = data[reader.index - 1]; - const prediction = new CharacterPrediction(this.typeaheadStyle!, char); - if (this.lastRow.charState === CharPredictState.Unknown) { - this.timeline.addBoundary(buffer, prediction); - this.lastRow.charState = CharPredictState.HasPendingChar; + const prediction = new CharacterPrediction(this._typeaheadStyle!, char); + if (this._lastRow.charState === CharPredictState.Unknown) { + this._timeline.addBoundary(buffer, prediction); + this._lastRow.charState = CharPredictState.HasPendingChar; } else { - this.timeline.addPrediction(buffer, prediction); + this._timeline.addPrediction(buffer, prediction); } - if (this.timeline.tentativeCursor(buffer).x >= terminal.cols) { - this.timeline.addBoundary(buffer, new LinewrapPrediction()); + if (this._timeline.tentativeCursor(buffer).x >= terminal.cols) { + this._timeline.addBoundary(buffer, new LinewrapPrediction()); } continue; } @@ -1512,30 +1518,30 @@ export class TypeAheadAddon extends Disposable implements ITerminalAddon { } if (reader.eatChar('\r') && buffer.cursorY < terminal.rows - 1) { - this.timeline.addPrediction(buffer, new NewlinePrediction()); + this._timeline.addPrediction(buffer, new NewlinePrediction()); continue; } // something else - this.timeline.addBoundary(buffer, new HardBoundary()); + this._timeline.addBoundary(buffer, new HardBoundary()); break; } - if (this.timeline.length === 1) { - this.deferClearingPredictions(); - this.typeaheadStyle!.startTracking(); + if (this._timeline.length === 1) { + this._deferClearingPredictions(); + this._typeaheadStyle!.startTracking(); } } - private onBeforeProcessData(event: IBeforeProcessDataEvent): void { - if (!this.timeline) { + private _onBeforeProcessData(event: IBeforeProcessDataEvent): void { + if (!this._timeline) { return; } // console.log('incoming data:', JSON.stringify(event.data)); - event.data = this.timeline.beforeServerInput(event.data); + event.data = this._timeline.beforeServerInput(event.data); // console.log('emitted data:', JSON.stringify(event.data)); - this.deferClearingPredictions(); + this._deferClearingPredictions(); } } diff --git a/src/vs/workbench/contrib/terminal/browser/terminalView.ts b/src/vs/workbench/contrib/terminal/browser/terminalView.ts index aa4cdd7ed50..df15b8c1cc9 100644 --- a/src/vs/workbench/contrib/terminal/browser/terminalView.ts +++ b/src/vs/workbench/contrib/terminal/browser/terminalView.ts @@ -21,7 +21,7 @@ import { IViewDescriptorService } from 'vs/workbench/common/views'; import { IOpenerService } from 'vs/platform/opener/common/opener'; import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND } from 'vs/workbench/common/theme'; import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions'; -import { ITerminalProfile, TERMINAL_COMMAND_ID, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProfile, TerminalCommandId, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import { ActionViewItem, SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems'; import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints'; import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler'; @@ -44,7 +44,7 @@ export class TerminalViewPane extends ViewPane { private _parentDomElement: HTMLElement | undefined; private _tabsViewWrapper: HTMLElement | undefined; private _terminalTabbedView?: TerminalTabbedView; - public get terminalTabbedView(): TerminalTabbedView | undefined { return this._terminalTabbedView; } + get terminalTabbedView(): TerminalTabbedView | undefined { return this._terminalTabbedView; } private _terminalsInitialized = false; private _bodyDimensions: { width: number, height: number } = { width: 0, height: 0 }; private _isWelcomeShowing: boolean = false; @@ -95,7 +95,7 @@ export class TerminalViewPane extends ViewPane { this._register(this._terminalService.onDidChangeAvailableProfiles(profiles => this._updateTabActionBar(profiles))); } - public override renderBody(container: HTMLElement): void { + override renderBody(container: HTMLElement): void { super.renderBody(container); this._parentDomElement = container; @@ -109,12 +109,12 @@ export class TerminalViewPane extends ViewPane { this._parentDomElement.appendChild(this._fontStyleElement); this._register(this.configurationService.onDidChangeConfiguration(e => { - if (e.affectsConfiguration(TERMINAL_SETTING_ID.FontFamily) || e.affectsConfiguration('editor.fontFamily')) { + if (e.affectsConfiguration(TerminalSettingId.FontFamily) || e.affectsConfiguration('editor.fontFamily')) { const configHelper = this._terminalService.configHelper; if (!configHelper.configFontIsMonospace()) { const choices: IPromptChoice[] = [{ label: nls.localize('terminal.useMonospace', "Use 'monospace'"), - run: () => this.configurationService.updateValue(TERMINAL_SETTING_ID.FontFamily, 'monospace'), + run: () => this.configurationService.updateValue(TerminalSettingId.FontFamily, 'monospace'), }]; this._notificationService.prompt(Severity.Warning, nls.localize('terminal.monospaceOnly', "The terminal only supports monospace fonts. Be sure to restart VS Code if this is a newly installed font."), choices); } @@ -123,7 +123,7 @@ export class TerminalViewPane extends ViewPane { this._register(this.onDidChangeBodyVisibility(visible => { if (visible) { - const hadTerminals = !!this._terminalService.terminalTabs.length; + const hadTerminals = !!this._terminalService.terminalGroups.length; if (this._terminalService.isProcessSupportRegistered) { if (this._terminalsInitialized) { if (!hadTerminals) { @@ -136,14 +136,14 @@ export class TerminalViewPane extends ViewPane { } if (hadTerminals) { - this._terminalService.getActiveTab()?.setVisible(visible); + this._terminalService.getActiveGroup()?.setVisible(visible); } else { // TODO@Tyriar - this call seems unnecessary this.layoutBody(this._bodyDimensions.height, this._bodyDimensions.width); } this._terminalService.showPanel(true); } else { - this._terminalService.getActiveTab()?.setVisible(false); + this._terminalService.getActiveGroup()?.setVisible(false); } })); this.layoutBody(this._parentDomElement.offsetHeight, this._parentDomElement.offsetWidth); @@ -159,6 +159,7 @@ export class TerminalViewPane extends ViewPane { this._parentDomElement.append(this._tabsViewWrapper); } + // eslint-disable-next-line @typescript-eslint/naming-convention protected override layoutBody(height: number, width: number): void { super.layoutBody(height, width); @@ -170,17 +171,17 @@ export class TerminalViewPane extends ViewPane { } } - public override getActionViewItem(action: Action): IActionViewItem | undefined { + override getActionViewItem(action: Action): IActionViewItem | undefined { switch (action.id) { - case TERMINAL_COMMAND_ID.SWITCH_TERMINAL: { + case TerminalCommandId.SwitchTerminal: { return this._instantiationService.createInstance(SwitchTerminalActionViewItem, action); } - case TERMINAL_COMMAND_ID.FOCUS: { + case TerminalCommandId.Focus: { const actions: IAction[] = []; createAndFillInContextMenuActions(this._singleTabMenu, undefined, actions); return this._instantiationService.createInstance(SingleTerminalTabActionViewItem, action, actions); } - case TERMINAL_COMMAND_ID.CREATE_WITH_PROFILE_BUTTON: { + case TerminalCommandId.CreateWithProfileButton: { if (this._tabButtons) { this._tabButtons.dispose(); } @@ -209,8 +210,8 @@ export class TerminalViewPane extends ViewPane { const submenuActions: IAction[] = []; for (const p of profiles) { - dropdownActions.push(new MenuItemAction({ id: TERMINAL_COMMAND_ID.NEW_WITH_PROFILE, title: p.profileName, category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService)); - submenuActions.push(new MenuItemAction({ id: TERMINAL_COMMAND_ID.SPLIT, title: p.profileName, category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService)); + dropdownActions.push(new MenuItemAction({ id: TerminalCommandId.NewWithProfile, title: p.profileName, category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService)); + submenuActions.push(new MenuItemAction({ id: TerminalCommandId.Split, title: p.profileName, category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService)); } for (const contributed of this._terminalContributionService.terminalTypes) { @@ -231,12 +232,12 @@ export class TerminalViewPane extends ViewPane { } } - const primaryAction = this._instantiationService.createInstance(MenuItemAction, { id: TERMINAL_COMMAND_ID.NEW, title: nls.localize('terminal.new', "New Terminal"), icon: Codicon.plus }, undefined, undefined); + const primaryAction = this._instantiationService.createInstance(MenuItemAction, { id: TerminalCommandId.New, title: nls.localize('terminal.new', "New Terminal"), icon: Codicon.plus }, undefined, undefined); const dropdownAction = new Action('refresh profiles', 'Launch Profile...', 'codicon-chevron-down', true); return { primaryAction, dropdownAction, dropdownMenuActions: dropdownActions, className: 'terminal-tab-actions' }; } - public override focus() { + override focus() { if (this._terminalService.connectionState === TerminalConnectionState.Connecting) { // If the terminal is waiting to reconnect to remote terminals, then there is no TerminalInstance yet that can // be focused. So wait for connection to finish, then focus. diff --git a/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts b/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts index f843f08e0ad..af556051eee 100644 --- a/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts +++ b/src/vs/workbench/contrib/terminal/browser/widgets/environmentVariableInfoWidget.ts @@ -43,7 +43,7 @@ export class EnvironmentVariableInfoWidget extends Widget implements ITerminalWi const scheduler: RunOnceScheduler = new RunOnceScheduler(() => this._showHover(), this._configurationService.getValue('workbench.hover.delay')); this._register(scheduler); - let origin = { x: 0, y: 0 }; + const origin = { x: 0, y: 0 }; this.onmouseover(this._domNode, e => { origin.x = e.browserEvent.pageX; diff --git a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts index 18f14f062ad..bdba2cba32b 100644 --- a/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts +++ b/src/vs/workbench/contrib/terminal/common/remoteTerminalChannel.ts @@ -37,7 +37,6 @@ export interface ICompleteTerminalConfiguration { 'terminal.integrated.env.windows': ITerminalEnvironment; 'terminal.integrated.env.osx': ITerminalEnvironment; 'terminal.integrated.env.linux': ITerminalEnvironment; - 'terminal.integrated.inheritEnv': boolean; 'terminal.integrated.cwd': string; 'terminal.integrated.detectLocale': 'auto' | 'off' | 'on'; } @@ -73,46 +72,46 @@ export interface ICreateTerminalProcessResult { export class RemoteTerminalChannelClient { - public get onPtyHostExit(): Event { + get onPtyHostExit(): Event { return this._channel.listen('$onPtyHostExitEvent'); } - public get onPtyHostStart(): Event { + get onPtyHostStart(): Event { return this._channel.listen('$onPtyHostStartEvent'); } - public get onPtyHostUnresponsive(): Event { + get onPtyHostUnresponsive(): Event { return this._channel.listen('$onPtyHostUnresponsiveEvent'); } - public get onPtyHostResponsive(): Event { + get onPtyHostResponsive(): Event { return this._channel.listen('$onPtyHostResponsiveEvent'); } - public get onProcessData(): Event<{ id: number, event: IProcessDataEvent | string }> { + get onProcessData(): Event<{ id: number, event: IProcessDataEvent | string }> { return this._channel.listen<{ id: number, event: IProcessDataEvent | string }>('$onProcessDataEvent'); } - public get onProcessExit(): Event<{ id: number, event: number | undefined }> { + get onProcessExit(): Event<{ id: number, event: number | undefined }> { return this._channel.listen<{ id: number, event: number | undefined }>('$onProcessExitEvent'); } - public get onProcessReady(): Event<{ id: number, event: { pid: number, cwd: string } }> { + get onProcessReady(): Event<{ id: number, event: { pid: number, cwd: string } }> { return this._channel.listen<{ id: number, event: { pid: number, cwd: string } }>('$onProcessReadyEvent'); } - public get onProcessReplay(): Event<{ id: number, event: IPtyHostProcessReplayEvent }> { + get onProcessReplay(): Event<{ id: number, event: IPtyHostProcessReplayEvent }> { return this._channel.listen<{ id: number, event: IPtyHostProcessReplayEvent }>('$onProcessReplayEvent'); } - public get onProcessTitleChanged(): Event<{ id: number, event: string }> { + get onProcessTitleChanged(): Event<{ id: number, event: string }> { return this._channel.listen<{ id: number, event: string }>('$onProcessTitleChangedEvent'); } - public get onProcessShellTypeChanged(): Event<{ id: number, event: TerminalShellType | undefined }> { + get onProcessShellTypeChanged(): Event<{ id: number, event: TerminalShellType | undefined }> { return this._channel.listen<{ id: number, event: TerminalShellType | undefined }>('$onProcessShellTypeChangedEvent'); } - public get onProcessOverrideDimensions(): Event<{ id: number, event: ITerminalDimensionsOverride | undefined }> { + get onProcessOverrideDimensions(): Event<{ id: number, event: ITerminalDimensionsOverride | undefined }> { return this._channel.listen<{ id: number, event: ITerminalDimensionsOverride | undefined }>('$onProcessOverrideDimensionsEvent'); } - public get onProcessResolvedShellLaunchConfig(): Event<{ id: number, event: IShellLaunchConfig }> { + get onProcessResolvedShellLaunchConfig(): Event<{ id: number, event: IShellLaunchConfig }> { return this._channel.listen<{ id: number, event: IShellLaunchConfig }>('$onProcessResolvedShellLaunchConfigEvent'); } - public get onProcessOrphanQuestion(): Event<{ id: number }> { + get onProcessOrphanQuestion(): Event<{ id: number }> { return this._channel.listen<{ id: number }>('$onProcessOrphanQuestion'); } - public get onExecuteCommand(): Event<{ reqId: number, commandId: string, commandArgs: any[] }> { + get onExecuteCommand(): Event<{ reqId: number, commandId: string, commandArgs: any[] }> { return this._channel.listen<{ reqId: number, commandId: string, commandArgs: any[] }>('$onExecuteCommand'); } @@ -133,7 +132,7 @@ export class RemoteTerminalChannelClient { return this._channel.call('$restartPtyHost', []); } - public async createProcess(shellLaunchConfig: IShellLaunchConfigDto, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, shouldPersistTerminal: boolean, cols: number, rows: number): Promise { + async createProcess(shellLaunchConfig: IShellLaunchConfigDto, configuration: ICompleteTerminalConfiguration, activeWorkspaceRootUri: URI | undefined, shouldPersistTerminal: boolean, cols: number, rows: number): Promise { // Be sure to first wait for the remote configuration await this._configurationService.whenRemoteConfigurationLoaded(); @@ -193,55 +192,59 @@ export class RemoteTerminalChannelClient { return await this._channel.call('$createProcess', args); } - public attachToProcess(id: number): Promise { + attachToProcess(id: number): Promise { return this._channel.call('$attachToProcess', [id]); } - public listProcesses(): Promise { + listProcesses(): Promise { return this._channel.call('$listProcesses'); } - public reduceConnectionGraceTime(): Promise { + reduceConnectionGraceTime(): Promise { return this._channel.call('$reduceConnectionGraceTime'); } - public processBinary(id: number, data: string): Promise { + processBinary(id: number, data: string): Promise { return this._channel.call('$processBinary', [id, data]); } - public start(id: number): Promise { + start(id: number): Promise { return this._channel.call('$start', [id]); } - public input(id: number, data: string): Promise { + input(id: number, data: string): Promise { return this._channel.call('$input', [id, data]); } - public acknowledgeDataEvent(id: number, charCount: number): Promise { + acknowledgeDataEvent(id: number, charCount: number): Promise { return this._channel.call('$acknowledgeDataEvent', [id, charCount]); } - public shutdown(id: number, immediate: boolean): Promise { + shutdown(id: number, immediate: boolean): Promise { return this._channel.call('$shutdown', [id, immediate]); } - public resize(id: number, cols: number, rows: number): Promise { + resize(id: number, cols: number, rows: number): Promise { return this._channel.call('$resize', [id, cols, rows]); } - public getInitialCwd(id: number): Promise { + getInitialCwd(id: number): Promise { return this._channel.call('$getInitialCwd', [id]); } - public getCwd(id: number): Promise { + getCwd(id: number): Promise { return this._channel.call('$getCwd', [id]); } - public orphanQuestionReply(id: number): Promise { + orphanQuestionReply(id: number): Promise { return this._channel.call('$orphanQuestionReply', [id]); } - public sendCommandResult(reqId: number, isError: boolean, payload: any): Promise { + sendCommandResult(reqId: number, isError: boolean, payload: any): Promise { return this._channel.call('$sendCommandResult', [reqId, isError, payload]); } - public getDefaultSystemShell(osOverride?: OperatingSystem): Promise { + getDefaultSystemShell(osOverride?: OperatingSystem): Promise { return this._channel.call('$getDefaultSystemShell', [osOverride]); } - public getShellEnvironment(): Promise { - return this._channel.call('$getShellEnvironment'); + getEnvironment(): Promise { + return this._channel.call('$getEnvironment'); } - public setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { + getWslPath(original: string): Promise { + return this._channel.call('$getWslPath', [original]); + } + + setTerminalLayoutInfo(layout: ITerminalsLayoutInfoById): Promise { const workspace = this._workspaceContextService.getWorkspace(); const args: ISetTerminalLayoutInfoArgs = { workspaceId: workspace.id, @@ -250,7 +253,7 @@ export class RemoteTerminalChannelClient { return this._channel.call('$setTerminalLayoutInfo', args); } - public getTerminalLayoutInfo(): Promise { + getTerminalLayoutInfo(): Promise { const workspace = this._workspaceContextService.getWorkspace(); const args: IGetTerminalLayoutInfoArgs = { workspaceId: workspace.id, diff --git a/src/vs/workbench/contrib/terminal/common/terminal.ts b/src/vs/workbench/contrib/terminal/common/terminal.ts index 2e45ff88b8a..5096d74604e 100644 --- a/src/vs/workbench/contrib/terminal/common/terminal.ts +++ b/src/vs/workbench/contrib/terminal/common/terminal.ts @@ -99,7 +99,7 @@ export interface ITerminalProfileResolverService { getDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise; getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise; getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise; - getShellEnvironment(remoteAuthority: string | undefined): Promise; + getEnvironment(remoteAuthority: string | undefined): Promise; // TODO: Remove when workspace trust is enabled getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined; @@ -171,7 +171,6 @@ export interface ITerminalConfiguration { cwd: string; confirmOnExit: boolean; enableBell: boolean; - inheritEnv: boolean; env: { linux: { [key: string]: string }; osx: { [key: string]: string }; @@ -232,21 +231,6 @@ export interface IRemoteTerminalAttachTarget { icon: string | undefined; } -/** - * Provides access to native Windows calls that can be injected into non-native layers. - */ -export interface ITerminalNativeWindowsDelegate { - /** - * Gets the Windows build number, eg. this would be `19041` for Windows 10 version 2004 - */ - getWindowsBuildNumber(): number; - /** - * Converts a regular Windows path into the WSL path equivalent, eg. `C:\` -> `/mnt/c` - * @param path The Windows path. - */ - getWslPath(path: string): Promise; -} - export interface ICommandTracker { scrollToPreviousCommand(): void; scrollToNextCommand(): void; @@ -359,21 +343,21 @@ export interface ITerminalProcessManager extends IDisposable { export const enum ProcessState { // The process has not been initialized yet. - UNINITIALIZED, + Uninitialized, // The process is currently launching, the process is marked as launching // for a short duration after being created and is helpful to indicate // whether the process died as a result of bad shell and args. - LAUNCHING, + Launching, // The process is running normally. - RUNNING, + Running, // The process was killed during launch, likely as a result of bad shell and // args. - KILLED_DURING_LAUNCH, + KilledDuringLaunch, // The process was killed by the user (the event originated from VS Code). - KILLED_BY_USER, + KilledByUser, // The process was killed by itself, for example the shell crashed or `exit` // was run. - KILLED_BY_PROCESS + KilledByProcess } export interface ITerminalProcessExtHostProxy extends IDisposable { @@ -411,12 +395,6 @@ export interface IDefaultShellAndArgsRequest { callback: (shell: string, args: string[] | string | undefined) => void; } -export enum LinuxDistro { - Fedora, - Ubuntu, - Unknown -} - export enum TitleEventSource { /** From the API or the rename command that overrides any other type */ Api, @@ -428,7 +406,7 @@ export enum TitleEventSource { export const QUICK_LAUNCH_PROFILE_CHOICE = 'workbench.action.terminal.profile.choice'; -export const enum TERMINAL_SETTING_ID { +export const enum TerminalSettingId { ShellLinux = 'terminal.integrated.shell.linux', ShellMacOs = 'terminal.integrated.shell.osx', ShellWindows = 'terminal.integrated.shell.windows', @@ -479,7 +457,6 @@ export const enum TERMINAL_SETTING_ID { CommandsToSkipShell = 'terminal.integrated.commandsToSkipShell', AllowChords = 'terminal.integrated.allowChords', AllowMnemonics = 'terminal.integrated.allowMnemonics', - InheritEnv = 'terminal.integrated.inheritEnv', EnvMacOs = 'terminal.integrated.env.osx', EnvLinux = 'terminal.integrated.env.linux', EnvWindows = 'terminal.integrated.env.windows', @@ -500,135 +477,135 @@ export const enum TERMINAL_SETTING_ID { AllowWorkspaceConfiguration = 'terminal.integrated.allowWorkspaceConfiguration' } -export const enum TERMINAL_COMMAND_ID { - FIND_NEXT = 'workbench.action.terminal.findNext', - FIND_PREVIOUS = 'workbench.action.terminal.findPrevious', - TOGGLE = 'workbench.action.terminal.toggleTerminal', - KILL = 'workbench.action.terminal.kill', - KILL_INSTANCE = 'workbench.action.terminal.killInstance', - QUICK_KILL = 'workbench.action.terminal.quickKill', - CONFIGURE_TERMINAL_SETTINGS = 'workbench.action.terminal.openSettings', - COPY_SELECTION = 'workbench.action.terminal.copySelection', - SELECT_ALL = 'workbench.action.terminal.selectAll', - DELETE_WORD_LEFT = 'workbench.action.terminal.deleteWordLeft', - DELETE_WORD_RIGHT = 'workbench.action.terminal.deleteWordRight', - DELETE_TO_LINE_START = 'workbench.action.terminal.deleteToLineStart', - MOVE_TO_LINE_START = 'workbench.action.terminal.moveToLineStart', - MOVE_TO_LINE_END = 'workbench.action.terminal.moveToLineEnd', - NEW = 'workbench.action.terminal.new', - NEW_WITH_CWD = 'workbench.action.terminal.newWithCwd', - NEW_LOCAL = 'workbench.action.terminal.newLocal', - NEW_IN_ACTIVE_WORKSPACE = 'workbench.action.terminal.newInActiveWorkspace', - NEW_WITH_PROFILE = 'workbench.action.terminal.newWithProfile', - SPLIT = 'workbench.action.terminal.split', - SPLIT_INSTANCE = 'workbench.action.terminal.splitInstance', - SPLIT_IN_ACTIVE_WORKSPACE = 'workbench.action.terminal.splitInActiveWorkspace', - RELAUNCH = 'workbench.action.terminal.relaunch', - FOCUS_PREVIOUS_PANE = 'workbench.action.terminal.focusPreviousPane', - SHOW_TABS = 'workbench.action.terminal.showTabs', - FOCUS_TABS = 'workbench.action.terminal.focusTabs', - FOCUS_NEXT_PANE = 'workbench.action.terminal.focusNextPane', - RESIZE_PANE_LEFT = 'workbench.action.terminal.resizePaneLeft', - RESIZE_PANE_RIGHT = 'workbench.action.terminal.resizePaneRight', - RESIZE_PANE_UP = 'workbench.action.terminal.resizePaneUp', - CREATE_WITH_PROFILE_BUTTON = 'workbench.action.terminal.createProfileButton', - RESIZE_PANE_DOWN = 'workbench.action.terminal.resizePaneDown', - FOCUS = 'workbench.action.terminal.focus', - FOCUS_NEXT = 'workbench.action.terminal.focusNext', - FOCUS_PREVIOUS = 'workbench.action.terminal.focusPrevious', - PASTE = 'workbench.action.terminal.paste', - PASTE_SELECTION = 'workbench.action.terminal.pasteSelection', - SELECT_DEFAULT_PROFILE = 'workbench.action.terminal.selectDefaultShell', - RUN_SELECTED_TEXT = 'workbench.action.terminal.runSelectedText', - RUN_ACTIVE_FILE = 'workbench.action.terminal.runActiveFile', - SWITCH_TERMINAL = 'workbench.action.terminal.switchTerminal', - SCROLL_DOWN_LINE = 'workbench.action.terminal.scrollDown', - SCROLL_DOWN_PAGE = 'workbench.action.terminal.scrollDownPage', - SCROLL_TO_BOTTOM = 'workbench.action.terminal.scrollToBottom', - SCROLL_UP_LINE = 'workbench.action.terminal.scrollUp', - SCROLL_UP_PAGE = 'workbench.action.terminal.scrollUpPage', - SCROLL_TO_TOP = 'workbench.action.terminal.scrollToTop', - CLEAR = 'workbench.action.terminal.clear', - CLEAR_SELECTION = 'workbench.action.terminal.clearSelection', - CHANGE_ICON = 'workbench.action.terminal.changeIcon', - CHANGE_ICON_INSTANCE = 'workbench.action.terminal.changeIconInstance', - RENAME = 'workbench.action.terminal.rename', - RENAME_INSTANCE = 'workbench.action.terminal.renameInstance', - RENAME_WITH_ARG = 'workbench.action.terminal.renameWithArg', - FIND_FOCUS = 'workbench.action.terminal.focusFind', - FIND_HIDE = 'workbench.action.terminal.hideFind', - QUICK_OPEN_TERM = 'workbench.action.quickOpenTerm', - SCROLL_TO_PREVIOUS_COMMAND = 'workbench.action.terminal.scrollToPreviousCommand', - SCROLL_TO_NEXT_COMMAND = 'workbench.action.terminal.scrollToNextCommand', - SELECT_TO_PREVIOUS_COMMAND = 'workbench.action.terminal.selectToPreviousCommand', - SELECT_TO_NEXT_COMMAND = 'workbench.action.terminal.selectToNextCommand', - SELECT_TO_PREVIOUS_LINE = 'workbench.action.terminal.selectToPreviousLine', - SELECT_TO_NEXT_LINE = 'workbench.action.terminal.selectToNextLine', - TOGGLE_ESCAPE_SEQUENCE_LOGGING = 'toggleEscapeSequenceLogging', - SEND_SEQUENCE = 'workbench.action.terminal.sendSequence', - TOGGLE_FIND_REGEX = 'workbench.action.terminal.toggleFindRegex', - TOGGLE_FIND_WHOLE_WORD = 'workbench.action.terminal.toggleFindWholeWord', - TOGGLE_FIND_CASE_SENSITIVE = 'workbench.action.terminal.toggleFindCaseSensitive', - NAVIGATION_MODE_EXIT = 'workbench.action.terminal.navigationModeExit', - NAVIGATION_MODE_FOCUS_NEXT = 'workbench.action.terminal.navigationModeFocusNext', - NAVIGATION_MODE_FOCUS_PREVIOUS = 'workbench.action.terminal.navigationModeFocusPrevious', - SHOW_ENVIRONMENT_INFORMATION = 'workbench.action.terminal.showEnvironmentInformation', - SEARCH_WORKSPACE = 'workbench.action.terminal.searchWorkspace', - ATTACH_TO_REMOTE_TERMINAL = 'workbench.action.terminal.attachToSession' +export const enum TerminalCommandId { + FindNext = 'workbench.action.terminal.findNext', + FindPrevious = 'workbench.action.terminal.findPrevious', + Toggle = 'workbench.action.terminal.toggleTerminal', + Kill = 'workbench.action.terminal.kill', + KillInstance = 'workbench.action.terminal.killInstance', + QuickKill = 'workbench.action.terminal.quickKill', + ConfigureTerminalSettings = 'workbench.action.terminal.openSettings', + CopySelection = 'workbench.action.terminal.copySelection', + SelectAll = 'workbench.action.terminal.selectAll', + DeleteWordLeft = 'workbench.action.terminal.deleteWordLeft', + DeleteWordRight = 'workbench.action.terminal.deleteWordRight', + DeleteToLineStart = 'workbench.action.terminal.deleteToLineStart', + MoveToLineStart = 'workbench.action.terminal.moveToLineStart', + MoveToLineEnd = 'workbench.action.terminal.moveToLineEnd', + New = 'workbench.action.terminal.new', + NewWithCwd = 'workbench.action.terminal.newWithCwd', + NewLocal = 'workbench.action.terminal.newLocal', + NewInActiveWorkspace = 'workbench.action.terminal.newInActiveWorkspace', + NewWithProfile = 'workbench.action.terminal.newWithProfile', + Split = 'workbench.action.terminal.split', + SplitInstance = 'workbench.action.terminal.splitInstance', + SplitInActiveWorkspace = 'workbench.action.terminal.splitInActiveWorkspace', + Relaunch = 'workbench.action.terminal.relaunch', + FocusPreviousPane = 'workbench.action.terminal.focusPreviousPane', + ShowTabs = 'workbench.action.terminal.showTabs', + FocusTabs = 'workbench.action.terminal.focusTabs', + FocusNextPane = 'workbench.action.terminal.focusNextPane', + ResizePaneLeft = 'workbench.action.terminal.resizePaneLeft', + ResizePaneRight = 'workbench.action.terminal.resizePaneRight', + ResizePaneUp = 'workbench.action.terminal.resizePaneUp', + CreateWithProfileButton = 'workbench.action.terminal.createProfileButton', + ResizePaneDown = 'workbench.action.terminal.resizePaneDown', + Focus = 'workbench.action.terminal.focus', + FocusNext = 'workbench.action.terminal.focusNext', + FocusPrevious = 'workbench.action.terminal.focusPrevious', + Paste = 'workbench.action.terminal.paste', + PasteSelection = 'workbench.action.terminal.pasteSelection', + SelectDefaultProfile = 'workbench.action.terminal.selectDefaultShell', + RunSelectedText = 'workbench.action.terminal.runSelectedText', + RunActiveFile = 'workbench.action.terminal.runActiveFile', + SwitchTerminal = 'workbench.action.terminal.switchTerminal', + ScrollDownLine = 'workbench.action.terminal.scrollDown', + ScrollDownPage = 'workbench.action.terminal.scrollDownPage', + ScrollToBottom = 'workbench.action.terminal.scrollToBottom', + ScrollUpLine = 'workbench.action.terminal.scrollUp', + ScrollUpPage = 'workbench.action.terminal.scrollUpPage', + ScrollToTop = 'workbench.action.terminal.scrollToTop', + Clear = 'workbench.action.terminal.clear', + ClearSelection = 'workbench.action.terminal.clearSelection', + ChangeIcon = 'workbench.action.terminal.changeIcon', + ChangeIconInstance = 'workbench.action.terminal.changeIconInstance', + Rename = 'workbench.action.terminal.rename', + RenameInstance = 'workbench.action.terminal.renameInstance', + RenameWithArgs = 'workbench.action.terminal.renameWithArg', + FindFocus = 'workbench.action.terminal.focusFind', + FindHide = 'workbench.action.terminal.hideFind', + QuickOpenTerm = 'workbench.action.quickOpenTerm', + ScrollToPreviousCommand = 'workbench.action.terminal.scrollToPreviousCommand', + ScrollToNextCommand = 'workbench.action.terminal.scrollToNextCommand', + SelectToPreviousCommand = 'workbench.action.terminal.selectToPreviousCommand', + SelectToNextCommand = 'workbench.action.terminal.selectToNextCommand', + SelectToPreviousLine = 'workbench.action.terminal.selectToPreviousLine', + SelectToNextLine = 'workbench.action.terminal.selectToNextLine', + ToggleEscapeSequenceLogging = 'toggleEscapeSequenceLogging', + SendSequence = 'workbench.action.terminal.sendSequence', + ToggleFindRegex = 'workbench.action.terminal.toggleFindRegex', + ToggleFindWholeWord = 'workbench.action.terminal.toggleFindWholeWord', + ToggleFindCaseSensitive = 'workbench.action.terminal.toggleFindCaseSensitive', + NavigationModeExit = 'workbench.action.terminal.navigationModeExit', + NavigationModeFocusNext = 'workbench.action.terminal.navigationModeFocusNext', + NavigationModeFocusPrevious = 'workbench.action.terminal.navigationModeFocusPrevious', + ShowEnvironmentInformation = 'workbench.action.terminal.showEnvironmentInformation', + SearchWorkspace = 'workbench.action.terminal.searchWorkspace', + AttachToRemoteTerminal = 'workbench.action.terminal.attachToSession' } export const DEFAULT_COMMANDS_TO_SKIP_SHELL: string[] = [ - TERMINAL_COMMAND_ID.CLEAR_SELECTION, - TERMINAL_COMMAND_ID.CLEAR, - TERMINAL_COMMAND_ID.COPY_SELECTION, - TERMINAL_COMMAND_ID.DELETE_TO_LINE_START, - TERMINAL_COMMAND_ID.DELETE_WORD_LEFT, - TERMINAL_COMMAND_ID.DELETE_WORD_RIGHT, - TERMINAL_COMMAND_ID.FIND_FOCUS, - TERMINAL_COMMAND_ID.FIND_HIDE, - TERMINAL_COMMAND_ID.FIND_NEXT, - TERMINAL_COMMAND_ID.FIND_PREVIOUS, - TERMINAL_COMMAND_ID.TOGGLE_FIND_REGEX, - TERMINAL_COMMAND_ID.TOGGLE_FIND_WHOLE_WORD, - TERMINAL_COMMAND_ID.TOGGLE_FIND_CASE_SENSITIVE, - TERMINAL_COMMAND_ID.FOCUS_NEXT_PANE, - TERMINAL_COMMAND_ID.FOCUS_NEXT, - TERMINAL_COMMAND_ID.FOCUS_PREVIOUS_PANE, - TERMINAL_COMMAND_ID.FOCUS_PREVIOUS, - TERMINAL_COMMAND_ID.FOCUS, - TERMINAL_COMMAND_ID.KILL, - TERMINAL_COMMAND_ID.MOVE_TO_LINE_END, - TERMINAL_COMMAND_ID.MOVE_TO_LINE_START, - TERMINAL_COMMAND_ID.NEW_IN_ACTIVE_WORKSPACE, - TERMINAL_COMMAND_ID.NEW, - TERMINAL_COMMAND_ID.PASTE, - TERMINAL_COMMAND_ID.PASTE_SELECTION, - TERMINAL_COMMAND_ID.RESIZE_PANE_DOWN, - TERMINAL_COMMAND_ID.RESIZE_PANE_LEFT, - TERMINAL_COMMAND_ID.RESIZE_PANE_RIGHT, - TERMINAL_COMMAND_ID.RESIZE_PANE_UP, - TERMINAL_COMMAND_ID.RUN_ACTIVE_FILE, - TERMINAL_COMMAND_ID.RUN_SELECTED_TEXT, - TERMINAL_COMMAND_ID.SCROLL_DOWN_LINE, - TERMINAL_COMMAND_ID.SCROLL_DOWN_PAGE, - TERMINAL_COMMAND_ID.SCROLL_TO_BOTTOM, - TERMINAL_COMMAND_ID.SCROLL_TO_NEXT_COMMAND, - TERMINAL_COMMAND_ID.SCROLL_TO_PREVIOUS_COMMAND, - TERMINAL_COMMAND_ID.SCROLL_TO_TOP, - TERMINAL_COMMAND_ID.SCROLL_UP_LINE, - TERMINAL_COMMAND_ID.SCROLL_UP_PAGE, - TERMINAL_COMMAND_ID.SEND_SEQUENCE, - TERMINAL_COMMAND_ID.SELECT_ALL, - TERMINAL_COMMAND_ID.SELECT_TO_NEXT_COMMAND, - TERMINAL_COMMAND_ID.SELECT_TO_NEXT_LINE, - TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_COMMAND, - TERMINAL_COMMAND_ID.SELECT_TO_PREVIOUS_LINE, - TERMINAL_COMMAND_ID.SPLIT_IN_ACTIVE_WORKSPACE, - TERMINAL_COMMAND_ID.SPLIT, - TERMINAL_COMMAND_ID.TOGGLE, - TERMINAL_COMMAND_ID.NAVIGATION_MODE_EXIT, - TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_NEXT, - TERMINAL_COMMAND_ID.NAVIGATION_MODE_FOCUS_PREVIOUS, + TerminalCommandId.ClearSelection, + TerminalCommandId.Clear, + TerminalCommandId.CopySelection, + TerminalCommandId.DeleteToLineStart, + TerminalCommandId.DeleteWordLeft, + TerminalCommandId.DeleteWordRight, + TerminalCommandId.FindFocus, + TerminalCommandId.FindHide, + TerminalCommandId.FindNext, + TerminalCommandId.FindPrevious, + TerminalCommandId.ToggleFindRegex, + TerminalCommandId.ToggleFindWholeWord, + TerminalCommandId.ToggleFindCaseSensitive, + TerminalCommandId.FocusNextPane, + TerminalCommandId.FocusNext, + TerminalCommandId.FocusPreviousPane, + TerminalCommandId.FocusPrevious, + TerminalCommandId.Focus, + TerminalCommandId.Kill, + TerminalCommandId.MoveToLineEnd, + TerminalCommandId.MoveToLineStart, + TerminalCommandId.NewInActiveWorkspace, + TerminalCommandId.New, + TerminalCommandId.Paste, + TerminalCommandId.PasteSelection, + TerminalCommandId.ResizePaneDown, + TerminalCommandId.ResizePaneLeft, + TerminalCommandId.ResizePaneRight, + TerminalCommandId.ResizePaneUp, + TerminalCommandId.RunActiveFile, + TerminalCommandId.RunSelectedText, + TerminalCommandId.ScrollDownLine, + TerminalCommandId.ScrollDownPage, + TerminalCommandId.ScrollToBottom, + TerminalCommandId.ScrollToNextCommand, + TerminalCommandId.ScrollToPreviousCommand, + TerminalCommandId.ScrollToTop, + TerminalCommandId.ScrollUpLine, + TerminalCommandId.ScrollUpPage, + TerminalCommandId.SendSequence, + TerminalCommandId.SelectAll, + TerminalCommandId.SelectToNextCommand, + TerminalCommandId.SelectToNextLine, + TerminalCommandId.SelectToPreviousCommand, + TerminalCommandId.SelectToPreviousLine, + TerminalCommandId.SplitInActiveWorkspace, + TerminalCommandId.Split, + TerminalCommandId.Toggle, + TerminalCommandId.NavigationModeExit, + TerminalCommandId.NavigationModeFocusNext, + TerminalCommandId.NavigationModeFocusPrevious, 'editor.action.toggleTabFocusMode', 'workbench.action.quickOpen', 'workbench.action.quickOpenPreviousEditor', diff --git a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts index 698defb35c9..1874578ab9d 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalConfiguration.ts @@ -6,8 +6,8 @@ import { ConfigurationScope, IConfigurationNode } from 'vs/platform/configuration/common/configurationRegistry'; import { localize } from 'vs/nls'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; -import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, DEFAULT_COMMANDS_TO_SKIP_SHELL, SUGGESTIONS_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_LOCAL_ECHO_EXCLUDE, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; -import { isMacintosh, isWindows, OperatingSystem } from 'vs/base/common/platform'; +import { DEFAULT_LETTER_SPACING, DEFAULT_LINE_HEIGHT, TerminalCursorStyle, DEFAULT_COMMANDS_TO_SKIP_SHELL, SUGGESTIONS_FONT_WEIGHT, MINIMUM_FONT_WEIGHT, MAXIMUM_FONT_WEIGHT, DEFAULT_LOCAL_ECHO_EXCLUDE, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; +import { isMacintosh, isWindows } from 'vs/base/common/platform'; import { IJSONSchema } from 'vs/base/common/jsonSchema'; const terminalProfileSchema: IJSONSchema = { @@ -53,12 +53,12 @@ export const terminalConfiguration: IConfigurationNode = { title: localize('terminalIntegratedConfigurationTitle', "Integrated Terminal"), type: 'object', properties: { - [TERMINAL_SETTING_ID.SendKeybindingsToShell]: { + [TerminalSettingId.SendKeybindingsToShell]: { markdownDescription: localize('terminal.integrated.sendKeybindingsToShell', "Dispatches most keybindings to the terminal instead of the workbench, overriding `#terminal.integrated.commandsToSkipShell#`, which can be used alternatively for fine tuning."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.AutomationShellLinux]: { + [TerminalSettingId.AutomationShellLinux]: { restricted: true, markdownDescription: localize({ key: 'terminal.integrated.automationShell.linux', @@ -67,7 +67,7 @@ export const terminalConfiguration: IConfigurationNode = { type: ['string', 'null'], default: null }, - [TERMINAL_SETTING_ID.AutomationShellMacOs]: { + [TerminalSettingId.AutomationShellMacOs]: { restricted: true, markdownDescription: localize({ key: 'terminal.integrated.automationShell.osx', @@ -76,7 +76,7 @@ export const terminalConfiguration: IConfigurationNode = { type: ['string', 'null'], default: null }, - [TERMINAL_SETTING_ID.AutomationShellWindows]: { + [TerminalSettingId.AutomationShellWindows]: { restricted: true, markdownDescription: localize({ key: 'terminal.integrated.automationShell.windows', @@ -85,7 +85,28 @@ export const terminalConfiguration: IConfigurationNode = { type: ['string', 'null'], default: null }, - [TERMINAL_SETTING_ID.ShellArgsLinux]: { + [TerminalSettingId.ShellLinux]: { + restricted: true, + markdownDescription: localize('terminal.integrated.shell.linux', "The path of the shell that the terminal uses on Linux. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + type: ['string', 'null'], + default: null, + markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.linux#` instead' + }, + [TerminalSettingId.ShellMacOs]: { + restricted: true, + markdownDescription: localize('terminal.integrated.shell.osx', "The path of the shell that the terminal uses on macOS. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + type: ['string', 'null'], + default: null, + markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.osx#` instead' + }, + [TerminalSettingId.ShellWindows]: { + restricted: true, + markdownDescription: localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), + type: ['string', 'null'], + default: null, + markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.windows#` instead' + }, + [TerminalSettingId.ShellArgsLinux]: { restricted: true, markdownDescription: localize('terminal.integrated.shellArgs.linux', "The command line arguments to use when on the Linux terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), type: 'array', @@ -95,7 +116,7 @@ export const terminalConfiguration: IConfigurationNode = { default: [], markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.linux#` instead' }, - [TERMINAL_SETTING_ID.ShellArgsMacOs]: { + [TerminalSettingId.ShellArgsMacOs]: { restricted: true, markdownDescription: localize('terminal.integrated.shellArgs.osx', "The command line arguments to use when on the macOS terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), type: 'array', @@ -108,7 +129,7 @@ export const terminalConfiguration: IConfigurationNode = { default: ['-l'], markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.osx#` instead' }, - [TERMINAL_SETTING_ID.ShellArgsWindows]: { + [TerminalSettingId.ShellArgsWindows]: { restricted: true, markdownDescription: localize('terminal.integrated.shellArgs.windows', "The command line arguments to use when on the Windows terminal. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), 'anyOf': [ @@ -127,7 +148,7 @@ export const terminalConfiguration: IConfigurationNode = { default: [], markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.windows#` instead' }, - [TERMINAL_SETTING_ID.ProfilesWindows]: { + [TerminalSettingId.ProfilesWindows]: { restricted: true, markdownDescription: localize( { @@ -187,7 +208,7 @@ export const terminalConfiguration: IConfigurationNode = { ] } }, - [TERMINAL_SETTING_ID.ProfilesMacOs]: { + [TerminalSettingId.ProfilesMacOs]: { restricted: true, markdownDescription: localize( { @@ -224,7 +245,7 @@ export const terminalConfiguration: IConfigurationNode = { ] } }, - [TERMINAL_SETTING_ID.ProfilesLinux]: { + [TerminalSettingId.ProfilesLinux]: { restricted: true, markdownDescription: localize( { @@ -260,35 +281,35 @@ export const terminalConfiguration: IConfigurationNode = { ] } }, - [TERMINAL_SETTING_ID.DefaultProfileLinux]: { + [TerminalSettingId.DefaultProfileLinux]: { description: localize('terminal.integrated.defaultProfile.linux', 'The default profile used on Linux. When set to a valid profile name, this will override the values of `terminal.integrated.shell.osx` and `terminal.integrated.shellArgs.osx`.'), type: ['string', 'null'], default: null, scope: ConfigurationScope.APPLICATION // Disallow setting the default in workspace settings }, - [TERMINAL_SETTING_ID.DefaultProfileMacOs]: { + [TerminalSettingId.DefaultProfileMacOs]: { description: localize('terminal.integrated.defaultProfile.osx', 'The default profile used on macOS. When set to a valid profile name, this will override the values of `terminal.integrated.shell.osx` and `terminal.integrated.shellArgs.osx`.'), type: ['string', 'null'], default: null, scope: ConfigurationScope.APPLICATION // Disallow setting the default in workspace settings }, - [TERMINAL_SETTING_ID.DefaultProfileWindows]: { + [TerminalSettingId.DefaultProfileWindows]: { description: localize('terminal.integrated.defaultProfile.windows', 'The default profile used on Windows. When set to a valid profile name, this will override the values of `terminal.integrated.shell.windows` and `terminal.integrated.shellArgs.windows`.'), type: ['string', 'null'], default: null, scope: ConfigurationScope.APPLICATION // Disallow setting the default in workspace settings }, - [TERMINAL_SETTING_ID.UseWslProfiles]: { + [TerminalSettingId.UseWslProfiles]: { description: localize('terminal.integrated.useWslProfiles', 'Controls whether or not WSL distros are shown in the terminal dropdown'), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.TabsEnabled]: { + [TerminalSettingId.TabsEnabled]: { description: localize('terminal.integrated.tabs.enabled', 'Controls whether terminal tabs display as a list to the side of the terminal. When this is disabled a dropdown will display instead.'), type: 'boolean', default: true, }, - [TERMINAL_SETTING_ID.TabsHideCondition]: { + [TerminalSettingId.TabsHideCondition]: { description: localize('terminal.integrated.tabs.hideCondition', 'Controls whether the terminal tabs view will hide under certain conditions.'), type: 'string', enum: ['never', 'singleTerminal'], @@ -298,7 +319,7 @@ export const terminalConfiguration: IConfigurationNode = { ], default: 'singleTerminal', }, - [TERMINAL_SETTING_ID.TabsShowActiveTerminal]: { + [TerminalSettingId.TabsShowActiveTerminal]: { description: localize('terminal.integrated.tabs.showActiveTerminal', 'Shows the active terminal information in the view, this is particularly useful when the title within the tabs aren\'t visible.'), type: 'string', enum: ['always', 'singleTerminal', 'singleTerminalOrNarrow', 'never'], @@ -310,7 +331,7 @@ export const terminalConfiguration: IConfigurationNode = { ], default: 'singleTerminalOrNarrow', }, - [TERMINAL_SETTING_ID.TabsLocation]: { + [TerminalSettingId.TabsLocation]: { type: 'string', enum: ['left', 'right'], enumDescriptions: [ @@ -320,7 +341,7 @@ export const terminalConfiguration: IConfigurationNode = { default: 'right', description: localize('terminal.integrated.tabs.location', "Controls the location of the terminal tabs, either to the left or right of the actual terminal(s).") }, - [TERMINAL_SETTING_ID.TabsFocusMode]: { + [TerminalSettingId.TabsFocusMode]: { type: 'string', enum: ['singleClick', 'doubleClick'], enumDescriptions: [ @@ -330,32 +351,32 @@ export const terminalConfiguration: IConfigurationNode = { default: 'doubleClick', description: localize('terminal.integrated.tabs.focusMode', "Controls whether focusing the terminal of a tab happens on double or single click.") }, - [TERMINAL_SETTING_ID.MacOptionIsMeta]: { + [TerminalSettingId.MacOptionIsMeta]: { description: localize('terminal.integrated.macOptionIsMeta', "Controls whether to treat the option key as the meta key in the terminal on macOS."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.MacOptionClickForcesSelection]: { + [TerminalSettingId.MacOptionClickForcesSelection]: { description: localize('terminal.integrated.macOptionClickForcesSelection', "Controls whether to force selection when using Option+click on macOS. This will force a regular (line) selection and disallow the use of column selection mode. This enables copying and pasting using the regular terminal selection, for example, when mouse mode is enabled in tmux."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.AltClickMovesCursor]: { + [TerminalSettingId.AltClickMovesCursor]: { markdownDescription: localize('terminal.integrated.altClickMovesCursor', "If enabled, alt/option + click will reposition the prompt cursor to underneath the mouse when `#editor.multiCursorModifier#` is set to `'alt'` (the default value). This may not work reliably depending on your shell."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.CopyOnSelection]: { + [TerminalSettingId.CopyOnSelection]: { description: localize('terminal.integrated.copyOnSelection', "Controls whether text selected in the terminal will be copied to the clipboard."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.DrawBoldTextInBrightColors]: { + [TerminalSettingId.DrawBoldTextInBrightColors]: { description: localize('terminal.integrated.drawBoldTextInBrightColors', "Controls whether bold text in the terminal will always use the \"bright\" ANSI color variant."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.FontFamily]: { + [TerminalSettingId.FontFamily]: { markdownDescription: localize('terminal.integrated.fontFamily', "Controls the font family of the terminal, this defaults to `#editor.fontFamily#`'s value."), type: 'string' }, @@ -365,42 +386,42 @@ export const terminalConfiguration: IConfigurationNode = { // 'type': 'boolean', // 'default': false // }, - [TERMINAL_SETTING_ID.FontSize]: { + [TerminalSettingId.FontSize]: { description: localize('terminal.integrated.fontSize', "Controls the font size in pixels of the terminal."), type: 'number', default: EDITOR_FONT_DEFAULTS.fontSize }, - [TERMINAL_SETTING_ID.LetterSpacing]: { + [TerminalSettingId.LetterSpacing]: { description: localize('terminal.integrated.letterSpacing', "Controls the letter spacing of the terminal, this is an integer value which represents the amount of additional pixels to add between characters."), type: 'number', default: DEFAULT_LETTER_SPACING }, - [TERMINAL_SETTING_ID.LineHeight]: { + [TerminalSettingId.LineHeight]: { description: localize('terminal.integrated.lineHeight', "Controls the line height of the terminal, this number is multiplied by the terminal font size to get the actual line-height in pixels."), type: 'number', default: DEFAULT_LINE_HEIGHT }, - [TERMINAL_SETTING_ID.MinimumContrastRatio]: { + [TerminalSettingId.MinimumContrastRatio]: { markdownDescription: localize('terminal.integrated.minimumContrastRatio', "When set the foreground color of each cell will change to try meet the contrast ratio specified. Example values:\n\n- 1: The default, do nothing.\n- 4.5: [WCAG AA compliance (minimum)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast-contrast.html).\n- 7: [WCAG AAA compliance (enhanced)](https://www.w3.org/TR/UNDERSTANDING-WCAG20/visual-audio-contrast7.html).\n- 21: White on black or black on white."), type: 'number', default: 1 }, - [TERMINAL_SETTING_ID.FastScrollSensitivity]: { + [TerminalSettingId.FastScrollSensitivity]: { markdownDescription: localize('terminal.integrated.fastScrollSensitivity', "Scrolling speed multiplier when pressing `Alt`."), type: 'number', default: 5 }, - [TERMINAL_SETTING_ID.MouseWheelScrollSensitivity]: { + [TerminalSettingId.MouseWheelScrollSensitivity]: { markdownDescription: localize('terminal.integrated.mouseWheelScrollSensitivity', "A multiplier to be used on the `deltaY` of mouse wheel scroll events."), type: 'number', default: 1 }, - [TERMINAL_SETTING_ID.BellDuration]: { + [TerminalSettingId.BellDuration]: { markdownDescription: localize('terminal.integrated.bellDuration', "The number of milliseconds to show the bell within a terminal tab when triggered."), type: 'number', default: 1000 }, - [TERMINAL_SETTING_ID.FontWeight]: { + [TerminalSettingId.FontWeight]: { 'anyOf': [ { type: 'number', @@ -419,7 +440,7 @@ export const terminalConfiguration: IConfigurationNode = { description: localize('terminal.integrated.fontWeight', "The font weight to use within the terminal for non-bold text. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000."), default: 'normal' }, - [TERMINAL_SETTING_ID.FontWeightBold]: { + [TerminalSettingId.FontWeightBold]: { 'anyOf': [ { type: 'number', @@ -438,27 +459,27 @@ export const terminalConfiguration: IConfigurationNode = { description: localize('terminal.integrated.fontWeightBold', "The font weight to use within the terminal for bold text. Accepts \"normal\" and \"bold\" keywords or numbers between 1 and 1000."), default: 'bold' }, - [TERMINAL_SETTING_ID.CursorBlinking]: { + [TerminalSettingId.CursorBlinking]: { description: localize('terminal.integrated.cursorBlinking', "Controls whether the terminal cursor blinks."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.CursorStyle]: { + [TerminalSettingId.CursorStyle]: { description: localize('terminal.integrated.cursorStyle', "Controls the style of terminal cursor."), enum: [TerminalCursorStyle.BLOCK, TerminalCursorStyle.LINE, TerminalCursorStyle.UNDERLINE], default: TerminalCursorStyle.BLOCK }, - [TERMINAL_SETTING_ID.CursorWidth]: { + [TerminalSettingId.CursorWidth]: { markdownDescription: localize('terminal.integrated.cursorWidth', "Controls the width of the cursor when `#terminal.integrated.cursorStyle#` is set to `line`."), type: 'number', default: 1 }, - [TERMINAL_SETTING_ID.Scrollback]: { + [TerminalSettingId.Scrollback]: { description: localize('terminal.integrated.scrollback', "Controls the maximum amount of lines the terminal keeps in its buffer."), type: 'number', default: 1000 }, - [TERMINAL_SETTING_ID.DetectLocale]: { + [TerminalSettingId.DetectLocale]: { markdownDescription: localize('terminal.integrated.detectLocale', "Controls whether to detect and set the `$LANG` environment variable to a UTF-8 compliant option since VS Code's terminal only supports UTF-8 encoded data coming from the shell."), type: 'string', enum: ['auto', 'off', 'on'], @@ -469,7 +490,7 @@ export const terminalConfiguration: IConfigurationNode = { ], default: 'auto' }, - [TERMINAL_SETTING_ID.GpuAcceleration]: { + [TerminalSettingId.GpuAcceleration]: { type: 'string', enum: ['auto', 'on', 'off'], markdownEnumDescriptions: [ @@ -480,7 +501,7 @@ export const terminalConfiguration: IConfigurationNode = { default: 'auto', description: localize('terminal.integrated.gpuAcceleration', "Controls whether the terminal will leverage the GPU to do its rendering.") }, - [TERMINAL_SETTING_ID.RightClickBehavior]: { + [TerminalSettingId.RightClickBehavior]: { type: 'string', enum: ['default', 'copyPaste', 'paste', 'selectWord'], enumDescriptions: [ @@ -492,23 +513,23 @@ export const terminalConfiguration: IConfigurationNode = { default: isMacintosh ? 'selectWord' : isWindows ? 'copyPaste' : 'default', description: localize('terminal.integrated.rightClickBehavior', "Controls how terminal reacts to right click.") }, - [TERMINAL_SETTING_ID.Cwd]: { + [TerminalSettingId.Cwd]: { restricted: true, description: localize('terminal.integrated.cwd', "An explicit start path where the terminal will be launched, this is used as the current working directory (cwd) for the shell process. This may be particularly useful in workspace settings if the root directory is not a convenient cwd."), type: 'string', default: undefined }, - [TERMINAL_SETTING_ID.ConfirmOnExit]: { + [TerminalSettingId.ConfirmOnExit]: { description: localize('terminal.integrated.confirmOnExit', "Controls whether to confirm on exit if there are active terminal sessions."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.EnableBell]: { + [TerminalSettingId.EnableBell]: { description: localize('terminal.integrated.enableBell', "Controls whether the terminal bell is enabled, this shows up as a visual bell next to the terminal's name."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.CommandsToSkipShell]: { + [TerminalSettingId.CommandsToSkipShell]: { markdownDescription: localize('terminal.integrated.commandsToSkipShell', "A set of command IDs whose keybindings will not be sent to the shell but instead always be handled by VS Code. This allows keybindings that would normally be consumed by the shell to act instead the same as when the terminal is not focused, for example `Ctrl+P` to launch Quick Open.\n\n \n\nMany commands are skipped by default. To override a default and pass that command's keybinding to the shell instead, add the command prefixed with the `-` character. For example add `-workbench.action.quickOpen` to allow `Ctrl+P` to reach the shell.\n\n \n\nThe following list of default skipped commands is truncated when viewed in Settings Editor. To see the full list, [open the default settings JSON](command:workbench.action.openRawDefaultSettings 'Open Default Settings (JSON)') and search for the first command from the list below.\n\n \n\nDefault Skipped Commands:\n\n{0}", DEFAULT_COMMANDS_TO_SKIP_SHELL.sort().map(command => `- ${command}`).join('\n')), type: 'array', items: { @@ -516,22 +537,17 @@ export const terminalConfiguration: IConfigurationNode = { }, default: [] }, - [TERMINAL_SETTING_ID.AllowChords]: { + [TerminalSettingId.AllowChords]: { markdownDescription: localize('terminal.integrated.allowChords', "Whether or not to allow chord keybindings in the terminal. Note that when this is true and the keystroke results in a chord it will bypass `#terminal.integrated.commandsToSkipShell#`, setting this to false is particularly useful when you want ctrl+k to go to your shell (not VS Code)."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.AllowMnemonics]: { + [TerminalSettingId.AllowMnemonics]: { markdownDescription: localize('terminal.integrated.allowMnemonics', "Whether to allow menubar mnemonics (eg. alt+f) to trigger the open the menubar. Note that this will cause all alt keystrokes to skip the shell when true. This does nothing on macOS."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.InheritEnv]: { - markdownDescription: localize('terminal.integrated.inheritEnv', "Whether new shells should inherit their environment from VS Code. This is not supported on Windows."), - type: 'boolean', - default: true - }, - [TERMINAL_SETTING_ID.EnvMacOs]: { + [TerminalSettingId.EnvMacOs]: { restricted: true, markdownDescription: localize('terminal.integrated.env.osx', "Object with environment variables that will be added to the VS Code process to be used by the terminal on macOS. Set to `null` to delete the environment variable."), type: 'object', @@ -540,7 +556,7 @@ export const terminalConfiguration: IConfigurationNode = { }, default: {} }, - [TERMINAL_SETTING_ID.EnvLinux]: { + [TerminalSettingId.EnvLinux]: { restricted: true, markdownDescription: localize('terminal.integrated.env.linux', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Linux. Set to `null` to delete the environment variable."), type: 'object', @@ -549,7 +565,7 @@ export const terminalConfiguration: IConfigurationNode = { }, default: {} }, - [TERMINAL_SETTING_ID.EnvWindows]: { + [TerminalSettingId.EnvWindows]: { restricted: true, markdownDescription: localize('terminal.integrated.env.windows', "Object with environment variables that will be added to the VS Code process to be used by the terminal on Windows. Set to `null` to delete the environment variable."), type: 'object', @@ -558,7 +574,7 @@ export const terminalConfiguration: IConfigurationNode = { }, default: {} }, - [TERMINAL_SETTING_ID.EnvironmentChangesIndicator]: { + [TerminalSettingId.EnvironmentChangesIndicator]: { markdownDescription: localize('terminal.integrated.environmentChangesIndicator', "Whether to display the environment changes indicator on each terminal which explains whether extensions have made, or want to make changes to the terminal's environment."), type: 'string', enum: ['off', 'on', 'warnonly'], @@ -569,17 +585,17 @@ export const terminalConfiguration: IConfigurationNode = { ], default: 'warnonly' }, - [TERMINAL_SETTING_ID.EnvironmentChangesRelaunch]: { + [TerminalSettingId.EnvironmentChangesRelaunch]: { markdownDescription: localize('terminal.integrated.environmentChangesRelaunch', "Whether to relaunch terminals automatically if extension want to contribute to their environment and have not been interacted with yet."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.ShowExitAlert]: { + [TerminalSettingId.ShowExitAlert]: { description: localize('terminal.integrated.showExitAlert', "Controls whether to show the alert \"The terminal process terminated with exit code\" when exit code is non-zero."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.SplitCwd]: { + [TerminalSettingId.SplitCwd]: { description: localize('terminal.integrated.splitCwd', "Controls the working directory a split terminal starts with."), type: 'string', enum: ['workspaceRoot', 'initial', 'inherited'], @@ -590,27 +606,27 @@ export const terminalConfiguration: IConfigurationNode = { ], default: 'inherited' }, - [TERMINAL_SETTING_ID.WindowsEnableConpty]: { + [TerminalSettingId.WindowsEnableConpty]: { description: localize('terminal.integrated.windowsEnableConpty', "Whether to use ConPTY for Windows terminal process communication (requires Windows 10 build number 18309+). Winpty will be used if this is false."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.WordSeparators]: { + [TerminalSettingId.WordSeparators]: { description: localize('terminal.integrated.wordSeparators', "A string containing all characters to be considered word separators by the double click to select word feature."), type: 'string', default: ' ()[]{}\',"`─' }, - [TERMINAL_SETTING_ID.ExperimentalUseTitleEvent]: { + [TerminalSettingId.ExperimentalUseTitleEvent]: { description: localize('terminal.integrated.experimentalUseTitleEvent', "An experimental setting that will use the terminal title event for the dropdown title. This setting will only apply to new terminals."), type: 'boolean', default: false }, - [TERMINAL_SETTING_ID.EnableFileLinks]: { + [TerminalSettingId.EnableFileLinks]: { description: localize('terminal.integrated.enableFileLinks', "Whether to enable file links in the terminal. Links can be slow when working on a network drive in particular because each file link is verified against the file system. Changing this will take effect only in new terminals."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.UnicodeVersion]: { + [TerminalSettingId.UnicodeVersion]: { type: 'string', enum: ['6', '11'], enumDescriptions: [ @@ -620,18 +636,18 @@ export const terminalConfiguration: IConfigurationNode = { default: '11', description: localize('terminal.integrated.unicodeVersion', "Controls what version of unicode to use when evaluating the width of characters in the terminal. If you experience emoji or other wide characters not taking up the right amount of space or backspace either deleting too much or too little then you may want to try tweaking this setting.") }, - [TERMINAL_SETTING_ID.ExperimentalLinkProvider]: { + [TerminalSettingId.ExperimentalLinkProvider]: { description: localize('terminal.integrated.experimentalLinkProvider', "An experimental setting that aims to improve link detection in the terminal by improving when links are detected and by enabling shared link detection with the editor. Currently this only supports web links."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.LocalEchoLatencyThreshold]: { + [TerminalSettingId.LocalEchoLatencyThreshold]: { description: localize('terminal.integrated.localEchoLatencyThreshold', "Experimental: length of network delay, in milliseconds, where local edits will be echoed on the terminal without waiting for server acknowledgement. If '0', local echo will always be on, and if '-1' it will be disabled."), type: 'integer', minimum: -1, default: 30, }, - [TERMINAL_SETTING_ID.LocalEchoExcludePrograms]: { + [TerminalSettingId.LocalEchoExcludePrograms]: { description: localize('terminal.integrated.localEchoExcludePrograms', "Experimental: local echo will be disabled when any of these program names are found in the terminal title."), type: 'array', items: { @@ -640,7 +656,7 @@ export const terminalConfiguration: IConfigurationNode = { }, default: DEFAULT_LOCAL_ECHO_EXCLUDE, }, - [TERMINAL_SETTING_ID.LocalEchoStyle]: { + [TerminalSettingId.LocalEchoStyle]: { description: localize('terminal.integrated.localEchoStyle', "Experimental: terminal style of locally echoed text; either a font style or an RGB color."), default: 'dim', oneOf: [ @@ -656,12 +672,12 @@ export const terminalConfiguration: IConfigurationNode = { } ] }, - [TERMINAL_SETTING_ID.EnablePersistentSessions]: { + [TerminalSettingId.EnablePersistentSessions]: { description: localize('terminal.integrated.enablePersistentSessions', "Persist terminal sessions for the workspace across window reloads."), type: 'boolean', default: true }, - [TERMINAL_SETTING_ID.AllowWorkspaceConfiguration]: { + [TerminalSettingId.AllowWorkspaceConfiguration]: { scope: ConfigurationScope.APPLICATION, description: localize('terminal.integrated.allowWorkspaceConfiguration', "Allows shell and profile settings to be pick up from a workspace."), type: 'boolean', @@ -669,49 +685,3 @@ export const terminalConfiguration: IConfigurationNode = { } } }; - -function getTerminalShellConfigurationStub(linux: string, osx: string, windows: string): IConfigurationNode { - return { - id: 'terminal', - order: 100, - title: localize('terminalIntegratedConfigurationTitle', "Integrated Terminal"), - type: 'object', - properties: { - [TERMINAL_SETTING_ID.ShellLinux]: { - restricted: true, - markdownDescription: linux, - type: ['string', 'null'], - default: null, - markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.linux#` instead' - }, - [TERMINAL_SETTING_ID.ShellMacOs]: { - restricted: true, - markdownDescription: osx, - type: ['string', 'null'], - default: null, - markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.osx#` instead' - }, - [TERMINAL_SETTING_ID.ShellWindows]: { - restricted: true, - markdownDescription: windows, - type: ['string', 'null'], - default: null, - markdownDeprecationMessage: 'This is deprecated, use `#terminal.integrated.defaultProfile.windows#` instead' - } - } - }; -} - -export function getNoDefaultTerminalShellConfiguration(): IConfigurationNode { - return getTerminalShellConfigurationStub( - localize('terminal.integrated.shell.linux.noDefault', "The path of the shell that the terminal uses on Linux. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), - localize('terminal.integrated.shell.osx.noDefault', "The path of the shell that the terminal uses on macOS. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration)."), - localize('terminal.integrated.shell.windows.noDefault', "The path of the shell that the terminal uses on Windows. [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).")); -} - -export async function getTerminalShellConfiguration(getSystemShell: (os: OperatingSystem) => Promise): Promise { - return getTerminalShellConfigurationStub( - localize('terminal.integrated.shell.linux', "The path of the shell that the terminal uses on Linux (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(OperatingSystem.Linux)), - localize('terminal.integrated.shell.osx', "The path of the shell that the terminal uses on macOS (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(OperatingSystem.Macintosh)), - localize('terminal.integrated.shell.windows', "The path of the shell that the terminal uses on Windows (default: {0}). [Read more about configuring the shell](https://code.visualstudio.com/docs/editor/integrated-terminal#_configuration).", await getSystemShell(OperatingSystem.Windows))); -} diff --git a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts index 0a024ec7826..f6d1aff514a 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalEnvironment.ts @@ -11,7 +11,7 @@ import { sanitizeProcessEnvironment } from 'vs/base/common/processes'; import { ILogService } from 'vs/platform/log/common/log'; import { IShellLaunchConfig, ITerminalEnvironment } from 'vs/platform/terminal/common/terminal'; import { IProcessEnvironment, isWindows, locale, OperatingSystem, OS, platform, Platform } from 'vs/base/common/platform'; -import { TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; /** * This module contains utility functions related to the environment, cwd and paths. @@ -237,29 +237,19 @@ function _sanitizeCwd(cwd: string): string { return cwd; } -export function escapeNonWindowsPath(path: string): string { - let newPath = path; - if (newPath.indexOf('\\') !== 0) { - newPath = newPath.replace(/\\/g, '\\\\'); - } - const bannedChars = /[\`\$\|\&\>\~\#\!\^\*\;\<\"\']/g; - newPath = newPath.replace(bannedChars, ''); - return `'${newPath}'`; -} - export type TerminalShellSetting = ( - TERMINAL_SETTING_ID.AutomationShellWindows - | TERMINAL_SETTING_ID.AutomationShellMacOs - | TERMINAL_SETTING_ID.AutomationShellLinux - | TERMINAL_SETTING_ID.ShellWindows - | TERMINAL_SETTING_ID.ShellMacOs - | TERMINAL_SETTING_ID.ShellLinux + TerminalSettingId.AutomationShellWindows + | TerminalSettingId.AutomationShellMacOs + | TerminalSettingId.AutomationShellLinux + | TerminalSettingId.ShellWindows + | TerminalSettingId.ShellMacOs + | TerminalSettingId.ShellLinux ); export type TerminalShellArgsSetting = ( - TERMINAL_SETTING_ID.ShellArgsWindows - | TERMINAL_SETTING_ID.ShellArgsMacOs - | TERMINAL_SETTING_ID.ShellArgsLinux + TerminalSettingId.ShellArgsWindows + | TerminalSettingId.ShellArgsMacOs + | TerminalSettingId.ShellArgsLinux ); export type VariableResolver = (str: string) => string; @@ -377,7 +367,7 @@ export function createTerminalEnvironment( baseEnv: IProcessEnvironment ): IProcessEnvironment { // Create a terminal environment based on settings, launch config and permissions - let env: IProcessEnvironment = {}; + const env: IProcessEnvironment = {}; if (shellLaunchConfig.strictEnv) { // strictEnv is true, only use the requested env (ignoring null entries) mergeNonNullKeys(env, shellLaunchConfig.env); diff --git a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts index b85ff372e68..37b88ccf787 100644 --- a/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts +++ b/src/vs/workbench/contrib/terminal/common/terminalExtensionPoints.ts @@ -20,11 +20,11 @@ export interface ITerminalContributionService { export const ITerminalContributionService = createDecorator('terminalContributionsService'); export class TerminalContributionService implements ITerminalContributionService { - public readonly _serviceBrand = undefined; + declare _serviceBrand: undefined; private _terminalTypes: ReadonlyArray = []; - public get terminalTypes() { + get terminalTypes() { return this._terminalTypes; } diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts deleted file mode 100644 index 6f6943b6e23..00000000000 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminal.contribution.ts +++ /dev/null @@ -1,34 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; -import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; -import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/electron-browser/terminalInstanceService'; -import { TerminalNativeContribution } from 'vs/workbench/contrib/terminal/electron-browser/terminalNativeContribution'; -import { Registry } from 'vs/platform/registry/common/platform'; -import { IConfigurationRegistry, Extensions } from 'vs/platform/configuration/common/configurationRegistry'; -import { getTerminalShellConfiguration } from 'vs/workbench/contrib/terminal/common/terminalConfiguration'; -import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; -import { getSystemShell } from 'vs/base/node/shell'; -import { process } from 'vs/base/parts/sandbox/electron-sandbox/globals'; -import { OperatingSystem } from 'vs/base/common/platform'; -import { ElectronTerminalProfileResolverService } from 'vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService'; -import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal'; - -// This file contains additional desktop-only contributions on top of those in browser/ - -// Register services -registerSingleton(ITerminalInstanceService, TerminalInstanceService, true); -registerSingleton(ITerminalProfileResolverService, ElectronTerminalProfileResolverService, true); - -const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); -workbenchRegistry.registerWorkbenchContribution(TerminalNativeContribution, LifecyclePhase.Ready); - -// Register configurations -const configurationRegistry = Registry.as(Extensions.Configuration); - -const systemShell = async (os: OperatingSystem) => getSystemShell(os, await process.shellEnv()); -getTerminalShellConfiguration(systemShell).then(config => configurationRegistry.registerConfiguration(config)); diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts deleted file mode 100644 index 3c47b5eaf5e..00000000000 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalInstanceService.ts +++ /dev/null @@ -1,60 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ -import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { IProcessEnvironment } from 'vs/base/common/platform'; -import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; -import type { Terminal as XTermTerminal } from 'xterm'; -import type { SearchAddon as XTermSearchAddon } from 'xterm-addon-search'; -import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode11'; -import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl'; -import { IShellEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentService'; - -let Terminal: typeof XTermTerminal; -let SearchAddon: typeof XTermSearchAddon; -let Unicode11Addon: typeof XTermUnicode11Addon; -let WebglAddon: typeof XTermWebglAddon; - -export class TerminalInstanceService extends Disposable implements ITerminalInstanceService { - public _serviceBrand: undefined; - - constructor( - @IShellEnvironmentService private readonly _shellEnvironmentService: IShellEnvironmentService - ) { - super(); - } - - public async getXtermConstructor(): Promise { - if (!Terminal) { - Terminal = (await import('xterm')).Terminal; - } - return Terminal; - } - - public async getXtermSearchConstructor(): Promise { - if (!SearchAddon) { - SearchAddon = (await import('xterm-addon-search')).SearchAddon; - } - return SearchAddon; - } - - public async getXtermUnicode11Constructor(): Promise { - if (!Unicode11Addon) { - Unicode11Addon = (await import('xterm-addon-unicode11')).Unicode11Addon; - } - return Unicode11Addon; - } - - public async getXtermWebglConstructor(): Promise { - if (!WebglAddon) { - WebglAddon = (await import('xterm-addon-webgl')).WebglAddon; - } - return WebglAddon; - } - - public async getMainProcessParentEnv(): Promise { - return getMainProcessParentEnv(await this._shellEnvironmentService.getShellEnv()); - } -} diff --git a/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeContribution.ts b/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeContribution.ts deleted file mode 100644 index 3c7442aed9d..00000000000 --- a/src/vs/workbench/contrib/terminal/electron-browser/terminalNativeContribution.ts +++ /dev/null @@ -1,54 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { escapeNonWindowsPath } from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; -import { execFile } from 'child_process'; -import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation'; -import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; -import { INativeHostService } from 'vs/platform/native/electron-sandbox/native'; -import { Disposable } from 'vs/base/common/lifecycle'; -import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; -import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; -import { getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; -import { linuxDistro } from 'vs/workbench/contrib/terminal/node/terminal'; - -export class TerminalNativeContribution extends Disposable implements IWorkbenchContribution { - public _serviceBrand: undefined; - - constructor( - @ITerminalService private readonly _terminalService: ITerminalService, - @IInstantiationService readonly instantiationService: IInstantiationService, - @IRemoteAgentService readonly remoteAgentService: IRemoteAgentService, - @INativeHostService readonly nativeHostService: INativeHostService - ) { - super(); - - this._terminalService.setLinuxDistro(linuxDistro); - this._terminalService.setNativeWindowsDelegate({ - getWslPath: this._getWslPath.bind(this), - getWindowsBuildNumber: this._getWindowsBuildNumber.bind(this) - }); - } - - /** - * Converts a path to a path on WSL using the wslpath utility. - * @param path The original path. - */ - private _getWslPath(path: string): Promise { - if (getWindowsBuildNumber() < 17063) { - throw new Error('wslpath does not exist on Windows build < 17063'); - } - return new Promise(c => { - const proc = execFile('bash.exe', ['-c', `wslpath ${escapeNonWindowsPath(path)}`], {}, (error, stdout, stderr) => { - c(escapeNonWindowsPath(stdout.trim())); - }); - proc.stdin!.end(); - }); - } - - private _getWindowsBuildNumber(): number { - return getWindowsBuildNumber(); - } -} diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts index 5adea910597..d136eb48052 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localPty.ts @@ -17,21 +17,21 @@ export class LocalPty extends Disposable implements ITerminalChildProcess { private _inReplay = false; private readonly _onProcessData = this._register(new Emitter()); - public readonly onProcessData = this._onProcessData.event; + readonly onProcessData = this._onProcessData.event; private readonly _onProcessReplay = this._register(new Emitter()); - public readonly onProcessReplay = this._onProcessReplay.event; + readonly onProcessReplay = this._onProcessReplay.event; private readonly _onProcessExit = this._register(new Emitter()); - public readonly onProcessExit = this._onProcessExit.event; + readonly onProcessExit = this._onProcessExit.event; private readonly _onProcessReady = this._register(new Emitter<{ pid: number, cwd: string }>()); - public readonly onProcessReady = this._onProcessReady.event; + readonly onProcessReady = this._onProcessReady.event; private readonly _onProcessTitleChanged = this._register(new Emitter()); - public readonly onProcessTitleChanged = this._onProcessTitleChanged.event; + readonly onProcessTitleChanged = this._onProcessTitleChanged.event; private readonly _onProcessOverrideDimensions = this._register(new Emitter()); - public readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; + readonly onProcessOverrideDimensions = this._onProcessOverrideDimensions.event; private readonly _onProcessResolvedShellLaunchConfig = this._register(new Emitter()); - public readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event; + readonly onProcessResolvedShellLaunchConfig = this._onProcessResolvedShellLaunchConfig.event; private readonly _onProcessShellTypeChanged = this._register(new Emitter()); - public readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; + readonly onProcessShellTypeChanged = this._onProcessShellTypeChanged.event; constructor( readonly id: number, diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts index 42c740c4772..f32180d18bd 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/localTerminalService.ts @@ -19,7 +19,7 @@ import { LocalPty } from 'vs/workbench/contrib/terminal/electron-sandbox/localPt import { IShellEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentService'; export class LocalTerminalService extends Disposable implements ILocalTerminalService { - public _serviceBrand: undefined; + declare _serviceBrand: undefined; private readonly _ptys: Map = new Map(); private _isPtyHostUnresponsive: boolean = false; @@ -98,7 +98,7 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe } } - public async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise { + async createProcess(shellLaunchConfig: IShellLaunchConfig, cwd: string, cols: number, rows: number, env: IProcessEnvironment, windowsEnableConpty: boolean, shouldPersist: boolean): Promise { const executableEnv = await this._shellEnvironmentService.getShellEnv(); const id = await this._localPtyService.createProcess(shellLaunchConfig, cwd, cols, rows, env, executableEnv, windowsEnableConpty, shouldPersist, this._getWorkspaceId(), this._getWorkspaceName()); const pty = this._instantiationService.createInstance(LocalPty, id, shouldPersist); @@ -106,7 +106,7 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe return pty; } - public async attachToProcess(id: number): Promise { + async attachToProcess(id: number): Promise { try { await this._localPtyService.attachToProcess(id); const pty = this._instantiationService.createInstance(LocalPty, id, true); @@ -118,23 +118,27 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe return undefined; } - public async listProcesses(): Promise { + async listProcesses(): Promise { return this._localPtyService.listProcesses(); } - public async reduceConnectionGraceTime(): Promise { + async reduceConnectionGraceTime(): Promise { this._localPtyService.reduceConnectionGraceTime(); } - public async getDefaultSystemShell(osOverride?: OperatingSystem): Promise { + async getDefaultSystemShell(osOverride?: OperatingSystem): Promise { return this._localPtyService.getDefaultSystemShell(osOverride); } - public async getShellEnvironment(): Promise { - return this._localPtyService.getShellEnvironment(); + async getEnvironment(): Promise { + return this._localPtyService.getEnvironment(); } - public async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise { + async getWslPath(original: string): Promise { + return this._localPtyService.getWslPath(original); + } + + async setTerminalLayoutInfo(layoutInfo?: ITerminalsLayoutInfoById): Promise { const args: ISetTerminalLayoutInfoArgs = { workspaceId: this._getWorkspaceId(), tabs: layoutInfo ? layoutInfo.tabs : [] @@ -142,12 +146,11 @@ export class LocalTerminalService extends Disposable implements ILocalTerminalSe await this._localPtyService.setTerminalLayoutInfo(args); } - public async getTerminalLayoutInfo(): Promise { + async getTerminalLayoutInfo(): Promise { const layoutArgs: IGetTerminalLayoutInfoArgs = { workspaceId: this._getWorkspaceId() }; - let result = await this._localPtyService.getTerminalLayoutInfo(layoutArgs); - return result; + return await this._localPtyService.getTerminalLayoutInfo(layoutArgs); } private _getWorkspaceId(): string { diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/terminal.contribution.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/terminal.contribution.ts index 6528bd19f1d..3ccdab481f2 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/terminal.contribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/terminal.contribution.ts @@ -10,12 +10,15 @@ import { ILocalTerminalService, TerminalIpcChannels } from 'vs/platform/terminal import { ILocalPtyService } from 'vs/platform/terminal/electron-sandbox/terminal'; import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'; import { ExternalTerminalContribution } from 'vs/workbench/contrib/externalTerminal/electron-sandbox/externalTerminal.contribution'; +import { ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal'; import { LocalTerminalService } from 'vs/workbench/contrib/terminal/electron-sandbox/localTerminalService'; import { TerminalNativeContribution } from 'vs/workbench/contrib/terminal/electron-sandbox/terminalNativeContribution'; +import { ElectronTerminalProfileResolverService } from 'vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService'; import { LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'; +// Register services registerSharedProcessRemoteService(ILocalPtyService, TerminalIpcChannels.LocalPty, { supportsDelayedInstantiation: true }); - +registerSingleton(ITerminalProfileResolverService, ElectronTerminalProfileResolverService, true); registerSingleton(ILocalTerminalService, LocalTerminalService, true); const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalNativeContribution.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalNativeContribution.ts index 33267e38002..651030fe136 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalNativeContribution.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalNativeContribution.ts @@ -16,7 +16,7 @@ import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal import { IWorkbenchContribution } from 'vs/workbench/common/contributions'; export class TerminalNativeContribution extends Disposable implements IWorkbenchContribution { - public _serviceBrand: undefined; + declare _serviceBrand: undefined; constructor( @IFileService private readonly _fileService: IFileService, diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService.ts index d22e66d5594..f50c41af229 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalProfileResolverService.ts @@ -10,7 +10,6 @@ import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace import { IRemoteTerminalService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { BaseTerminalProfileResolverService } from 'vs/workbench/contrib/terminal/browser/terminalProfileResolverService'; import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver'; -import { IShellEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/shellEnvironmentService'; import { IHistoryService } from 'vs/workbench/services/history/common/history'; export class ElectronTerminalProfileResolverService extends BaseTerminalProfileResolverService { @@ -20,7 +19,6 @@ export class ElectronTerminalProfileResolverService extends BaseTerminalProfileR @IConfigurationService configurationService: IConfigurationService, @IHistoryService historyService: IHistoryService, @ILogService logService: ILogService, - @IShellEnvironmentService shellEnvironmentService: IShellEnvironmentService, @ITerminalService terminalService: ITerminalService, @ILocalTerminalService localTerminalService: ILocalTerminalService, @IRemoteTerminalService remoteTerminalService: IRemoteTerminalService, @@ -32,11 +30,12 @@ export class ElectronTerminalProfileResolverService extends BaseTerminalProfileR const service = remoteAuthority ? remoteTerminalService : localTerminalService; return service.getDefaultSystemShell(platform); }, - getShellEnvironment: (remoteAuthority) => { + getEnvironment: (remoteAuthority) => { if (remoteAuthority) { - remoteTerminalService.getShellEnvironment(); + return remoteTerminalService.getEnvironment(); + } else { + return localTerminalService.getEnvironment(); } - return shellEnvironmentService.getShellEnv(); } }, configurationService, diff --git a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalRemote.ts b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalRemote.ts index 677c5dfcb8a..9743f3c138c 100644 --- a/src/vs/workbench/contrib/terminal/electron-sandbox/terminalRemote.ts +++ b/src/vs/workbench/contrib/terminal/electron-sandbox/terminalRemote.ts @@ -7,7 +7,7 @@ import * as nls from 'vs/nls'; import { Registry } from 'vs/platform/registry/common/platform'; import { Extensions as ActionExtensions, IWorkbenchActionRegistry } from 'vs/workbench/common/actions'; import { SyncActionDescriptor } from 'vs/platform/actions/common/actions'; -import { TERMINAL_ACTION_CATEGORY, TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TERMINAL_ACTION_CATEGORY, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { Action } from 'vs/base/common/actions'; import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { INativeEnvironmentService } from 'vs/platform/environment/common/environment'; @@ -18,8 +18,8 @@ export function registerRemoteContributions() { } export class CreateNewLocalTerminalAction extends Action { - public static readonly ID = TERMINAL_COMMAND_ID.NEW_LOCAL; - public static readonly LABEL = nls.localize('workbench.action.terminal.newLocal', "Create New Integrated Terminal (Local)"); + static readonly ID = TerminalCommandId.NewLocal; + static readonly LABEL = nls.localize('workbench.action.terminal.newLocal', "Create New Integrated Terminal (Local)"); constructor( id: string, label: string, @@ -29,7 +29,7 @@ export class CreateNewLocalTerminalAction extends Action { super(id, label); } - public override run(): Promise { + override run(): Promise { const instance = this._terminalService.createTerminal({ cwd: this._nativeEnvironmentService.userHome }); if (!instance) { return Promise.resolve(undefined); diff --git a/src/vs/workbench/contrib/terminal/node/terminal.ts b/src/vs/workbench/contrib/terminal/node/terminal.ts deleted file mode 100644 index adb21019594..00000000000 --- a/src/vs/workbench/contrib/terminal/node/terminal.ts +++ /dev/null @@ -1,28 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as fs from 'fs'; -import { isLinux } from 'vs/base/common/platform'; -import { SymlinkSupport } from 'vs/base/node/pfs'; -import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; - -let detectedDistro = LinuxDistro.Unknown; -if (isLinux) { - const file = '/etc/os-release'; - SymlinkSupport.existsFile(file).then(async exists => { - if (!exists) { - return; - } - const buffer = await fs.promises.readFile(file); - const contents = buffer.toString(); - if (/NAME="?Fedora"?/.test(contents)) { - detectedDistro = LinuxDistro.Fedora; - } else if (/NAME="?Ubuntu"?/.test(contents)) { - detectedDistro = LinuxDistro.Ubuntu; - } - }); -} - -export const linuxDistro = detectedDistro; diff --git a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts b/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts deleted file mode 100644 index 988b9aed510..00000000000 --- a/src/vs/workbench/contrib/terminal/node/terminalEnvironment.ts +++ /dev/null @@ -1,79 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as fs from 'fs'; -import * as path from 'vs/base/common/path'; -import { IProcessEnvironment, isLinux, isMacintosh, isWindows } from 'vs/base/common/platform'; - -let mainProcessParentEnv: IProcessEnvironment | undefined; - -export async function getMainProcessParentEnv(baseEnvironment: IProcessEnvironment): Promise { - if (mainProcessParentEnv) { - return mainProcessParentEnv; - } - - // For Linux use /proc//status to get the parent of the main process and then fetch its - // env using /proc//environ. - if (isLinux) { - const mainProcessId = process.ppid; - const codeProcessName = path.basename(process.argv[0]); - let pid: number = 0; - let ppid: number = mainProcessId; - let name: string = codeProcessName; - do { - pid = ppid; - const status = await fs.promises.readFile(`/proc/${pid}/status`, 'utf8'); - const splitByLine = status.split('\n'); - splitByLine.forEach(line => { - if (line.indexOf('Name:') === 0) { - name = line.replace(/^Name:\s+/, ''); - } - if (line.indexOf('PPid:') === 0) { - ppid = parseInt(line.replace(/^PPid:\s+/, '')); - } - }); - } while (name === codeProcessName); - const rawEnv = await fs.promises.readFile(`/proc/${pid}/environ`, 'utf8'); - const env: IProcessEnvironment = {}; - rawEnv.split('\0').forEach(e => { - const i = e.indexOf('='); - env[e.substr(0, i)] = e.substr(i + 1); - }); - mainProcessParentEnv = env; - } - - // For macOS we want the "root" environment as shells by default run as login shells. It - // doesn't appear to be possible to get the "root" environment as `ps eww -o command` for - // PID 1 (the parent of the main process when launched from the dock/finder) returns no - // environment, because of this we will fill in the root environment using a allowlist of - // environment variables that we have. - if (isMacintosh) { - mainProcessParentEnv = {}; - // This list was generated by diffing launching a terminal with {} and the system - // terminal launched from finder. - const rootEnvVars = [ - 'SHELL', - 'SSH_AUTH_SOCK', - 'Apple_PubSub_Socket_Render', - 'XPC_FLAGS', - 'XPC_SERVICE_NAME', - 'HOME', - 'LOGNAME', - 'TMPDIR' - ]; - rootEnvVars.forEach(k => { - if (baseEnvironment[k]) { - mainProcessParentEnv![k] = baseEnvironment[k]!; - } - }); - } - - // TODO: Windows should return a fresh environment block, might need native code? - if (isWindows) { - mainProcessParentEnv = baseEnvironment; - } - - return mainProcessParentEnv!; -} diff --git a/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts b/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts index 4e2eb6e1596..89cdf939398 100644 --- a/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts +++ b/src/vs/workbench/contrib/terminal/node/terminalProfiles.ts @@ -7,7 +7,7 @@ import * as fs from 'fs'; import { normalize, basename, delimiter } from 'vs/base/common/path'; import { enumeratePowerShellInstallations } from 'vs/base/node/powershell'; import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node/terminalEnvironment'; -import { ITerminalProfile, ITerminalProfileObject, ProfileSource, TERMINAL_SETTING_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ITerminalProfile, ITerminalProfileObject, ProfileSource, TerminalSettingId } from 'vs/workbench/contrib/terminal/common/terminal'; import * as cp from 'child_process'; import { ExtHostVariableResolverService } from 'vs/workbench/api/common/extHostDebugService'; import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace'; @@ -29,8 +29,8 @@ export function detectAvailableProfiles(configuredProfilesOnly: boolean, safeCon configuredProfilesOnly, fsProvider, logService, - safeConfigProvider(TERMINAL_SETTING_ID.UseWslProfiles) || true, - safeConfigProvider(TERMINAL_SETTING_ID.ProfilesWindows), + safeConfigProvider(TerminalSettingId.UseWslProfiles) || true, + safeConfigProvider(TerminalSettingId.ProfilesWindows), variableResolver, workspaceFolder ); @@ -39,7 +39,7 @@ export function detectAvailableProfiles(configuredProfilesOnly: boolean, safeCon fsProvider, logService, configuredProfilesOnly, - safeConfigProvider(isMacintosh ? TERMINAL_SETTING_ID.ProfilesMacOs : TERMINAL_SETTING_ID.ProfilesLinux), + safeConfigProvider(isMacintosh ? TerminalSettingId.ProfilesMacOs : TerminalSettingId.ProfilesLinux), testPaths, variableResolver, workspaceFolder @@ -201,7 +201,7 @@ async function getWslProfiles(wslPath: string, useWslProfiles?: boolean): Promis if (distroOutput) { const regex = new RegExp(/[\r?\n]/); const distroNames = distroOutput.split(regex).filter(t => t.trim().length > 0 && t !== ''); - for (let distroName of distroNames) { + for (const distroName of distroNames) { // Skip empty lines if (distroName === '') { continue; diff --git a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkHelpers.test.ts b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkHelpers.test.ts index c803351966c..56c271e5825 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkHelpers.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/links/terminalLinkHelpers.test.ts @@ -157,7 +157,7 @@ const TEST_WIDE_CHAR = '文'; const TEST_NULL_CHAR = 'C'; function createBufferLineArray(lines: { text: string, width: number }[]): IBufferLine[] { - let result: IBufferLine[] = []; + const result: IBufferLine[] = []; lines.forEach((l, i) => { result.push(new TestBufferLine( l.text, @@ -178,9 +178,9 @@ class TestBufferLine implements IBufferLine { } getCell(x: number): IBufferCell | undefined { // Create a fake line of cells and use that to resolve the width - let cells: string[] = []; + const cells: string[] = []; let wideNullCellOffset = 0; // There is no null 0 width char after a wide char - let emojiOffset = 0; // Skip chars as emoji are multiple characters + const emojiOffset = 0; // Skip chars as emoji are multiple characters for (let i = 0; i <= x - wideNullCellOffset + emojiOffset; i++) { let char = this._text.charAt(i); if (char === '\ud83d') { diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts index 1f1a4da2775..230b0cfe8c7 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalConfigHelper.test.ts @@ -7,7 +7,13 @@ import * as assert from 'assert'; import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper'; import { EDITOR_FONT_DEFAULTS } from 'vs/editor/common/config/editorOptions'; import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService'; -import { LinuxDistro } from 'vs/workbench/contrib/terminal/common/terminal'; +import { LinuxDistro } from 'vs/workbench/contrib/terminal/browser/terminal'; + +class TestTerminalConfigHelper extends TerminalConfigHelper { + set linuxDistro(distro: LinuxDistro) { + this._linuxDistro = distro; + } +} suite('Workbench - TerminalConfigHelper', () => { let fixture: HTMLElement; @@ -20,7 +26,7 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); await configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); await configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: 'bar' } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontFamily, 'bar', 'terminal.integrated.fontFamily should be selected over editor.fontFamily'); }); @@ -29,8 +35,8 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); await configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); await configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); - configHelper.setLinuxDistro(LinuxDistro.Fedora); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper.linuxDistro = LinuxDistro.Fedora; configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontFamily, '\'DejaVu Sans Mono\', monospace', 'Fedora should have its font overridden when terminal.integrated.fontFamily not set'); }); @@ -39,8 +45,8 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); await configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); await configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); - configHelper.setLinuxDistro(LinuxDistro.Ubuntu); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper.linuxDistro = LinuxDistro.Ubuntu; configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontFamily, '\'Ubuntu Mono\', monospace', 'Ubuntu should have its font overridden when terminal.integrated.fontFamily not set'); }); @@ -49,7 +55,7 @@ suite('Workbench - TerminalConfigHelper', () => { const configurationService = new TestConfigurationService(); await configurationService.setUserConfiguration('editor', { fontFamily: 'foo' }); await configurationService.setUserConfiguration('terminal', { integrated: { fontFamily: null } }); - const configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontFamily, 'foo', 'editor.fontFamily should be the fallback when terminal.integrated.fontFamily not set'); }); @@ -67,7 +73,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 10 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + let configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, 10, 'terminal.integrated.fontSize should be selected over editor.fontSize'); @@ -80,12 +86,12 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); - configHelper.setLinuxDistro(LinuxDistro.Ubuntu); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper.linuxDistro = LinuxDistro.Ubuntu; configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, 8, 'The minimum terminal font size (with adjustment) should be used when terminal.integrated.fontSize less than it'); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, 6, 'The minimum terminal font size should be used when terminal.integrated.fontSize less than it'); @@ -98,7 +104,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: 1500 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, 25, 'The maximum terminal font size should be used when terminal.integrated.fontSize more than it'); @@ -111,12 +117,12 @@ suite('Workbench - TerminalConfigHelper', () => { fontSize: null } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); - configHelper.setLinuxDistro(LinuxDistro.Ubuntu); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper.linuxDistro = LinuxDistro.Ubuntu; configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize + 2, 'The default editor font size (with adjustment) should be used when terminal.integrated.fontSize is not set'); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().fontSize, EDITOR_FONT_DEFAULTS.fontSize, 'The default editor font size should be used when terminal.integrated.fontSize is not set'); }); @@ -134,7 +140,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 2 } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + let configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().lineHeight, 2, 'terminal.integrated.lineHeight should be selected over editor.lineHeight'); @@ -148,7 +154,7 @@ suite('Workbench - TerminalConfigHelper', () => { lineHeight: 0 } }); - configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.getFont().lineHeight, 1, 'editor.lineHeight should be 1 when terminal.integrated.lineHeight not set'); }); @@ -161,7 +167,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -173,7 +179,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'sans-serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -185,7 +191,7 @@ suite('Workbench - TerminalConfigHelper', () => { fontFamily: 'serif' } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); @@ -201,7 +207,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), true, 'monospace is monospaced'); }); @@ -217,7 +223,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), false, 'sans-serif is not monospaced'); }); @@ -233,7 +239,7 @@ suite('Workbench - TerminalConfigHelper', () => { } }); - let configHelper = new TerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); + const configHelper = new TestTerminalConfigHelper(configurationService, null!, null!, null!, null!, null!); configHelper.panelContainer = fixture; assert.strictEqual(configHelper.configFontIsMonospace(), false, 'serif is not monospaced'); }); diff --git a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts index 184af066d14..0f93b55fda7 100644 --- a/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts +++ b/src/vs/workbench/contrib/terminal/test/browser/terminalTypeahead.test.ts @@ -388,36 +388,36 @@ suite('Workbench - Terminal Typeahead', () => { }); class TestTypeAheadAddon extends TypeAheadAddon { - public unlockMakingPredictions() { - this.lastRow = { y: 1, startingX: 100, endingX: 100, charState: CharPredictState.Validated }; + unlockMakingPredictions() { + this._lastRow = { y: 1, startingX: 100, endingX: 100, charState: CharPredictState.Validated }; } - public lockMakingPredictions() { - this.lastRow = undefined; + lockMakingPredictions() { + this._lastRow = undefined; } - public unlockNavigating() { - this.lastRow = { y: 1, startingX: 1, endingX: 1, charState: CharPredictState.Validated }; + unlockNavigating() { + this._lastRow = { y: 1, startingX: 1, endingX: 1, charState: CharPredictState.Validated }; } - public reevaluateNow() { - this.reevaluatePredictorStateNow(this.stats!, this.timeline!); + reevaluateNow() { + this._reevaluatePredictorStateNow(this.stats!, this._timeline!); } - public get isShowing() { - return !!this.timeline?.isShowingPredictions; + get isShowing() { + return !!this._timeline?.isShowingPredictions; } - public undoAllPredictions() { - this.timeline?.undoAllPredictions(); + undoAllPredictions() { + this._timeline?.undoAllPredictions(); } - public physicalCursor(buffer: IBuffer) { - return this.timeline?.physicalCursor(buffer); + physicalCursor(buffer: IBuffer) { + return this._timeline?.physicalCursor(buffer); } - public tentativeCursor(buffer: IBuffer) { - return this.timeline?.tentativeCursor(buffer); + tentativeCursor(buffer: IBuffer) { + return this._timeline?.tentativeCursor(buffer); } } diff --git a/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts index 2524a5ad713..f0737aa3e58 100644 --- a/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/terminalColorRegistry.test.ts @@ -13,9 +13,9 @@ import { ColorScheme } from 'vs/platform/theme/common/theme'; registerColors(); -let themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); +const themingRegistry = Registry.as(ThemeingExtensions.ColorContribution); function getMockTheme(type: ColorScheme): IColorTheme { - let theme = { + const theme = { selector: '', label: '', type: type, @@ -31,8 +31,8 @@ function getMockTheme(type: ColorScheme): IColorTheme { suite('Workbench - TerminalColorRegistry', () => { test('hc colors', function () { - let theme = getMockTheme(ColorScheme.HIGH_CONTRAST); - let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); + const theme = getMockTheme(ColorScheme.HIGH_CONTRAST); + const colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepStrictEqual(colors, [ '#000000', @@ -56,8 +56,8 @@ suite('Workbench - TerminalColorRegistry', () => { }); test('light colors', function () { - let theme = getMockTheme(ColorScheme.LIGHT); - let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); + const theme = getMockTheme(ColorScheme.LIGHT); + const colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepStrictEqual(colors, [ '#000000', @@ -81,8 +81,8 @@ suite('Workbench - TerminalColorRegistry', () => { }); test('dark colors', function () { - let theme = getMockTheme(ColorScheme.DARK); - let colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); + const theme = getMockTheme(ColorScheme.DARK); + const colors = ansiColorIdentifiers.map(colorId => Color.Format.CSS.formatHexA(theme.getColor(colorId)!, true)); assert.deepStrictEqual(colors, [ '#000000', diff --git a/src/vs/workbench/contrib/terminal/test/common/terminalDataBuffering.test.ts b/src/vs/workbench/contrib/terminal/test/common/terminalDataBuffering.test.ts index 92ec1097e93..01cec8ee267 100644 --- a/src/vs/workbench/contrib/terminal/test/common/terminalDataBuffering.test.ts +++ b/src/vs/workbench/contrib/terminal/test/common/terminalDataBuffering.test.ts @@ -80,7 +80,7 @@ suite('Workbench - TerminalDataBufferer', () => { }); test('stop', async () => { - let terminalOnData = new Emitter(); + const terminalOnData = new Emitter(); bufferer.startBuffering(1, terminalOnData.event, 0); diff --git a/src/vs/workbench/contrib/url/browser/trustedDomains.ts b/src/vs/workbench/contrib/url/browser/trustedDomains.ts index 1e6f5743e62..f2685ea2fc3 100644 --- a/src/vs/workbench/contrib/url/browser/trustedDomains.ts +++ b/src/vs/workbench/contrib/url/browser/trustedDomains.ts @@ -156,14 +156,18 @@ async function getRemotes(fileService: IFileService, textFileService: ITextFileS const domains = await Promise.race([ new Promise(resolve => setTimeout(() => resolve([]), 2000)), Promise.all(workspaceUris.map(async workspaceUri => { - const path = workspaceUri.path; - const uri = workspaceUri.with({ path: `${path !== '/' ? path : ''}/.git/config` }); - const exists = await fileService.exists(uri); - if (!exists) { + try { + const path = workspaceUri.path; + const uri = workspaceUri.with({ path: `${path !== '/' ? path : ''}/.git/config` }); + const exists = await fileService.exists(uri); + if (!exists) { + return []; + } + const gitConfig = (await (textFileService.read(uri, { acceptTextOnly: true }).catch(() => ({ value: '' })))).value; + return extractGitHubRemotesFromGitConfig(gitConfig); + } catch { return []; } - const gitConfig = (await (textFileService.read(uri, { acceptTextOnly: true }).catch(() => ({ value: '' })))).value; - return extractGitHubRemotesFromGitConfig(gitConfig); }))]); const set = domains.reduce((set, list) => list.reduce((set, item) => set.add(item), set), new Set()); diff --git a/src/vs/workbench/contrib/watermark/browser/watermark.ts b/src/vs/workbench/contrib/watermark/browser/watermark.ts index d6840773e0b..52284e2b6c2 100644 --- a/src/vs/workbench/contrib/watermark/browser/watermark.ts +++ b/src/vs/workbench/contrib/watermark/browser/watermark.ts @@ -22,7 +22,7 @@ import * as dom from 'vs/base/browser/dom'; import { KeybindingLabel } from 'vs/base/browser/ui/keybindingLabel/keybindingLabel'; import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService'; import { CommandsRegistry } from 'vs/platform/commands/common/commands'; -import { TERMINAL_COMMAND_ID } from 'vs/workbench/contrib/terminal/common/terminal'; +import { TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal'; import { assertIsDefined } from 'vs/base/common/types'; import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuration'; import { NEW_UNTITLED_FILE_COMMAND_ID } from 'vs/workbench/contrib/files/browser/fileCommands'; @@ -46,7 +46,7 @@ const openFileOrFolderMacOnly: WatermarkEntry = { text: nls.localize('watermark. const openRecent: WatermarkEntry = { text: nls.localize('watermark.openRecent', "Open Recent"), id: 'workbench.action.openRecent' }; const newUntitledFile: WatermarkEntry = { text: nls.localize('watermark.newUntitledFile', "New Untitled File"), id: NEW_UNTITLED_FILE_COMMAND_ID }; const newUntitledFileMacOnly: WatermarkEntry = Object.assign({ mac: true }, newUntitledFile); -const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: TERMINAL_COMMAND_ID.TOGGLE }; +const toggleTerminal: WatermarkEntry = { text: nls.localize({ key: 'watermark.toggleTerminal', comment: ['toggle is a verb here'] }, "Toggle Terminal"), id: TerminalCommandId.Toggle }; const findInFiles: WatermarkEntry = { text: nls.localize('watermark.findInFiles', "Find in Files"), id: FindInFilesActionId }; const startDebugging: WatermarkEntry = { text: nls.localize('watermark.startDebugging', "Start Debugging"), id: DEBUG_START_COMMAND_ID }; diff --git a/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts b/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts index eb1458e9484..21196f4283e 100644 --- a/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts +++ b/src/vs/workbench/contrib/webview/browser/baseWebviewElement.ts @@ -372,8 +372,11 @@ export abstract class BaseWebview extends Disposable { }); } - public set localResourcesRoot(resources: URI[]) { - /** no op */ + public set localResourcesRoot(resources: readonly URI[]) { + this.content = { + ...this.content, + options: { ...this.content.options, localResourceRoots: resources } + }; } public set state(state: string | undefined) { diff --git a/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts b/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts index 109d1e547ce..90bb06bb659 100644 --- a/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts +++ b/src/vs/workbench/contrib/webview/browser/webviewFindWidget.ts @@ -46,7 +46,7 @@ export class WebviewFindWidget extends SimpleFindWidget { this._delegate.focus(); } - public onInputChanged() { + public _onInputChanged() { const val = this.inputValue; if (val) { this._delegate.startFind(val); @@ -56,17 +56,17 @@ export class WebviewFindWidget extends SimpleFindWidget { return false; } - protected onFocusTrackerFocus() { + protected _onFocusTrackerFocus() { this._findWidgetFocused.set(true); } - protected onFocusTrackerBlur() { + protected _onFocusTrackerBlur() { this._findWidgetFocused.reset(); } - protected onFindInputFocusTrackerFocus() { } + protected _onFindInputFocusTrackerFocus() { } - protected onFindInputFocusTrackerBlur() { } + protected _onFindInputFocusTrackerBlur() { } protected findFirst() { } } diff --git a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts index 41de5df3a93..f67e578973a 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspace.contribution.ts @@ -41,6 +41,7 @@ import { Schemas } from 'vs/base/common/network'; import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme'; import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; import { splitName } from 'vs/base/common/labels'; +import { IHostService } from 'vs/workbench/services/host/browser/host'; const STARTUP_PROMPT_SHOWN_KEY = 'workspace.trust.startupPrompt.shown'; @@ -58,12 +59,23 @@ export class WorkspaceTrustRequestHandler extends Disposable implements IWorkben @IConfigurationService private readonly configurationService: IConfigurationService, @IStorageService private readonly storageService: IStorageService, @IWorkspaceTrustRequestService private readonly workspaceTrustRequestService: IWorkspaceTrustRequestService, + @IHostService private readonly hostService: IHostService, ) { super(); if (isWorkspaceTrustEnabled(configurationService)) { this.registerListeners(); - this.showModalOnStart(); + + if (this.hostService.hasFocus) { + this.showModalOnStart(); + } else { + const focusDisposable = this.hostService.onDidChangeFocus(focused => { + if (focused) { + focusDisposable.dispose(); + this.showModalOnStart(); + } + }); + } } } @@ -222,7 +234,7 @@ export class WorkspaceTrustRequestHandler extends Disposable implements IWorkben return e.join(new Promise(async resolve => { // Workspace is trusted and there are added/changed folders if (trusted && (e.changes.added.length || e.changes.changed.length)) { - const addedFoldersTrustInfo = e.changes.added.map(folder => this.workspaceTrustManagementService.getFolderTrustInfo(folder.uri)); + const addedFoldersTrustInfo = e.changes.added.map(folder => this.workspaceTrustManagementService.getUriTrustInfo(folder.uri)); if (!addedFoldersTrustInfo.map(i => i.trusted).every(trusted => trusted)) { const result = await this.dialogService.show( Severity.Info, @@ -236,7 +248,7 @@ export class WorkspaceTrustRequestHandler extends Disposable implements IWorkben ); // Mark added/changed folders as trusted - this.workspaceTrustManagementService.setFoldersTrust(addedFoldersTrustInfo.map(i => i.uri), result.choice === 0); + this.workspaceTrustManagementService.setUrisTrust(addedFoldersTrustInfo.map(i => i.uri), result.choice === 0); resolve(); } @@ -490,7 +502,7 @@ class WorkspaceTrustTelemetryContribution extends Disposable implements IWorkben }; for (const folder of this.workspaceContextService.getWorkspace().folders) { - const { trusted, uri } = this.workspaceTrustManagementService.getFolderTrustInfo(folder.uri); + const { trusted, uri } = this.workspaceTrustManagementService.getUriTrustInfo(folder.uri); if (!trusted) { continue; } diff --git a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts index 82f5f4c90c9..63374ce059d 100644 --- a/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts +++ b/src/vs/workbench/contrib/workspace/browser/workspaceTrustEditor.ts @@ -333,7 +333,7 @@ export class WorkspaceTrustEditor extends EditorPane { if (!uris) { this.workspaceTrustManagementService.setWorkspaceTrust(true); } else { - this.workspaceTrustManagementService.setFoldersTrust(uris, true); + this.workspaceTrustManagementService.setUrisTrust(uris, true); } }; diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts index fc7dbe32bfb..7ef079abfc2 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts @@ -11,14 +11,12 @@ import { Event } from 'vs/base/common/event'; import { IAddressProvider } from 'vs/platform/remote/common/remoteAgentConnection'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { IExtensionService, NullExtensionService } from 'vs/workbench/services/extensions/common/extensions'; -import { IProcessEnvironment, isWindows, OperatingSystem } from 'vs/base/common/platform'; +import { isWindows } from 'vs/base/common/platform'; import { IWebviewService, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview'; import { ITunnelProvider, ITunnelService, RemoteTunnel, TunnelProviderFeatures } from 'vs/platform/remote/common/tunnel'; import { Disposable, IDisposable } from 'vs/base/common/lifecycle'; import { joinPath } from 'vs/base/common/resources'; import { VSBuffer } from 'vs/base/common/buffer'; -import { TerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; -import { ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal'; import { SearchService } from 'vs/workbench/services/search/common/searchService'; import { ISearchService } from 'vs/workbench/services/search/common/search'; import { IModelService } from 'vs/editor/common/services/modelService'; @@ -28,8 +26,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; import { IEditorService } from 'vs/workbench/services/editor/common/editorService'; import { IUriIdentityService } from 'vs/workbench/services/uriIdentity/common/uriIdentity'; import { INativeWorkbenchEnvironmentService } from 'vs/workbench/services/environment/electron-sandbox/environmentService'; -import { IShellLaunchConfigResolveOptions, ITerminalProfile, ITerminalProfileResolverService } from 'vs/workbench/contrib/terminal/common/terminal'; -import { IShellLaunchConfig } from 'vs/platform/terminal/common/terminal'; //#region Environment @@ -309,34 +305,6 @@ registerSingleton(ITunnelService, SimpleTunnelService); //#endregion -//#region Terminal Instance - -class SimpleTerminalInstanceService extends TerminalInstanceService { } - -registerSingleton(ITerminalInstanceService, SimpleTerminalInstanceService); - -//#endregion - - -//#region Terminal Profile Resolver Service - -class SimpleTerminalProfileResolverService implements ITerminalProfileResolverService { - - _serviceBrand: undefined; - - resolveIcon(shellLaunchConfig: IShellLaunchConfig, os: OperatingSystem): void { } - async resolveShellLaunchConfig(shellLaunchConfig: IShellLaunchConfig, options: IShellLaunchConfigResolveOptions): Promise { } - getDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise { throw new Error('Method not implemented.'); } - getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise { throw new Error('Method not implemented.'); } - getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise { throw new Error('Method not implemented.'); } - getShellEnvironment(remoteAuthority: string | undefined): Promise { throw new Error('Method not implemented.'); } - getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { throw new Error('Method not implemented.'); } - getSafeConfigValueFullKey(key: string): unknown | undefined { throw new Error('Method not implemented.'); } -} - -registerSingleton(ITerminalProfileResolverService, SimpleTerminalProfileResolverService); - - //#region Search Service class SimpleSearchService extends SearchService { diff --git a/src/vs/workbench/services/editor/browser/editorOverrideService.ts b/src/vs/workbench/services/editor/browser/editorOverrideService.ts index 1c3c9147463..e1aa1493b96 100644 --- a/src/vs/workbench/services/editor/browser/editorOverrideService.ts +++ b/src/vs/workbench/services/editor/browser/editorOverrideService.ts @@ -373,7 +373,7 @@ export class EditorOverrideService extends Disposable implements IEditorOverride const currentEditor = firstOrDefault(group.findEditors(resource)); // If untitled, we want all contribution points let contributionPoints = resource.scheme === Schemas.untitled ? distinct(flatten(Array.from(this._contributionPoints.values())), (contrib) => contrib.editorInfo.id) : this.findMatchingContributions(resource); - + const defaultSetting = this.getAssociationsForResource(resource)[0].viewType; // Not the most efficient way to do this, but we want to ensure the text editor is at the top of the quickpick contributionPoints = contributionPoints.sort((a, b) => { if (a.editorInfo.id === DEFAULT_EDITOR_ASSOCIATION.id) { @@ -385,13 +385,16 @@ export class EditorOverrideService extends Disposable implements IEditorOverride } }); const quickPickEntries: Array = []; + const currentlyActiveLabel = localize('promptOpenWith.currentlyActive', "Currently Active"); + const currentDefaultLabel = localize('promptOpenWith.currentDefault', "Current Default"); // Get the matching contribtuions and call resolve whether they're active for the picker contributionPoints.forEach(contribPoint => { const isActive = currentEditor ? contribPoint.editorInfo.describes(currentEditor) : false; + const isDefault = contribPoint.editorInfo.id === defaultSetting || (!defaultSetting && priorityToRank(contribPoint.editorInfo.priority) >= priorityToRank(ContributedEditorPriority.builtin)); const quickPickEntry: IQuickPickItem = { id: contribPoint.editorInfo.id, label: contribPoint.editorInfo.label, - description: isActive ? localize('promptOpenWith.currentlyActive', "Currently Active") : undefined, + description: isActive ? currentlyActiveLabel : isDefault ? currentDefaultLabel : undefined, detail: contribPoint.editorInfo.detail ?? contribPoint.editorInfo.priority, }; quickPickEntries.push(quickPickEntry); diff --git a/src/vs/workbench/services/search/test/common/searchHelpers.test.ts b/src/vs/workbench/services/search/test/common/searchHelpers.test.ts index 96f243e7593..f22e14e9c76 100644 --- a/src/vs/workbench/services/search/test/common/searchHelpers.test.ts +++ b/src/vs/workbench/services/search/test/common/searchHelpers.test.ts @@ -4,10 +4,10 @@ *--------------------------------------------------------------------------------------------*/ import * as assert from 'assert'; -import { ITextModel, FindMatch } from 'vs/editor/common/model'; -import { editorMatchesToTextSearchResults, addContextToEditorMatches } from 'vs/workbench/services/search/common/searchHelpers'; import { Range } from 'vs/editor/common/core/range'; -import { ITextQuery, QueryType, ITextSearchContext } from 'vs/workbench/services/search/common/search'; +import { FindMatch, ITextModel } from 'vs/editor/common/model'; +import { ISearchRange, ITextQuery, ITextSearchContext, QueryType } from 'vs/workbench/services/search/common/search'; +import { addContextToEditorMatches, editorMatchesToTextSearchResults } from 'vs/workbench/services/search/common/searchHelpers'; suite('SearchHelpers', () => { suite('editorMatchesToTextSearchResults', () => { @@ -17,12 +17,29 @@ suite('SearchHelpers', () => { } }; + function assertRangesEqual(actual: ISearchRange | ISearchRange[], expected: ISearchRange[]) { + if (!Array.isArray(actual)) { + // All of these tests are for arrays... + throw new Error('Expected array of ranges'); + } + + assert.strictEqual(actual.length, expected.length); + + // These are sometimes Range, sometimes SearchRange + actual.forEach((r, i) => { + const expectedRange = expected[i]; + assert.deepStrictEqual( + { startLineNumber: r.startLineNumber, startColumn: r.startColumn, endLineNumber: r.endLineNumber, endColumn: r.endColumn }, + { startLineNumber: expectedRange.startLineNumber, startColumn: expectedRange.startColumn, endLineNumber: expectedRange.endLineNumber, endColumn: expectedRange.endColumn }); + }); + } + test('simple', () => { const results = editorMatchesToTextSearchResults([new FindMatch(new Range(6, 1, 6, 2), null)], mockTextModel); assert.strictEqual(results.length, 1); assert.strictEqual(results[0].preview.text, '6\n'); - assert.deepEqual(results[0].preview.matches, [new Range(0, 0, 0, 1)]); - assert.deepEqual(results[0].ranges, [new Range(5, 0, 5, 1)]); + assertRangesEqual(results[0].preview.matches, [new Range(0, 0, 0, 1)]); + assertRangesEqual(results[0].ranges, [new Range(5, 0, 5, 1)]); }); test('multiple', () => { @@ -34,20 +51,20 @@ suite('SearchHelpers', () => { ], mockTextModel); assert.strictEqual(results.length, 2); - assert.deepEqual(results[0].preview.matches, [ + assertRangesEqual(results[0].preview.matches, [ new Range(0, 0, 0, 1), new Range(0, 3, 2, 1), ]); - assert.deepEqual(results[0].ranges, [ + assertRangesEqual(results[0].ranges, [ new Range(5, 0, 5, 1), new Range(5, 3, 7, 1), ]); assert.strictEqual(results[0].preview.text, '6\n7\n8\n'); - assert.deepEqual(results[1].preview.matches, [ + assertRangesEqual(results[1].preview.matches, [ new Range(0, 0, 1, 2), ]); - assert.deepEqual(results[1].ranges, [ + assertRangesEqual(results[1].ranges, [ new Range(8, 0, 9, 2), ]); assert.strictEqual(results[1].preview.text, '9\n10\n'); diff --git a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts index 57ee8973993..282d4872fbb 100644 --- a/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts +++ b/src/vs/workbench/services/workspaces/browser/abstractWorkspaceEditingService.ts @@ -14,7 +14,7 @@ import { ConfigurationScope, IConfigurationRegistry, Extensions as Configuration import { Registry } from 'vs/platform/registry/common/platform'; import { ICommandService } from 'vs/platform/commands/common/commands'; import { distinct } from 'vs/base/common/arrays'; -import { dirname, isEqual, isEqualAuthority } from 'vs/base/common/resources'; +import { isEqual, isEqualAuthority } from 'vs/base/common/resources'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { IFileService } from 'vs/platform/files/common/files'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; @@ -361,7 +361,7 @@ export abstract class AbstractWorkspaceEditingService implements IWorkspaceEditi private trustWorkspaceConfiguration(configPathURI: URI): void { if (this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY && this.workspaceTrustManagementService.isWorkpaceTrusted()) { - this.workspaceTrustManagementService.setFoldersTrust([dirname(configPathURI)], true); + this.workspaceTrustManagementService.setUrisTrust([configPathURI], true); } } diff --git a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts index 7d6724b71bd..cabd5e2cd9b 100644 --- a/src/vs/workbench/services/workspaces/common/workspaceTrust.ts +++ b/src/vs/workbench/services/workspaces/common/workspaceTrust.ts @@ -8,7 +8,7 @@ import { splitName } from 'vs/base/common/labels'; import { Disposable } from 'vs/base/common/lifecycle'; import { Schemas } from 'vs/base/common/network'; import { isWeb } from 'vs/base/common/platform'; -import { dirname, isEqual } from 'vs/base/common/resources'; +import { isEqual } from 'vs/base/common/resources'; import { URI } from 'vs/base/common/uri'; import { localize } from 'vs/nls'; import { IConfigurationService } from 'vs/platform/configuration/common/configuration'; @@ -131,16 +131,16 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork return true; } - const workspaceFolders = this.getWorkspaceFolders(); - const trusted = this.getFoldersTrust(workspaceFolders); + const workspaceUris = this.getWorkspaceUris(); + const trusted = this.getUrisTrust(workspaceUris); return trusted; } - private getFoldersTrust(folders: URI[]): boolean { + private getUrisTrust(uris: URI[]): boolean { let state = true; - for (const folder of folders) { - const { trusted } = this.getFolderTrustInfo(folder); + for (const uri of uris) { + const { trusted } = this.getUriTrustInfo(uri); if (!trusted) { state = trusted; @@ -151,24 +151,24 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork return state; } - private getWorkspaceFolders(): URI[] { - const folderURIs = this.workspaceService.getWorkspace().folders.map(f => f.uri); + private getWorkspaceUris(): URI[] { + const workspaceUris = this.workspaceService.getWorkspace().folders.map(f => f.uri); const workspaceConfiguration = this.workspaceService.getWorkspace().configuration; if (workspaceConfiguration && !isUntitledWorkspace(workspaceConfiguration, this.environmentService)) { - folderURIs.push(dirname(workspaceConfiguration)); + workspaceUris.push(workspaceConfiguration); } - return folderURIs; + return workspaceUris; } - public getFolderTrustInfo(folder: URI): IWorkspaceTrustUriInfo { + public getUriTrustInfo(uri: URI): IWorkspaceTrustUriInfo { let resultState = false; let maxLength = -1; - let resultUri = folder; + let resultUri = uri; for (const trustInfo of this._trustStateInfo.uriTrustInfo) { - if (this.uriIdentityService.extUri.isEqualOrParent(folder, trustInfo.uri)) { + if (this.uriIdentityService.extUri.isEqualOrParent(uri, trustInfo.uri)) { const fsPath = trustInfo.uri.fsPath; if (fsPath.length > maxLength) { maxLength = fsPath.length; @@ -181,19 +181,19 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork return { trusted: resultState, uri: resultUri }; } - setFoldersTrust(folders: URI[], trusted: boolean): void { + setUrisTrust(uris: URI[], trusted: boolean): void { let changed = false; - for (const folder of folders) { + for (const uri of uris) { if (trusted) { - const foundItem = this._trustStateInfo.uriTrustInfo.find(trustInfo => this.uriIdentityService.extUri.isEqual(trustInfo.uri, folder)); + const foundItem = this._trustStateInfo.uriTrustInfo.find(trustInfo => this.uriIdentityService.extUri.isEqual(trustInfo.uri, uri)); if (!foundItem) { - this._trustStateInfo.uriTrustInfo.push({ uri: folder, trusted: true }); + this._trustStateInfo.uriTrustInfo.push({ uri, trusted: true }); changed = true; } } else { const previousLength = this._trustStateInfo.uriTrustInfo.length; - this._trustStateInfo.uriTrustInfo = this._trustStateInfo.uriTrustInfo.filter(trustInfo => !this.uriIdentityService.extUri.isEqual(trustInfo.uri, folder)); + this._trustStateInfo.uriTrustInfo = this._trustStateInfo.uriTrustInfo.filter(trustInfo => !this.uriIdentityService.extUri.isEqual(trustInfo.uri, uri)); if (previousLength !== this._trustStateInfo.uriTrustInfo.length) { changed = true; } @@ -224,7 +224,7 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork } // If the current folder isn't trusted directly, return false - const trustInfo = this.getFolderTrustInfo(workspaceIdentifier.uri); + const trustInfo = this.getUriTrustInfo(workspaceIdentifier.uri); if (!trustInfo.trusted || !isEqual(workspaceIdentifier.uri, trustInfo.uri)) { return false; } @@ -232,7 +232,7 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork // Check if the parent is also trusted if (this.canSetParentFolderTrust()) { const { parentPath } = splitName(workspaceIdentifier.uri.fsPath); - const parentIsTrusted = this.getFolderTrustInfo(URI.file(parentPath)).trusted; + const parentIsTrusted = this.getUriTrustInfo(URI.file(parentPath)).trusted; if (parentIsTrusted) { return false; } @@ -255,13 +255,13 @@ export class WorkspaceTrustManagementService extends Disposable implements IWork if (isSingleFolderWorkspaceIdentifier(workspaceIdentifier) && workspaceIdentifier.uri.scheme === Schemas.file) { const { parentPath } = splitName(workspaceIdentifier.uri.fsPath); - this.setFoldersTrust([URI.file(parentPath)], trusted); + this.setUrisTrust([URI.file(parentPath)], trusted); } } setWorkspaceTrust(trusted: boolean): void { - const workspaceFolders = this.getWorkspaceFolders(); - this.setFoldersTrust(workspaceFolders, trusted); + const workspaceFolders = this.getWorkspaceUris(); + this.setUrisTrust(workspaceFolders, trusted); } getTrustedFolders(): URI[] { diff --git a/src/vs/workbench/services/workspaces/test/common/testWorkspaceTrustService.ts b/src/vs/workbench/services/workspaces/test/common/testWorkspaceTrustService.ts index d3d696eb9a5..68d5fb95b04 100644 --- a/src/vs/workbench/services/workspaces/test/common/testWorkspaceTrustService.ts +++ b/src/vs/workbench/services/workspaces/test/common/testWorkspaceTrustService.ts @@ -31,7 +31,7 @@ export class TestWorkspaceTrustManagementService implements IWorkspaceTrustManag throw new Error('Method not implemented.'); } - getFolderTrustInfo(folder: URI): IWorkspaceTrustUriInfo { + getUriTrustInfo(uri: URI): IWorkspaceTrustUriInfo { throw new Error('Method not implemented.'); } @@ -39,7 +39,7 @@ export class TestWorkspaceTrustManagementService implements IWorkspaceTrustManag throw new Error('Method not implemented.'); } - setFoldersTrust(folders: URI[], trusted: boolean): void { + setUrisTrust(uris: URI[], trusted: boolean): void { throw new Error('Method not implemented.'); } diff --git a/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts b/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts index 502e756ea61..8a8f2514c9b 100644 --- a/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts +++ b/src/vs/workbench/test/browser/api/mainThreadTreeViews.test.ts @@ -70,7 +70,7 @@ suite('MainThreadHostTreeView', function () { } drain(): any { return null; } }, new TestViewsService(), new TestNotificationService(), testExtensionService, new NullLogService()); - mainThreadTreeViews.$registerTreeViewDataProvider(testTreeViewId, { showCollapseAll: false, canSelectMany: false }); + mainThreadTreeViews.$registerTreeViewDataProvider(testTreeViewId, { showCollapseAll: false, canSelectMany: false, canDragAndDrop: false }); await testExtensionService.whenInstalledExtensionsRegistered(); }); diff --git a/src/vs/workbench/test/browser/quickAccess.test.ts b/src/vs/workbench/test/browser/quickAccess.test.ts index 9259c00c462..3eff27aeda0 100644 --- a/src/vs/workbench/test/browser/quickAccess.test.ts +++ b/src/vs/workbench/test/browser/quickAccess.test.ts @@ -207,7 +207,7 @@ suite('QuickAccess', () => { super('fast'); } - protected getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array { + protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Array { fastProviderCalled = true; return [{ label: 'Fast Pick' }]; @@ -220,7 +220,7 @@ suite('QuickAccess', () => { super('slow'); } - protected async getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { + protected async _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise> { slowProviderCalled = true; await timeout(1); @@ -239,7 +239,7 @@ suite('QuickAccess', () => { super('bothFastAndSlow'); } - protected getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): FastAndSlowPicks { + protected _getPicks(filter: string, disposables: DisposableStore, token: CancellationToken): FastAndSlowPicks { fastAndSlowProviderCalled = true; return { diff --git a/src/vs/workbench/test/browser/workbenchTestServices.ts b/src/vs/workbench/test/browser/workbenchTestServices.ts index 1cd91687358..61837014956 100644 --- a/src/vs/workbench/test/browser/workbenchTestServices.ts +++ b/src/vs/workbench/test/browser/workbenchTestServices.ts @@ -1592,7 +1592,7 @@ export class TestTerminalProfileResolverService implements ITerminalProfileResol async getDefaultProfile(options: IShellLaunchConfigResolveOptions): Promise { return { path: '/default', profileName: 'Default' }; } async getDefaultShell(options: IShellLaunchConfigResolveOptions): Promise { return '/default'; } async getDefaultShellArgs(options: IShellLaunchConfigResolveOptions): Promise { return []; } - async getShellEnvironment(): Promise { return process.env; } + async getEnvironment(): Promise { return process.env; } getSafeConfigValue(key: string, os: OperatingSystem): unknown | undefined { return undefined; } getSafeConfigValueFullKey(key: string): unknown | undefined { return undefined; } } @@ -1611,7 +1611,8 @@ export class TestLocalTerminalService implements ILocalTerminalService { async attachToProcess(id: number): Promise { throw new Error('Method not implemented.'); } async listProcesses(): Promise { throw new Error('Method not implemented.'); } getDefaultSystemShell(osOverride?: OperatingSystem): Promise { throw new Error('Method not implemented.'); } - getShellEnvironment(): Promise { throw new Error('Method not implemented.'); } + getEnvironment(): Promise { throw new Error('Method not implemented.'); } + getWslPath(original: string): Promise { throw new Error('Method not implemented.'); } async setTerminalLayoutInfo(argsOrLayout?: ISetTerminalLayoutInfoArgs | ITerminalsLayoutInfoById) { throw new Error('Method not implemented.'); } async getTerminalLayoutInfo(): Promise { throw new Error('Method not implemented.'); } async reduceConnectionGraceTime(): Promise { throw new Error('Method not implemented.'); } diff --git a/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts b/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts index 7336a33bd23..8094ccc6d35 100644 --- a/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts +++ b/src/vs/workbench/test/electron-browser/api/mainThreadWorkspace.test.ts @@ -31,7 +31,7 @@ suite('MainThreadWorkspace', () => { assert.strictEqual(query.folderQueries.length, 1); assert.strictEqual(query.folderQueries[0].disregardIgnoreFiles, true); - assert.deepEqual(query.includePattern, { 'foo': true }); + assert.deepStrictEqual({ ...query.includePattern }, { 'foo': true }); assert.strictEqual(query.maxResults, 10); return Promise.resolve({ results: [], messages: [] }); @@ -89,7 +89,7 @@ suite('MainThreadWorkspace', () => { instantiationService.stub(ISearchService, { fileSearch(query: IFileQuery) { assert.strictEqual(query.folderQueries[0].excludePattern, undefined); - assert.deepEqual(query.excludePattern, { 'exclude/**': true }); + assert.deepStrictEqual({ ...query.excludePattern }, { 'exclude/**': true }); return Promise.resolve({ results: [], messages: [] }); } diff --git a/src/vs/workbench/workbench.common.main.ts b/src/vs/workbench/workbench.common.main.ts index 626eb097b11..62d4ccf4e23 100644 --- a/src/vs/workbench/workbench.common.main.ts +++ b/src/vs/workbench/workbench.common.main.ts @@ -230,6 +230,7 @@ import 'vs/workbench/contrib/output/browser/outputView'; // Terminal import 'vs/workbench/contrib/terminal/common/environmentVariable.contribution'; import 'vs/workbench/contrib/terminal/common/terminalExtensionPoints.contribution'; +import 'vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution'; import 'vs/workbench/contrib/terminal/browser/terminal.contribution'; import 'vs/workbench/contrib/terminal/browser/terminalView'; diff --git a/src/vs/workbench/workbench.desktop.main.ts b/src/vs/workbench/workbench.desktop.main.ts index be79d8ca0d2..ade84c9141e 100644 --- a/src/vs/workbench/workbench.desktop.main.ts +++ b/src/vs/workbench/workbench.desktop.main.ts @@ -114,9 +114,6 @@ import 'vs/workbench/contrib/webview/electron-browser/webview.contribution'; // Extensions Management import 'vs/workbench/contrib/extensions/electron-browser/extensions.contribution'; -// Terminal -import 'vs/workbench/contrib/terminal/electron-browser/terminal.contribution'; - // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts index 054db752bbe..beba1bfee6f 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -130,6 +130,7 @@ import 'vs/workbench/contrib/extensions/browser/extensions.web.contribution'; // Terminal import 'vs/workbench/contrib/terminal/browser/terminal.web.contribution'; +import 'vs/workbench/contrib/externalTerminal/browser/externalTerminal.contribution'; import 'vs/workbench/contrib/terminal/browser/terminalInstanceService'; // Tasks diff --git a/test/automation/package.json b/test/automation/package.json index edad2f731a2..823dfa5027d 100644 --- a/test/automation/package.json +++ b/test/automation/package.json @@ -23,7 +23,7 @@ "@types/debug": "4.1.5", "@types/mkdirp": "^1.0.1", "@types/ncp": "2.0.1", - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/tmp": "0.1.0", "cpx2": "3.0.0", "mkdirp": "^1.0.4", diff --git a/test/automation/yarn.lock b/test/automation/yarn.lock index f3458adaef2..71d52ecb42f 100644 --- a/test/automation/yarn.lock +++ b/test/automation/yarn.lock @@ -26,10 +26,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-12.7.1.tgz#3b5c3a26393c19b400844ac422bd0f631a94d69d" integrity sha512-aK9jxMypeSrhiYofWWBf/T7O+KwaiAHzM4sveCdWPn71lzUSMimRnKzhXDKfKwV1kWoBo2P1aGgaIYGLf9/ljw== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/tmp@0.1.0": version "0.1.0" diff --git a/test/integration/browser/package.json b/test/integration/browser/package.json index d29777d3952..90be82a546a 100644 --- a/test/integration/browser/package.json +++ b/test/integration/browser/package.json @@ -8,7 +8,7 @@ }, "devDependencies": { "@types/mkdirp": "^1.0.1", - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/optimist": "0.0.29", "@types/rimraf": "^2.0.4", "@types/tmp": "0.1.0", diff --git a/test/integration/browser/src/index.ts b/test/integration/browser/src/index.ts index 5ce67dd0548..fae55e5fb98 100644 --- a/test/integration/browser/src/index.ts +++ b/test/integration/browser/src/index.ts @@ -32,7 +32,7 @@ const height = 800; type BrowserType = 'chromium' | 'firefox' | 'webkit'; async function runTestsInBrowser(browserType: BrowserType, endpoint: url.UrlWithStringQuery, server: cp.ChildProcess): Promise { - const args = process.platform === 'linux' && browserType === 'chromium' ? ['--no-sandbox'] : undefined; // disable sandbox to run chrome on certain Linux distros + const args = process.platform === 'linux' && browserType === 'chromium' ? ['--disable-setuid-sandbox'] : undefined; // setuid sandboxes requires root and is used in containers so we disable this to support our CI const browser = await playwright[browserType].launch({ headless: !Boolean(optimist.argv.debug), args }); const context = await browser.newContext(); const page = await context.newPage(); diff --git a/test/integration/browser/yarn.lock b/test/integration/browser/yarn.lock index 8cdd9ff7443..3adb0413636 100644 --- a/test/integration/browser/yarn.lock +++ b/test/integration/browser/yarn.lock @@ -33,10 +33,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.0.tgz#b417deda18cf8400f278733499ad5547ed1abec4" integrity sha512-GnZbirvmqZUzMgkFn70c74OQpTTUcCzlhQliTzYjQMqg+hVKcDnxdL19Ne3UdYzdMA/+W3eb646FWn/ZaT1NfQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/optimist@0.0.29": version "0.0.29" diff --git a/test/smoke/package.json b/test/smoke/package.json index 910080d8994..2b917791f7f 100644 --- a/test/smoke/package.json +++ b/test/smoke/package.json @@ -15,7 +15,7 @@ "@types/mkdirp": "^1.0.1", "@types/mocha": "^8.2.0", "@types/ncp": "2.0.1", - "@types/node": "^12.19.9", + "@types/node": "14.x", "@types/rimraf": "^2.0.4", "htmlparser2": "^3.9.2", "mkdirp": "^1.0.4", diff --git a/test/smoke/yarn.lock b/test/smoke/yarn.lock index 979bf3b2677..ca5132ad490 100644 --- a/test/smoke/yarn.lock +++ b/test/smoke/yarn.lock @@ -50,10 +50,10 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.0.tgz#390ea202539c61c8fa6ba4428b57e05bc36dc47b" integrity sha512-uM4mnmsIIPK/yeO+42F2RQhGUIs39K2RFmugcJANppXe6J1nvH87PvzPZYpza7Xhhs8Yn9yIAVdLZ84z61+0xQ== -"@types/node@^12.19.9": - version "12.19.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.9.tgz#990ad687ad8b26ef6dcc34a4f69c33d40c95b679" - integrity sha512-yj0DOaQeUrk3nJ0bd3Y5PeDRJ6W0r+kilosLA+dzF3dola/o9hxhMSg2sFvVcA2UHS5JSOsZp4S0c1OEXc4m1Q== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== "@types/rimraf@^2.0.4": version "2.0.4" diff --git a/test/unit/browser/index.js b/test/unit/browser/index.js index 02f0e18c6d4..92a9cc7264d 100644 --- a/test/unit/browser/index.js +++ b/test/unit/browser/index.js @@ -146,7 +146,7 @@ function consoleLogFn(msg) { } async function runTestsInBrowser(testModules, browserType) { - const args = process.platform === 'linux' && browserType === 'chromium' ? ['--no-sandbox'] : undefined; // disable sandbox to run chrome on certain Linux distros + const args = process.platform === 'linux' && browserType === 'chromium' ? ['--disable-setuid-sandbox'] : undefined; // setuid sandboxes requires root and is used in containers so we disable this to support our CI const browser = await playwright[browserType].launch({ headless: !Boolean(argv.debug), args }); const context = await browser.newContext(); const page = await context.newPage(); diff --git a/yarn.lock b/yarn.lock index 0cf5d054862..11e952222f1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -489,6 +489,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-4.2.22.tgz#cf488a0f6b4a9c245d09927f4f757ca278b9c8ce" integrity sha512-LXRap3bb4AjtLZ5NOFc4ssVZrQPTgdPcNm++0SEJuJZaOA+xHkojJNYqy33A5q/94BmG5tA6yaMeD4VdCv5aSA== +"@types/node@14.x": + version "14.14.43" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.43.tgz#26bcbb0595b305400e8ceaf9a127a7f905ae49c8" + integrity sha512-3pwDJjp1PWacPTpH0LcfhgjvurQvrZFBrC6xxjaUEZ7ifUtT32jtjPxEMMblpqd2Mvx+k8haqQJLQxolyGN/cQ== + "@types/node@>= 8": version "14.14.22" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.22.tgz#0d29f382472c4ccf3bd96ff0ce47daf5b7b84b18" @@ -499,7 +504,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.21.tgz#7e8a0c34cf29f4e17a36e9bd0ea72d45ba03908e" integrity sha512-CBgLNk4o3XMnqMc0rhb6lc77IwShMEglz05deDcn2lQxyXEZivfwgYJu7SMha9V5XcrP6qZuevTHV/QrN2vjKQ== -"@types/node@^14.14.37", "@types/node@^14.6.2": +"@types/node@^14.6.2": version "14.14.37" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.37.tgz#a3dd8da4eb84a996c36e331df98d82abd76b516e" integrity sha512-XYmBiy+ohOR4Lh5jE379fV2IU+6Jn4g5qASinhitfyO71b/sCo6MKsMLF5tc7Zf2CE8hViVQyYSobJNke8OvUw==