Archived
Merge branch 'ads-master-vscode-2020-05-08T03-58-31'
This commit is contained in:
Vendored
+19
@@ -145,6 +145,25 @@
|
||||
"order": 2
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"name": "Main Process",
|
||||
"runtimeExecutable": "${workspaceFolder}/scripts/code.sh",
|
||||
"windows": {
|
||||
"runtimeExecutable": "${workspaceFolder}/scripts/code.bat",
|
||||
},
|
||||
"runtimeArgs": [
|
||||
"--no-cached-data"
|
||||
],
|
||||
"outFiles": [
|
||||
"${workspaceFolder}/out/**/*.js"
|
||||
],
|
||||
"presentation": {
|
||||
"group": "1_vscode",
|
||||
"order": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
|
||||
@@ -2,54 +2,76 @@ steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.13.0"
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3 # {{SQL CARBON EDIT}} update version
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
|
||||
- script: |
|
||||
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
|
||||
displayName: Install Dependencies
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
yarn electron x64
|
||||
displayName: Download Electron
|
||||
|
||||
- script: |
|
||||
yarn gulp hygiene
|
||||
displayName: Run Hygiene Checks
|
||||
|
||||
- script: | # {{SQL CARBON EDIT}} add step
|
||||
yarn strict-vscode
|
||||
displayName: Run Strict Null Check.
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} remove step
|
||||
# yarn monaco-compile-check
|
||||
# displayName: Run Monaco Editor Checks
|
||||
|
||||
- script: |
|
||||
yarn valid-layers-check
|
||||
displayName: Run Valid Layers Checks
|
||||
|
||||
- script: |
|
||||
yarn compile
|
||||
displayName: Compile Sources
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} remove step
|
||||
# yarn download-builtin-extensions
|
||||
# displayName: Download Built-in Extensions
|
||||
|
||||
- script: |
|
||||
./scripts/test.sh --tfs "Unit Tests"
|
||||
displayName: Run Unit Tests (Electron)
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} disable
|
||||
# yarn test-browser --browser chromium --browser webkit --browser firefox
|
||||
# displayName: Run Unit Tests (Browser)
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} disable
|
||||
# ./scripts/test-integration.sh --tfs "Integration Tests"
|
||||
# displayName: Run Integration Tests (Electron)
|
||||
|
||||
# - task: PublishPipelineArtifact@0
|
||||
# inputs:
|
||||
# artifactName: crash-dump-macos
|
||||
# targetPath: .build/crashes
|
||||
# displayName: 'Publish Crash Reports'
|
||||
# condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Tests Results
|
||||
inputs:
|
||||
|
||||
@@ -2,13 +2,5 @@
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.disable-library-validation</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -152,15 +152,29 @@ steps:
|
||||
displayName: Run smoke tests (Browser)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: crash-dump-macos
|
||||
targetPath: .build/crashes
|
||||
displayName: 'Publish Crash Reports'
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
APP_ROOT=$(agent.builddirectory)/VSCode-darwin
|
||||
APP_NAME="`ls $APP_ROOT | head -n 1`"
|
||||
HELPER_APP_NAME="`echo $APP_NAME | sed -e 's/^Visual Studio //;s/\.app$//'`"
|
||||
APP_FRAMEWORK_PATH="$APP_ROOT/$APP_NAME/Contents/Frameworks"
|
||||
security create-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
|
||||
security default-keychain -s $(agent.tempdirectory)/buildagent.keychain
|
||||
security unlock-keychain -p pwd $(agent.tempdirectory)/buildagent.keychain
|
||||
echo "$(macos-developer-certificate)" | base64 -D > $(agent.tempdirectory)/cert.p12
|
||||
security import $(agent.tempdirectory)/cert.p12 -k $(agent.tempdirectory)/buildagent.keychain -P "$(macos-developer-certificate-key)" -T /usr/bin/codesign
|
||||
security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k pwd $(agent.tempdirectory)/buildagent.keychain
|
||||
codesign -s 99FM488X57 --deep --force --options runtime --entitlements build/azure-pipelines/darwin/entitlements.plist $(agent.builddirectory)/VSCode-darwin/*.app
|
||||
codesign -s 99FM488X57 --deep --force --options runtime --entitlements build/azure-pipelines/darwin/entitlements.plist "$APP_ROOT"/*.app
|
||||
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-gpu-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (GPU).app"
|
||||
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-plugin-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (Plugin).app"
|
||||
codesign -s 99FM488X57 --force --options runtime --entitlements build/azure-pipelines/darwin/helper-renderer-entitlements.plist "$APP_FRAMEWORK_PATH/$HELPER_APP_NAME Helper (Renderer).app"
|
||||
displayName: Set Hardened Entitlements
|
||||
|
||||
- script: |
|
||||
|
||||
@@ -7,57 +7,80 @@ steps:
|
||||
sudo chmod +x /etc/init.d/xvfb
|
||||
sudo update-rc.d xvfb defaults
|
||||
sudo service xvfb start
|
||||
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.13.0"
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
|
||||
- script: |
|
||||
CHILD_CONCURRENCY=1 yarn --frozen-lockfile
|
||||
displayName: Install Dependencies
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- script: |
|
||||
yarn electron x64
|
||||
displayName: Download Electron
|
||||
|
||||
- script: |
|
||||
yarn gulp hygiene
|
||||
displayName: Run Hygiene Checks
|
||||
|
||||
- script: | # {{SQL CARBON EDIT}} add strict null check
|
||||
yarn strict-vscode
|
||||
|
||||
displayName: Run Strict Null Check
|
||||
# - script: | {{SQL CARBON EDIT}} remove monaco editor checks
|
||||
# yarn monaco-compile-check
|
||||
# displayName: Run Monaco Editor Checks
|
||||
|
||||
- script: |
|
||||
yarn valid-layers-check
|
||||
displayName: Run Valid Layers Checks
|
||||
|
||||
- script: |
|
||||
yarn compile
|
||||
displayName: Compile Sources
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} remove step
|
||||
# yarn download-builtin-extensions
|
||||
# displayName: Download Built-in Extensions
|
||||
|
||||
- script: |
|
||||
DISPLAY=:10 ./scripts/test.sh --tfs "Unit Tests"
|
||||
displayName: Run Unit Tests (Electron)
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} disable
|
||||
# DISPLAY=:10 yarn test-browser --browser chromium
|
||||
# displayName: Run Unit Tests (Browser)
|
||||
|
||||
# - script: | {{SQL CARBON EDIT}} disable
|
||||
# DISPLAY=:10 ./scripts/test-integration.sh --tfs "Integration Tests"
|
||||
# displayName: Run Integration Tests (Electron)
|
||||
|
||||
# - task: PublishPipelineArtifact@0
|
||||
# inputs:
|
||||
# artifactName: crash-dump-linux
|
||||
# targetPath: .build/crashes
|
||||
# displayName: 'Publish Crash Reports'
|
||||
# condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Tests Results
|
||||
inputs:
|
||||
|
||||
@@ -140,6 +140,13 @@ steps:
|
||||
displayName: Run integration tests (Browser)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: crash-dump-linux
|
||||
targetPath: .build/crashes
|
||||
displayName: 'Publish Crash Reports'
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- script: |
|
||||
set -e
|
||||
yarn gulp "vscode-linux-x64-build-deb"
|
||||
|
||||
@@ -2,59 +2,83 @@ steps:
|
||||
- task: NodeTool@0
|
||||
inputs:
|
||||
versionSpec: "12.13.0"
|
||||
|
||||
- task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@3 # {{SQL CARBON EDIT}} update version
|
||||
inputs:
|
||||
versionSpec: "1.x"
|
||||
|
||||
- task: UsePythonVersion@0
|
||||
inputs:
|
||||
versionSpec: '2.x'
|
||||
addToPath: true
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
|
||||
- powershell: |
|
||||
yarn --frozen-lockfile
|
||||
env:
|
||||
CHILD_CONCURRENCY: "1"
|
||||
displayName: Install Dependencies
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||
inputs:
|
||||
keyfile: 'build/.cachesalt, .yarnrc, remote/.yarnrc, **/yarn.lock, !**/node_modules/**/yarn.lock, !**/.*/**/yarn.lock, !samples/**/yarn.lock'
|
||||
targetfolder: '**/node_modules, !**/node_modules/**/node_modules, !samples/**/node_modules'
|
||||
vstsFeed: 'npm-cache' # {{SQL CARBON EDIT}} update build cache
|
||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||
|
||||
- powershell: |
|
||||
yarn electron
|
||||
displayName: Download Electron
|
||||
|
||||
- script: |
|
||||
yarn gulp hygiene
|
||||
displayName: Run Hygiene Checks
|
||||
|
||||
- script: | # {{SQL CARBON EDIT}} add step
|
||||
yarn strict-vscode
|
||||
displayName: Run Strict Null Check
|
||||
|
||||
# - powershell: | {{SQL CARBON EDIT}} remove step
|
||||
# yarn monaco-compile-check
|
||||
# displayName: Run Monaco Editor Checks
|
||||
|
||||
- script: |
|
||||
yarn valid-layers-check
|
||||
displayName: Run Valid Layers Checks
|
||||
|
||||
- powershell: |
|
||||
yarn compile
|
||||
displayName: Compile Sources
|
||||
|
||||
# - powershell: | {{SQL CARBON EDIT}} remove step
|
||||
# yarn download-builtin-extensions
|
||||
# displayName: Download Built-in Extensions
|
||||
|
||||
- powershell: |
|
||||
.\scripts\test.bat --tfs "Unit Tests"
|
||||
displayName: Run Unit Tests (Electron)
|
||||
|
||||
# - powershell: | {{SQL CARBON EDIT}} disable
|
||||
# yarn test-browser --browser chromium --browser firefox
|
||||
# displayName: Run Unit Tests (Browser)
|
||||
|
||||
# - powershell: | {{SQL CARBON EDIT}} disable
|
||||
# .\scripts\test-integration.bat --tfs "Integration Tests"
|
||||
# displayName: Run Integration Tests (Electron)
|
||||
|
||||
# - task: PublishPipelineArtifact@0
|
||||
# displayName: 'Publish Crash Reports'
|
||||
# inputs:
|
||||
# artifactName: crash-dump-windows
|
||||
# targetPath: .build\crashes
|
||||
# condition: succeededOrFailed()
|
||||
|
||||
- task: PublishTestResults@2
|
||||
displayName: Publish Tests Results
|
||||
inputs:
|
||||
|
||||
@@ -149,6 +149,13 @@ steps:
|
||||
displayName: Run integration tests (Browser)
|
||||
condition: and(succeeded(), eq(variables['VSCODE_STEP_ON_IT'], 'false'))
|
||||
|
||||
- task: PublishPipelineArtifact@0
|
||||
inputs:
|
||||
artifactName: crash-dump-windows-$(VSCODE_ARCH)
|
||||
targetPath: .build\crashes
|
||||
displayName: 'Publish Crash Reports'
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@1
|
||||
inputs:
|
||||
ConnectedServiceName: 'ESRP CodeSign'
|
||||
|
||||
@@ -430,6 +430,7 @@ function markNodes(languageService, options) {
|
||||
|| ts.isIndexSignatureDeclaration(member)
|
||||
|| ts.isCallSignatureDeclaration(member)
|
||||
|| memberName === '[Symbol.iterator]'
|
||||
|| memberName === '[Symbol.toStringTag]'
|
||||
|| memberName === 'toJSON'
|
||||
|| memberName === 'toString'
|
||||
|| memberName === 'dispose' // TODO: keeping all `dispose` methods
|
||||
|
||||
@@ -548,6 +548,7 @@ function markNodes(languageService: ts.LanguageService, options: ITreeShakingOpt
|
||||
|| ts.isIndexSignatureDeclaration(member)
|
||||
|| ts.isCallSignatureDeclaration(member)
|
||||
|| memberName === '[Symbol.iterator]'
|
||||
|| memberName === '[Symbol.toStringTag]'
|
||||
|| memberName === 'toJSON'
|
||||
|| memberName === 'toString'
|
||||
|| memberName === 'dispose'// TODO: keeping all `dispose` methods
|
||||
|
||||
@@ -409,6 +409,11 @@
|
||||
"command": "git.timeline.copyCommitMessage",
|
||||
"title": "%command.timelineCopyCommitMessage%",
|
||||
"category": "Git"
|
||||
},
|
||||
{
|
||||
"command": "git.rebaseAbort",
|
||||
"title": "%command.rebaseAbort%",
|
||||
"category": "Git"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"command.showOutput": "Show Git Output",
|
||||
"command.ignore": "Add to .gitignore",
|
||||
"command.revealInExplorer": "Reveal in Side Bar",
|
||||
"command.rebaseAbort": "Abort Rebase",
|
||||
"command.stashIncludeUntracked": "Stash (Include Untracked)",
|
||||
"command.stash": "Stash",
|
||||
"command.stashPop": "Pop Stash...",
|
||||
|
||||
@@ -2494,6 +2494,10 @@ export class CommandCenter {
|
||||
env.clipboard.writeText(item.message);
|
||||
}
|
||||
|
||||
@command('git.rebaseAbort', { repository: true })
|
||||
async rebaseAbort(repository: Repository): Promise<void> {
|
||||
await repository.rebaseAbort();
|
||||
}
|
||||
|
||||
private createCommand(id: string, key: string, method: Function, options: CommandOptions): (...args: any[]) => any {
|
||||
const result = (...args: any[]) => {
|
||||
|
||||
@@ -1333,6 +1333,10 @@ export class Repository {
|
||||
}
|
||||
}
|
||||
|
||||
async rebaseAbort(): Promise<void> {
|
||||
await this.run(['rebase', '--abort']);
|
||||
}
|
||||
|
||||
async rebaseContinue(): Promise<void> {
|
||||
const args = ['rebase', '--continue'];
|
||||
|
||||
|
||||
@@ -303,6 +303,7 @@ export const enum Operation {
|
||||
CheckIgnore = 'CheckIgnore',
|
||||
GetObjectDetails = 'GetObjectDetails',
|
||||
SubmoduleUpdate = 'SubmoduleUpdate',
|
||||
RebaseAbort = 'RebaseAbort',
|
||||
RebaseContinue = 'RebaseContinue',
|
||||
FindTrackingBranches = 'GetTracking',
|
||||
Apply = 'Apply',
|
||||
@@ -1331,6 +1332,10 @@ export class Repository implements Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
async rebaseAbort(): Promise<void> {
|
||||
await this.run(Operation.RebaseAbort, async () => await this.repository.rebaseAbort());
|
||||
}
|
||||
|
||||
checkIgnore(filePaths: string[]): Promise<Set<string>> {
|
||||
return this.run(Operation.CheckIgnore, () => {
|
||||
return new Promise<Set<string>>((resolve, reject) => {
|
||||
|
||||
@@ -77,6 +77,12 @@ interface JSONSchemaSettings {
|
||||
schema?: any;
|
||||
}
|
||||
|
||||
namespace SettingIds {
|
||||
export const enableFormatter = 'json.format.enable';
|
||||
export const enableSchemaDownload = 'json.schemaDownload.enable';
|
||||
export const maxItemsComputed = 'json.maxItemsComputed';
|
||||
}
|
||||
|
||||
let telemetryReporter: TelemetryReporter | undefined;
|
||||
|
||||
export function activate(context: ExtensionContext) {
|
||||
@@ -107,10 +113,8 @@ export function activate(context: ExtensionContext) {
|
||||
id: 'status.json.resolveError',
|
||||
name: localize('json.resolveError', "JSON: Schema Resolution Error"),
|
||||
alignment: StatusBarAlignment.Right,
|
||||
priority: 0
|
||||
priority: 0,
|
||||
});
|
||||
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
|
||||
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema.') + ' ' + localize('json.clickToRetry', 'Click to retry.');
|
||||
schemaResolutionErrorStatusBarItem.text = '$(alert)';
|
||||
toDispose.push(schemaResolutionErrorStatusBarItem);
|
||||
|
||||
@@ -200,6 +204,7 @@ export function activate(context: ExtensionContext) {
|
||||
toDispose.push(disposable);
|
||||
client.onReady().then(() => {
|
||||
const schemaDocuments: { [uri: string]: boolean } = {};
|
||||
let schemaDownloadEnabled = true;
|
||||
|
||||
// handle content request
|
||||
client.onRequest(VSCodeContentRequest.type, (uriPath: string) => {
|
||||
@@ -208,12 +213,16 @@ export function activate(context: ExtensionContext) {
|
||||
return Promise.reject(new Error(localize('untitled.schema', 'Unable to load {0}', uri.toString())));
|
||||
}
|
||||
if (uri.scheme !== 'http' && uri.scheme !== 'https') {
|
||||
if (schemaDownloadEnabled) {
|
||||
return workspace.openTextDocument(uri).then(doc => {
|
||||
schemaDocuments[uri.toString()] = true;
|
||||
return doc.getText();
|
||||
}, error => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
} else {
|
||||
return Promise.reject(localize('schemaDownloadDisabled', 'Downloading schemas is disabled through setting \'{0}\'', SettingIds.enableSchemaDownload));
|
||||
}
|
||||
} else {
|
||||
if (telemetryReporter && uri.authority === 'schema.management.azure.com') {
|
||||
/* __GDPR__
|
||||
@@ -294,30 +303,26 @@ export function activate(context: ExtensionContext) {
|
||||
client.sendNotification(SchemaAssociationNotification.type, getSchemaAssociations(context));
|
||||
});
|
||||
|
||||
// manually register / deregister format provider based on the `html.format.enable` setting avoiding issues with late registration. See #71652.
|
||||
// manually register / deregister format provider based on the `json.format.enable` setting avoiding issues with late registration. See #71652.
|
||||
updateFormatterRegistration();
|
||||
toDispose.push({ dispose: () => rangeFormatting && rangeFormatting.dispose() });
|
||||
toDispose.push(workspace.onDidChangeConfiguration(e => e.affectsConfiguration('html.format.enable') && updateFormatterRegistration()));
|
||||
|
||||
updateSchemaDownloadSetting();
|
||||
|
||||
toDispose.push(workspace.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration(SettingIds.enableFormatter)) {
|
||||
updateFormatterRegistration();
|
||||
} else if (e.affectsConfiguration(SettingIds.enableSchemaDownload)) {
|
||||
updateSchemaDownloadSetting();
|
||||
}
|
||||
}));
|
||||
|
||||
client.onNotification(ResultLimitReachedNotification.type, message => {
|
||||
window.showInformationMessage(`${message}\nUse setting 'json.maxItemsComputed' to configure the limit.`);
|
||||
window.showInformationMessage(`${message}\n${localize('configureLimit', 'Use setting \'{0}\' to configure the limit.', SettingIds.maxItemsComputed)}`);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const languageConfiguration: LanguageConfiguration = {
|
||||
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
|
||||
indentationRules: {
|
||||
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
|
||||
decreaseIndentPattern: /^\s*[}\]],?\s*$/
|
||||
}
|
||||
};
|
||||
languages.setLanguageConfiguration('json', languageConfiguration);
|
||||
languages.setLanguageConfiguration('jsonc', languageConfiguration);
|
||||
|
||||
function updateFormatterRegistration() {
|
||||
const formatEnabled = workspace.getConfiguration().get('json.format.enable');
|
||||
const formatEnabled = workspace.getConfiguration().get(SettingIds.enableFormatter);
|
||||
if (!formatEnabled && rangeFormatting) {
|
||||
rangeFormatting.dispose();
|
||||
rangeFormatting = undefined;
|
||||
@@ -340,6 +345,31 @@ export function activate(context: ExtensionContext) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function updateSchemaDownloadSetting() {
|
||||
schemaDownloadEnabled = workspace.getConfiguration().get(SettingIds.enableSchemaDownload) !== false;
|
||||
if (schemaDownloadEnabled) {
|
||||
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionErrorMessage', 'Unable to resolve schema. Click to retry.');
|
||||
schemaResolutionErrorStatusBarItem.command = '_json.retryResolveSchema';
|
||||
handleRetryResolveSchemaCommand();
|
||||
} else {
|
||||
schemaResolutionErrorStatusBarItem.tooltip = localize('json.schemaResolutionDisabledMessage', 'Downloading schemas is disabled. Click to configure.');
|
||||
schemaResolutionErrorStatusBarItem.command = { command: 'workbench.action.openSettings', arguments: [SettingIds.enableSchemaDownload], title: '' };
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
const languageConfiguration: LanguageConfiguration = {
|
||||
wordPattern: /("(?:[^\\\"]*(?:\\.)?)*"?)|[^\s{}\[\],:]+/,
|
||||
indentationRules: {
|
||||
increaseIndentPattern: /({+(?=([^"]*"[^"]*")*[^"}]*$))|(\[+(?=([^"]*"[^"]*")*[^"\]]*$))/,
|
||||
decreaseIndentPattern: /^\s*[}\]],?\s*$/
|
||||
}
|
||||
};
|
||||
languages.setLanguageConfiguration('json', languageConfiguration);
|
||||
languages.setLanguageConfiguration('jsonc', languageConfiguration);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -386,7 +416,7 @@ function getSchemaAssociations(_context: ExtensionContext): ISchemaAssociation[]
|
||||
function getSettings(): Settings {
|
||||
const httpSettings = workspace.getConfiguration('http');
|
||||
|
||||
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get('json.maxItemsComputed')))) || 5000;
|
||||
const resultLimit: number = Math.trunc(Math.max(0, Number(workspace.getConfiguration().get(SettingIds.maxItemsComputed)))) || 5000;
|
||||
|
||||
const settings: Settings = {
|
||||
http: {
|
||||
|
||||
@@ -95,6 +95,12 @@
|
||||
"type": "number",
|
||||
"default": 5000,
|
||||
"description": "%json.maxItemsComputed.desc%"
|
||||
},
|
||||
"json.schemaDownload.enable": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "%json.enableSchemaDownload.desc%",
|
||||
"tags": ["usesOnlineServices"]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
"json.colorDecorators.enable.deprecationMessage": "The setting `json.colorDecorators.enable` has been deprecated in favor of `editor.colorDecorators`.",
|
||||
"json.schemaResolutionErrorMessage": "Unable to resolve schema.",
|
||||
"json.clickToRetry": "Click to retry.",
|
||||
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons)."
|
||||
"json.maxItemsComputed.desc": "The maximum number of outline symbols and folding regions computed (limited for performance reasons).",
|
||||
"json.enableSchemaDownload.desc": "When enabled, JSON schemas can be fetched from http and https locations."
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ function createContext(): TestContext {
|
||||
storagePath: '',
|
||||
globalStoragePath: '',
|
||||
logPath: '',
|
||||
extensionUri: vscode.Uri.parse('')
|
||||
extensionUri: vscode.Uri.parse(''),
|
||||
environmentVariableCollection: { } as any
|
||||
},
|
||||
outputChannel: {
|
||||
name: '',
|
||||
|
||||
@@ -22,6 +22,7 @@ export class MockExtensionContext implements vscode.ExtensionContext {
|
||||
constructor() {
|
||||
this.subscriptions = [];
|
||||
}
|
||||
environmentVariableCollection: vscode.EnvironmentVariableCollection;
|
||||
}
|
||||
|
||||
export class MockOutputChannel implements vscode.OutputChannel {
|
||||
|
||||
@@ -33,7 +33,8 @@ export function createContext(): TestContext {
|
||||
storagePath: '',
|
||||
globalStoragePath: '',
|
||||
logPath: '',
|
||||
extensionUri: vscode.Uri.parse('')
|
||||
extensionUri: vscode.Uri.parse(''),
|
||||
environmentVariableCollection: undefined as any
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ let fs = require('fs');
|
||||
let https = require('https');
|
||||
let url = require('url');
|
||||
|
||||
// list of languagesIs not shipped with VSCode. The information is used to associate an icon with a language association
|
||||
// list of languagesId not shipped with VSCode. The information is used to associate an icon with a language association
|
||||
let nonBuiltInLanguages = { // { fileNames, extensions }
|
||||
"r": { extensions: ['r', 'rhistory', 'rprofile', 'rt'] },
|
||||
"argdown": { extensions: ['ad', 'adown', 'argdown', 'argdn'] },
|
||||
@@ -32,10 +32,16 @@ let nonBuiltInLanguages = { // { fileNames, extensions }
|
||||
"haml": { extensions: ['haml'] },
|
||||
"stylus": { extensions: ['styl'] },
|
||||
"vala": { extensions: ['vala'] },
|
||||
"todo": { fileNames: ['todo'] },
|
||||
"jsonc": { extensions: ['json'] }
|
||||
"todo": { fileNames: ['todo'] }
|
||||
};
|
||||
|
||||
// list of languagesId that inherit the icon from another language
|
||||
let inheritIconFromLanguage = {
|
||||
"jsonc": 'json',
|
||||
"postcss": 'css',
|
||||
"django-html": 'html'
|
||||
}
|
||||
|
||||
let FROM_DISK = true; // set to true to take content from a repo checked out next to the vscode repo
|
||||
|
||||
let font, fontMappingsFile, fileAssociationFile, colorsFile;
|
||||
@@ -358,6 +364,16 @@ exports.update = function () {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (let lang in inheritIconFromLanguage) {
|
||||
let superLang = inheritIconFromLanguage[lang];
|
||||
let def = lang2Def[superLang];
|
||||
if (def) {
|
||||
lang2Def[lang] = def;
|
||||
} else {
|
||||
console.log('skipping icon def for ' + lang + ': no icon for ' + superLang + ' defined');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return download(colorsFile).then(function (content) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"git": {
|
||||
"name": "seti-ui",
|
||||
"repositoryUrl": "https://github.com/jesseweed/seti-ui",
|
||||
"commitHash": "4b3e0a3d0ca8999430bc3aa9f2c8324e6922b3de"
|
||||
"commitHash": "8f22764c37feb7f706465f5186132111a2401b6b"
|
||||
}
|
||||
},
|
||||
"version": "0.1.0"
|
||||
|
||||
Binary file not shown.
@@ -966,399 +966,413 @@
|
||||
"fontCharacter": "\\E06C",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_pug_light": {
|
||||
"_prolog_light": {
|
||||
"fontCharacter": "\\E06E",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_prolog": {
|
||||
"fontCharacter": "\\E06E",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_pug_light": {
|
||||
"fontCharacter": "\\E06F",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_pug": {
|
||||
"fontCharacter": "\\E06E",
|
||||
"fontCharacter": "\\E06F",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_puppet_light": {
|
||||
"fontCharacter": "\\E06F",
|
||||
"fontCharacter": "\\E070",
|
||||
"fontColor": "#b7b73b"
|
||||
},
|
||||
"_puppet": {
|
||||
"fontCharacter": "\\E06F",
|
||||
"fontCharacter": "\\E070",
|
||||
"fontColor": "#cbcb41"
|
||||
},
|
||||
"_python_light": {
|
||||
"fontCharacter": "\\E070",
|
||||
"fontCharacter": "\\E071",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_python": {
|
||||
"fontCharacter": "\\E070",
|
||||
"fontCharacter": "\\E071",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_react_light": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_react": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_react_1_light": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_react_1": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_react_2_light": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#b7b73b"
|
||||
},
|
||||
"_react_2": {
|
||||
"fontCharacter": "\\E072",
|
||||
"fontCharacter": "\\E073",
|
||||
"fontColor": "#cbcb41"
|
||||
},
|
||||
"_reasonml_light": {
|
||||
"fontCharacter": "\\E073",
|
||||
"fontCharacter": "\\E074",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_reasonml": {
|
||||
"fontCharacter": "\\E073",
|
||||
"fontCharacter": "\\E074",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_rmd_light": {
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_rmd": {
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_rollup_light": {
|
||||
"fontCharacter": "\\E074",
|
||||
"fontCharacter": "\\E075",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_rollup": {
|
||||
"fontCharacter": "\\E074",
|
||||
"fontCharacter": "\\E075",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_ruby_light": {
|
||||
"fontCharacter": "\\E075",
|
||||
"fontCharacter": "\\E076",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_ruby": {
|
||||
"fontCharacter": "\\E075",
|
||||
"fontCharacter": "\\E076",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_rust_light": {
|
||||
"fontCharacter": "\\E076",
|
||||
"fontCharacter": "\\E077",
|
||||
"fontColor": "#627379"
|
||||
},
|
||||
"_rust": {
|
||||
"fontCharacter": "\\E076",
|
||||
"fontCharacter": "\\E077",
|
||||
"fontColor": "#6d8086"
|
||||
},
|
||||
"_salesforce_light": {
|
||||
"fontCharacter": "\\E077",
|
||||
"fontCharacter": "\\E078",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_salesforce": {
|
||||
"fontCharacter": "\\E077",
|
||||
"fontCharacter": "\\E078",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_sass_light": {
|
||||
"fontCharacter": "\\E078",
|
||||
"fontCharacter": "\\E079",
|
||||
"fontColor": "#dd4b78"
|
||||
},
|
||||
"_sass": {
|
||||
"fontCharacter": "\\E078",
|
||||
"fontCharacter": "\\E079",
|
||||
"fontColor": "#f55385"
|
||||
},
|
||||
"_sbt_light": {
|
||||
"fontCharacter": "\\E079",
|
||||
"fontCharacter": "\\E07A",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_sbt": {
|
||||
"fontCharacter": "\\E079",
|
||||
"fontCharacter": "\\E07A",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_scala_light": {
|
||||
"fontCharacter": "\\E07A",
|
||||
"fontCharacter": "\\E07B",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_scala": {
|
||||
"fontCharacter": "\\E07A",
|
||||
"fontCharacter": "\\E07B",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_shell_light": {
|
||||
"fontCharacter": "\\E07D",
|
||||
"fontCharacter": "\\E07E",
|
||||
"fontColor": "#455155"
|
||||
},
|
||||
"_shell": {
|
||||
"fontCharacter": "\\E07D",
|
||||
"fontCharacter": "\\E07E",
|
||||
"fontColor": "#4d5a5e"
|
||||
},
|
||||
"_slim_light": {
|
||||
"fontCharacter": "\\E07E",
|
||||
"fontCharacter": "\\E07F",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_slim": {
|
||||
"fontCharacter": "\\E07E",
|
||||
"fontCharacter": "\\E07F",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_smarty_light": {
|
||||
"fontCharacter": "\\E07F",
|
||||
"fontCharacter": "\\E080",
|
||||
"fontColor": "#b7b73b"
|
||||
},
|
||||
"_smarty": {
|
||||
"fontCharacter": "\\E07F",
|
||||
"fontCharacter": "\\E080",
|
||||
"fontColor": "#cbcb41"
|
||||
},
|
||||
"_spring_light": {
|
||||
"fontCharacter": "\\E080",
|
||||
"fontCharacter": "\\E081",
|
||||
"fontColor": "#7fae42"
|
||||
},
|
||||
"_spring": {
|
||||
"fontCharacter": "\\E080",
|
||||
"fontCharacter": "\\E081",
|
||||
"fontColor": "#8dc149"
|
||||
},
|
||||
"_stylelint_light": {
|
||||
"fontCharacter": "\\E081",
|
||||
"fontCharacter": "\\E082",
|
||||
"fontColor": "#bfc2c1"
|
||||
},
|
||||
"_stylelint": {
|
||||
"fontCharacter": "\\E081",
|
||||
"fontCharacter": "\\E082",
|
||||
"fontColor": "#d4d7d6"
|
||||
},
|
||||
"_stylelint_1_light": {
|
||||
"fontCharacter": "\\E081",
|
||||
"fontCharacter": "\\E082",
|
||||
"fontColor": "#455155"
|
||||
},
|
||||
"_stylelint_1": {
|
||||
"fontCharacter": "\\E081",
|
||||
"fontCharacter": "\\E082",
|
||||
"fontColor": "#4d5a5e"
|
||||
},
|
||||
"_stylus_light": {
|
||||
"fontCharacter": "\\E082",
|
||||
"fontCharacter": "\\E083",
|
||||
"fontColor": "#7fae42"
|
||||
},
|
||||
"_stylus": {
|
||||
"fontCharacter": "\\E082",
|
||||
"fontCharacter": "\\E083",
|
||||
"fontColor": "#8dc149"
|
||||
},
|
||||
"_sublime_light": {
|
||||
"fontCharacter": "\\E083",
|
||||
"fontCharacter": "\\E084",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_sublime": {
|
||||
"fontCharacter": "\\E083",
|
||||
"fontCharacter": "\\E084",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_svg_light": {
|
||||
"fontCharacter": "\\E084",
|
||||
"fontCharacter": "\\E085",
|
||||
"fontColor": "#9068b0"
|
||||
},
|
||||
"_svg": {
|
||||
"fontCharacter": "\\E084",
|
||||
"fontCharacter": "\\E085",
|
||||
"fontColor": "#a074c4"
|
||||
},
|
||||
"_svg_1_light": {
|
||||
"fontCharacter": "\\E084",
|
||||
"fontCharacter": "\\E085",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_svg_1": {
|
||||
"fontCharacter": "\\E084",
|
||||
"fontCharacter": "\\E085",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_swift_light": {
|
||||
"fontCharacter": "\\E085",
|
||||
"fontCharacter": "\\E086",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_swift": {
|
||||
"fontCharacter": "\\E085",
|
||||
"fontCharacter": "\\E086",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_terraform_light": {
|
||||
"fontCharacter": "\\E086",
|
||||
"fontCharacter": "\\E087",
|
||||
"fontColor": "#9068b0"
|
||||
},
|
||||
"_terraform": {
|
||||
"fontCharacter": "\\E086",
|
||||
"fontCharacter": "\\E087",
|
||||
"fontColor": "#a074c4"
|
||||
},
|
||||
"_tex_light": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_tex": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_tex_1_light": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#b7b73b"
|
||||
},
|
||||
"_tex_1": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#cbcb41"
|
||||
},
|
||||
"_tex_2_light": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_tex_2": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_tex_3_light": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#bfc2c1"
|
||||
},
|
||||
"_tex_3": {
|
||||
"fontCharacter": "\\E087",
|
||||
"fontCharacter": "\\E088",
|
||||
"fontColor": "#d4d7d6"
|
||||
},
|
||||
"_todo": {
|
||||
"fontCharacter": "\\E089"
|
||||
"fontCharacter": "\\E08A"
|
||||
},
|
||||
"_tsconfig_light": {
|
||||
"fontCharacter": "\\E08A",
|
||||
"fontCharacter": "\\E08B",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_tsconfig": {
|
||||
"fontCharacter": "\\E08A",
|
||||
"fontCharacter": "\\E08B",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_twig_light": {
|
||||
"fontCharacter": "\\E08B",
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontColor": "#7fae42"
|
||||
},
|
||||
"_twig": {
|
||||
"fontCharacter": "\\E08B",
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontColor": "#8dc149"
|
||||
},
|
||||
"_typescript_light": {
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_typescript": {
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_typescript_1_light": {
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontColor": "#b7b73b"
|
||||
},
|
||||
"_typescript_1": {
|
||||
"fontCharacter": "\\E08C",
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontColor": "#cbcb41"
|
||||
},
|
||||
"_vala_light": {
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontCharacter": "\\E08E",
|
||||
"fontColor": "#627379"
|
||||
},
|
||||
"_vala": {
|
||||
"fontCharacter": "\\E08D",
|
||||
"fontCharacter": "\\E08E",
|
||||
"fontColor": "#6d8086"
|
||||
},
|
||||
"_video_light": {
|
||||
"fontCharacter": "\\E08E",
|
||||
"fontCharacter": "\\E08F",
|
||||
"fontColor": "#dd4b78"
|
||||
},
|
||||
"_video": {
|
||||
"fontCharacter": "\\E08E",
|
||||
"fontCharacter": "\\E08F",
|
||||
"fontColor": "#f55385"
|
||||
},
|
||||
"_vue_light": {
|
||||
"fontCharacter": "\\E08F",
|
||||
"fontCharacter": "\\E090",
|
||||
"fontColor": "#7fae42"
|
||||
},
|
||||
"_vue": {
|
||||
"fontCharacter": "\\E08F",
|
||||
"fontCharacter": "\\E090",
|
||||
"fontColor": "#8dc149"
|
||||
},
|
||||
"_wasm_light": {
|
||||
"fontCharacter": "\\E090",
|
||||
"fontCharacter": "\\E091",
|
||||
"fontColor": "#9068b0"
|
||||
},
|
||||
"_wasm": {
|
||||
"fontCharacter": "\\E090",
|
||||
"fontCharacter": "\\E091",
|
||||
"fontColor": "#a074c4"
|
||||
},
|
||||
"_wat_light": {
|
||||
"fontCharacter": "\\E091",
|
||||
"fontCharacter": "\\E092",
|
||||
"fontColor": "#9068b0"
|
||||
},
|
||||
"_wat": {
|
||||
"fontCharacter": "\\E091",
|
||||
"fontCharacter": "\\E092",
|
||||
"fontColor": "#a074c4"
|
||||
},
|
||||
"_webpack_light": {
|
||||
"fontCharacter": "\\E092",
|
||||
"fontCharacter": "\\E093",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_webpack": {
|
||||
"fontCharacter": "\\E092",
|
||||
"fontCharacter": "\\E093",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_wgt_light": {
|
||||
"fontCharacter": "\\E093",
|
||||
"fontCharacter": "\\E094",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_wgt": {
|
||||
"fontCharacter": "\\E093",
|
||||
"fontCharacter": "\\E094",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_windows_light": {
|
||||
"fontCharacter": "\\E094",
|
||||
"fontCharacter": "\\E095",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_windows": {
|
||||
"fontCharacter": "\\E094",
|
||||
"fontCharacter": "\\E095",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_word_light": {
|
||||
"fontCharacter": "\\E095",
|
||||
"fontCharacter": "\\E096",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_word": {
|
||||
"fontCharacter": "\\E095",
|
||||
"fontCharacter": "\\E096",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_xls_light": {
|
||||
"fontCharacter": "\\E096",
|
||||
"fontCharacter": "\\E097",
|
||||
"fontColor": "#7fae42"
|
||||
},
|
||||
"_xls": {
|
||||
"fontCharacter": "\\E096",
|
||||
"fontCharacter": "\\E097",
|
||||
"fontColor": "#8dc149"
|
||||
},
|
||||
"_xml_light": {
|
||||
"fontCharacter": "\\E097",
|
||||
"fontCharacter": "\\E098",
|
||||
"fontColor": "#cc6d2e"
|
||||
},
|
||||
"_xml": {
|
||||
"fontCharacter": "\\E097",
|
||||
"fontCharacter": "\\E098",
|
||||
"fontColor": "#e37933"
|
||||
},
|
||||
"_yarn_light": {
|
||||
"fontCharacter": "\\E098",
|
||||
"fontCharacter": "\\E099",
|
||||
"fontColor": "#498ba7"
|
||||
},
|
||||
"_yarn": {
|
||||
"fontCharacter": "\\E098",
|
||||
"fontCharacter": "\\E099",
|
||||
"fontColor": "#519aba"
|
||||
},
|
||||
"_yml_light": {
|
||||
"fontCharacter": "\\E099",
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontColor": "#9068b0"
|
||||
},
|
||||
"_yml": {
|
||||
"fontCharacter": "\\E099",
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontColor": "#a074c4"
|
||||
},
|
||||
"_zip_light": {
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontCharacter": "\\E09B",
|
||||
"fontColor": "#b8383d"
|
||||
},
|
||||
"_zip": {
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontCharacter": "\\E09B",
|
||||
"fontColor": "#cc3e44"
|
||||
},
|
||||
"_zip_1_light": {
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontCharacter": "\\E09B",
|
||||
"fontColor": "#627379"
|
||||
},
|
||||
"_zip_1": {
|
||||
"fontCharacter": "\\E09A",
|
||||
"fontCharacter": "\\E09B",
|
||||
"fontColor": "#6d8086"
|
||||
},
|
||||
// {{SQL CARBON EDIT}}
|
||||
@@ -1392,6 +1406,7 @@
|
||||
"edn": "_clojure_1",
|
||||
"cfc": "_coldfusion",
|
||||
"cfm": "_coldfusion",
|
||||
"litcoffee": "_coffee",
|
||||
"config": "_config",
|
||||
"cfg": "_config",
|
||||
"conf": "_config",
|
||||
@@ -1434,6 +1449,7 @@
|
||||
"hxml": "_haxe_3",
|
||||
"class": "_java",
|
||||
"classpath": "_java",
|
||||
"properties": "_java",
|
||||
"js.map": "_javascript",
|
||||
"spec.js": "_javascript_1",
|
||||
"test.js": "_javascript_1",
|
||||
@@ -1480,6 +1496,7 @@
|
||||
"test.tsx": "_react_2",
|
||||
"re": "_reasonml",
|
||||
"r": "_R",
|
||||
"rmd": "_rmd",
|
||||
"erb": "_html_erb",
|
||||
"erb.html": "_html_erb",
|
||||
"html.erb": "_html_erb",
|
||||
@@ -1507,6 +1524,7 @@
|
||||
"vue": "_vue",
|
||||
"wasm": "_wasm",
|
||||
"wat": "_wat",
|
||||
"pro": "_prolog",
|
||||
"jar": "_zip",
|
||||
"zip": "_zip_1",
|
||||
"wgt": "_wgt",
|
||||
@@ -1545,6 +1563,8 @@
|
||||
"obj": "_svg_1",
|
||||
"dae": "_svg_1",
|
||||
"babelrc": "_babel",
|
||||
"babelrc.js": "_babel",
|
||||
"babelrc.cjs": "_babel",
|
||||
"bowerrc": "_bower",
|
||||
"dockerignore": "_docker_1",
|
||||
"codeclimate.yml": "_code-climate",
|
||||
@@ -1588,12 +1608,14 @@
|
||||
"version.md": "_clock",
|
||||
"version": "_clock",
|
||||
"mvnw": "_maven",
|
||||
"tsconfig.json": "_tsconfig",
|
||||
"swagger.json": "_json_1",
|
||||
"swagger.yml": "_json_1",
|
||||
"swagger.yaml": "_json_1",
|
||||
"mime.types": "_config",
|
||||
"jenkinsfile": "_jenkins",
|
||||
"babel.config.js": "_babel",
|
||||
"babel.config.json": "_babel",
|
||||
"babel.config.cjs": "_babel",
|
||||
"bower.json": "_bower",
|
||||
"docker-healthcheck": "_docker_2",
|
||||
"docker-compose.yml": "_docker_3",
|
||||
@@ -1606,6 +1628,7 @@
|
||||
"gruntfile.babel.js": "_grunt",
|
||||
"gruntfile.coffee": "_grunt",
|
||||
"gulpfile": "_gulp",
|
||||
"gulpfile.js": "_gulp",
|
||||
"ionic.config.json": "_ionic",
|
||||
"ionic.project": "_ionic",
|
||||
"platformio.ini": "_platformio",
|
||||
@@ -1649,7 +1672,6 @@
|
||||
"groovy": "_grails",
|
||||
"handlebars": "_mustache",
|
||||
"html": "_html_3",
|
||||
"properties": "_java",
|
||||
"java": "_java",
|
||||
"javascriptreact": "_react",
|
||||
"javascript": "_javascript",
|
||||
@@ -1699,7 +1721,9 @@
|
||||
"todo": "_todo",
|
||||
// {{SQL CARBON EDIT}}
|
||||
"notebook": "notebook_dark",
|
||||
"scmp": "scmp_dark"
|
||||
"scmp": "scmp_dark",
|
||||
"postcss": "_css",
|
||||
"django-html": "_html_3"
|
||||
},
|
||||
"light": {
|
||||
"file": "_default_light",
|
||||
@@ -1719,6 +1743,7 @@
|
||||
"edn": "_clojure_1_light",
|
||||
"cfc": "_coldfusion_light",
|
||||
"cfm": "_coldfusion_light",
|
||||
"litcoffee": "_coffee_light",
|
||||
"config": "_config_light",
|
||||
"cfg": "_config_light",
|
||||
"conf": "_config_light",
|
||||
@@ -1761,6 +1786,7 @@
|
||||
"hxml": "_haxe_3_light",
|
||||
"class": "_java_light",
|
||||
"classpath": "_java_light",
|
||||
"properties": "_java_light",
|
||||
"js.map": "_javascript_light",
|
||||
"spec.js": "_javascript_1_light",
|
||||
"test.js": "_javascript_1_light",
|
||||
@@ -1807,6 +1833,7 @@
|
||||
"test.tsx": "_react_2_light",
|
||||
"re": "_reasonml_light",
|
||||
"r": "_R_light",
|
||||
"rmd": "_rmd_light",
|
||||
"erb": "_html_erb_light",
|
||||
"erb.html": "_html_erb_light",
|
||||
"html.erb": "_html_erb_light",
|
||||
@@ -1834,6 +1861,7 @@
|
||||
"vue": "_vue_light",
|
||||
"wasm": "_wasm_light",
|
||||
"wat": "_wat_light",
|
||||
"pro": "_prolog_light",
|
||||
"jar": "_zip_light",
|
||||
"zip": "_zip_1_light",
|
||||
"wgt": "_wgt_light",
|
||||
@@ -1872,6 +1900,8 @@
|
||||
"obj": "_svg_1_light",
|
||||
"dae": "_svg_1_light",
|
||||
"babelrc": "_babel_light",
|
||||
"babelrc.js": "_babel_light",
|
||||
"babelrc.cjs": "_babel_light",
|
||||
"bowerrc": "_bower_light",
|
||||
"dockerignore": "_docker_1_light",
|
||||
"codeclimate.yml": "_code-climate_light",
|
||||
@@ -1919,7 +1949,6 @@
|
||||
"groovy": "_grails_light",
|
||||
"handlebars": "_mustache_light",
|
||||
"html": "_html_3_light",
|
||||
"properties": "_java_light",
|
||||
"java": "_java_light",
|
||||
"javascriptreact": "_react_light",
|
||||
"javascript": "_javascript_light",
|
||||
@@ -1968,7 +1997,9 @@
|
||||
"vala": "_vala_light",
|
||||
// {{SQL CARBON EDIT}}
|
||||
"notebook": "notebook",
|
||||
"scmp": "scmp"
|
||||
"scmp": "scmp",
|
||||
"postcss": "_css_light",
|
||||
"django-html": "_html_3_light"
|
||||
},
|
||||
"fileNames": {
|
||||
"mix": "_hex_light",
|
||||
@@ -1981,12 +2012,14 @@
|
||||
"version.md": "_clock_light",
|
||||
"version": "_clock_light",
|
||||
"mvnw": "_maven_light",
|
||||
"tsconfig.json": "_tsconfig_light",
|
||||
"swagger.json": "_json_1_light",
|
||||
"swagger.yml": "_json_1_light",
|
||||
"swagger.yaml": "_json_1_light",
|
||||
"mime.types": "_config_light",
|
||||
"jenkinsfile": "_jenkins_light",
|
||||
"babel.config.js": "_babel_light",
|
||||
"babel.config.json": "_babel_light",
|
||||
"babel.config.cjs": "_babel_light",
|
||||
"bower.json": "_bower_light",
|
||||
"docker-healthcheck": "_docker_2_light",
|
||||
"docker-compose.yml": "_docker_3_light",
|
||||
@@ -1999,6 +2032,7 @@
|
||||
"gruntfile.babel.js": "_grunt_light",
|
||||
"gruntfile.coffee": "_grunt_light",
|
||||
"gulpfile": "_gulp_light",
|
||||
"gulpfile.js": "_gulp_light",
|
||||
"ionic.config.json": "_ionic_light",
|
||||
"ionic.project": "_ionic_light",
|
||||
"platformio.ini": "_platformio_light",
|
||||
@@ -2027,5 +2061,5 @@
|
||||
"Schema Compare": "scmp"
|
||||
}
|
||||
},
|
||||
"version": "https://github.com/jesseweed/seti-ui/commit/4b3e0a3d0ca8999430bc3aa9f2c8324e6922b3de"
|
||||
"version": "https://github.com/jesseweed/seti-ui/commit/8f22764c37feb7f706465f5186132111a2401b6b"
|
||||
}
|
||||
@@ -317,6 +317,10 @@ export class AzureActiveDirectoryService {
|
||||
}
|
||||
|
||||
private getCallbackEnvironment(callbackUri: vscode.Uri): string {
|
||||
if (callbackUri.authority.endsWith('.workspaces.github.com')) {
|
||||
return `${callbackUri.authority},`;
|
||||
}
|
||||
|
||||
switch (callbackUri.authority) {
|
||||
case 'online.visualstudio.com':
|
||||
return 'vso,';
|
||||
|
||||
+3
-3
@@ -76,15 +76,15 @@
|
||||
"sudo-prompt": "9.1.1",
|
||||
"v8-inspect-profiler": "^0.0.20",
|
||||
"vscode-nsfw": "1.2.8",
|
||||
"vscode-oniguruma": "1.3.0",
|
||||
"vscode-oniguruma": "1.3.1",
|
||||
"vscode-proxy-agent": "^0.5.2",
|
||||
"vscode-ripgrep": "^1.5.8",
|
||||
"vscode-sqlite3": "4.0.10",
|
||||
"vscode-textmate": "5.1.1",
|
||||
"xterm": "4.6.0-beta.38",
|
||||
"xterm": "4.6.0-beta.44",
|
||||
"xterm-addon-search": "0.7.0-beta.2",
|
||||
"xterm-addon-unicode11": "0.2.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.6",
|
||||
"xterm-addon-webgl": "0.7.0-beta.10",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3",
|
||||
|
||||
+3
-3
@@ -34,14 +34,14 @@
|
||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
|
||||
"spdlog": "^0.11.1",
|
||||
"vscode-nsfw": "1.2.8",
|
||||
"vscode-oniguruma": "1.3.0",
|
||||
"vscode-oniguruma": "1.3.1",
|
||||
"vscode-proxy-agent": "^0.5.2",
|
||||
"vscode-ripgrep": "^1.5.8",
|
||||
"vscode-textmate": "5.1.1",
|
||||
"xterm": "4.6.0-beta.38",
|
||||
"xterm": "4.6.0-beta.44",
|
||||
"xterm-addon-search": "0.7.0-beta.2",
|
||||
"xterm-addon-unicode11": "0.2.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.6",
|
||||
"xterm-addon-webgl": "0.7.0-beta.10",
|
||||
"yauzl": "^2.9.2",
|
||||
"yazl": "^2.4.3",
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
"sanitize-html": "^1.19.1",
|
||||
"semver-umd": "^5.5.6",
|
||||
"slickgrid": "github:anthonydresser/SlickGrid#2.3.33",
|
||||
"vscode-oniguruma": "1.3.0",
|
||||
"vscode-oniguruma": "1.3.1",
|
||||
"vscode-textmate": "5.1.1",
|
||||
"xterm": "4.6.0-beta.38",
|
||||
"xterm": "4.6.0-beta.44",
|
||||
"xterm-addon-search": "0.7.0-beta.2",
|
||||
"xterm-addon-unicode11": "0.2.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.5",
|
||||
"xterm-addon-web-links": "0.4.0-beta.6",
|
||||
"xterm-addon-webgl": "0.7.0-beta.10",
|
||||
"zone.js": "^0.8.4"
|
||||
}
|
||||
|
||||
+12
-12
@@ -338,10 +338,10 @@ util-deprecate@^1.0.1:
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
|
||||
|
||||
vscode-oniguruma@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
|
||||
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
|
||||
vscode-oniguruma@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.1.tgz#e2383879c3485b19f533ec34efea9d7a2b14be8f"
|
||||
integrity sha512-gz6ZBofA7UXafVA+m2Yt2zHKgXC2qedArprIsHAPKByTkwq9l5y/izAGckqxYml7mSbYxTRTfdRwsFq3cwF4LQ==
|
||||
|
||||
vscode-textmate@5.1.1:
|
||||
version "5.1.1"
|
||||
@@ -363,20 +363,20 @@ xterm-addon-unicode11@0.2.0-beta.5:
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
|
||||
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
|
||||
|
||||
xterm-addon-web-links@0.4.0-beta.5:
|
||||
version "0.4.0-beta.5"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
|
||||
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
|
||||
xterm-addon-web-links@0.4.0-beta.6:
|
||||
version "0.4.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.6.tgz#d159d4542eb9a02d57977fe7eb5f42f8ef2f27fa"
|
||||
integrity sha512-dsQVD/EyVq8PtAYGh2PGQTCt009UipIfX6Q2SBDlz+W9x7IkXjhRxRaryMmLsBCca20qeVKwmbQ+ANhLi+nTaQ==
|
||||
|
||||
xterm-addon-webgl@0.7.0-beta.10:
|
||||
version "0.7.0-beta.10"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
|
||||
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
|
||||
|
||||
xterm@4.6.0-beta.38:
|
||||
version "4.6.0-beta.38"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
|
||||
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
|
||||
xterm@4.6.0-beta.44:
|
||||
version "4.6.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.44.tgz#76b2a6b8e147595ab44aa752c0e721d935464615"
|
||||
integrity sha512-vYtfz4spFcSKLEUpC6anH7TwDams71+k2wAtUzCJ47dNL2IrwYafcFsvGPm46QLTtq4M2Bp9rQo3R3V746yxNg==
|
||||
|
||||
zone.js@^0.8.4:
|
||||
version "0.8.29"
|
||||
|
||||
+12
-12
@@ -698,10 +698,10 @@ vscode-nsfw@1.2.8:
|
||||
lodash.isundefined "^3.0.1"
|
||||
nan "^2.10.0"
|
||||
|
||||
vscode-oniguruma@1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.0.tgz#6788a9db2f8b0781243b4eb8c7a1dd25f6c0e2c8"
|
||||
integrity sha512-m4Br19v6XD4MRbVrgsLNSZgQrBzk1BCMCleL8+GrcoGxKEJJd62zOFcTaoQR3hCrSlLqoxWmJ7Cc0VieVV3iTQ==
|
||||
vscode-oniguruma@1.3.1:
|
||||
version "1.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.3.1.tgz#e2383879c3485b19f533ec34efea9d7a2b14be8f"
|
||||
integrity sha512-gz6ZBofA7UXafVA+m2Yt2zHKgXC2qedArprIsHAPKByTkwq9l5y/izAGckqxYml7mSbYxTRTfdRwsFq3cwF4LQ==
|
||||
|
||||
vscode-proxy-agent@^0.5.2:
|
||||
version "0.5.2"
|
||||
@@ -750,20 +750,20 @@ xterm-addon-unicode11@0.2.0-beta.5:
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-unicode11/-/xterm-addon-unicode11-0.2.0-beta.5.tgz#5961850162df20b5e966166423cd6957ac2db298"
|
||||
integrity sha512-IjnbBcyfS5JgJDXPO0W2nk/VBtGwx6GWE2snMC676z4DmAABUqPXfTzJKfUoWqoT6UcbxB0oIjDzykCfoRJp6Q==
|
||||
|
||||
xterm-addon-web-links@0.4.0-beta.5:
|
||||
version "0.4.0-beta.5"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.5.tgz#523fd0a1c5668370d73e05019ed16eaf596894c8"
|
||||
integrity sha512-Qe0idPpSokCNvGrthSBjdrOZrsgXwnLYbzuv0JoEec/A9HVcxKmZ+ktw7fOA2gT/zbcwtrA5FWrir3GlRHglCQ==
|
||||
xterm-addon-web-links@0.4.0-beta.6:
|
||||
version "0.4.0-beta.6"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-web-links/-/xterm-addon-web-links-0.4.0-beta.6.tgz#d159d4542eb9a02d57977fe7eb5f42f8ef2f27fa"
|
||||
integrity sha512-dsQVD/EyVq8PtAYGh2PGQTCt009UipIfX6Q2SBDlz+W9x7IkXjhRxRaryMmLsBCca20qeVKwmbQ+ANhLi+nTaQ==
|
||||
|
||||
xterm-addon-webgl@0.7.0-beta.10:
|
||||
version "0.7.0-beta.10"
|
||||
resolved "https://registry.yarnpkg.com/xterm-addon-webgl/-/xterm-addon-webgl-0.7.0-beta.10.tgz#39fdb96351e97a1bf15f4c4c8944ba3d05cacee4"
|
||||
integrity sha512-nQl/ASk+ck11aSrBZXb2a0tu+SNDnm89owBk/sAZeZzi5MHNo6bB8y2VTKNNC6D3i3aFouTz4VorYB25LUgNFg==
|
||||
|
||||
xterm@4.6.0-beta.38:
|
||||
version "4.6.0-beta.38"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.38.tgz#8472b168941500c3071aba482c2b5c6040951ec7"
|
||||
integrity sha512-Q+nOalMD1MDGOqXdtkGZmOQqbSBU+71vhlX2RBwQoSpJa1QBrKDAhSlN/J+/XvouvVEtCiEFDeacF4EufMEIMg==
|
||||
xterm@4.6.0-beta.44:
|
||||
version "4.6.0-beta.44"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-4.6.0-beta.44.tgz#76b2a6b8e147595ab44aa752c0e721d935464615"
|
||||
integrity sha512-vYtfz4spFcSKLEUpC6anH7TwDams71+k2wAtUzCJ47dNL2IrwYafcFsvGPm46QLTtq4M2Bp9rQo3R3V746yxNg==
|
||||
|
||||
yauzl@^2.9.2:
|
||||
version "2.10.0"
|
||||
|
||||
@@ -9,6 +9,7 @@ if grep -qi Microsoft /proc/version && [ -z "$DONT_PROMPT_WSL_INSTALL" ]; then
|
||||
read -e -p "Do you want to continue anyways ? [y/N] " YN
|
||||
|
||||
[[ $YN == "n" || $YN == "N" || $YN == "" ]] && exit 1
|
||||
echo "To no longer see this prompt, start @@PRODNAME@@ with the environment variable DONT_PROMPT_WSL_INSTALL defined."
|
||||
fi
|
||||
|
||||
|
||||
|
||||
@@ -4,14 +4,16 @@ setlocal
|
||||
pushd %~dp0\..
|
||||
|
||||
set VSCODEUSERDATADIR=%TEMP%\vscodeuserfolder-%RANDOM%-%TIME:~6,2%
|
||||
set VSCODECRASHDIR=%~dp0\..\.build\crashes
|
||||
|
||||
:: Figure out which Electron to use for running tests
|
||||
if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
|
||||
:: Run out of sources: no need to compile as code.sh takes care of it
|
||||
:: Run out of sources: no need to compile as code.bat takes care of it
|
||||
chcp 65001
|
||||
set INTEGRATION_TEST_ELECTRON_PATH=.\scripts\code.bat
|
||||
set VSCODE_BUILD_BUILTIN_EXTENSIONS_SILENCE_PLEASE=1
|
||||
|
||||
echo Storing crash reports into '%VSCODECRASHDIR%'.
|
||||
echo Running integration tests out of sources.
|
||||
) else (
|
||||
:: Run from a built: need to compile all test extensions
|
||||
@@ -29,8 +31,8 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
|
||||
:: Configuration for more verbose output
|
||||
set VSCODE_CLI=1
|
||||
set ELECTRON_ENABLE_LOGGING=1
|
||||
set ELECTRON_ENABLE_STACK_DUMPING=1
|
||||
|
||||
echo Storing crash reports into '%VSCODECRASHDIR%'.
|
||||
echo Running integration tests with '%INTEGRATION_TEST_ELECTRON_PATH%' as build.
|
||||
)
|
||||
|
||||
@@ -41,19 +43,19 @@ if "%INTEGRATION_TEST_ELECTRON_PATH%"=="" (
|
||||
|
||||
:: Tests in the extension host
|
||||
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\singlefolder-tests --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-api-tests\testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=%~dp0\..\extensions\vscode-api-tests --extensionTestsPath=%~dp0\..\extensions\vscode-api-tests\out\workspace-tests --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\vscode-colorize-tests\test --extensionDevelopmentPath=%~dp0\..\extensions\vscode-colorize-tests --extensionTestsPath=%~dp0\..\extensions\vscode-colorize-tests\out --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
REM if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\markdown-language-features\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\markdown-language-features --extensionTestsPath=%~dp0\..\extensions\markdown-language-features\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
|
||||
REM if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
|
||||
REM call "%INTEGRATION_TEST_ELECTRON_PATH%" $%~dp0\..\extensions\emmet\out\test\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\emmet --extensionTestsPath=%~dp0\..\extensions\emmet\out\test --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR% .
|
||||
REM if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
call "%INTEGRATION_TEST_ELECTRON_PATH%" %~dp0\..\extensions\azurecore\test-fixtures --extensionDevelopmentPath=%~dp0\..\extensions\azurecore --extensionTestsPath=%~dp0\..\extensions\azurecore\out\test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
@@ -62,7 +64,7 @@ if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
for /f "delims=" %%i in ('node -p "require('fs').realpathSync.native(require('os').tmpdir())"') do set TEMPDIR=%%i
|
||||
set GITWORKSPACE=%TEMPDIR%\git-%RANDOM%
|
||||
mkdir %GITWORKSPACE%
|
||||
call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test --enable-proposed-api=vscode.git --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
call "%INTEGRATION_TEST_ELECTRON_PATH%" %GITWORKSPACE% --extensionDevelopmentPath=%~dp0\..\extensions\git --extensionTestsPath=%~dp0\..\extensions\git\out\test --enable-proposed-api=vscode.git --disable-telemetry --crash-reporter-directory=%VSCODECRASHDIR% --disable-updates --disable-extensions --user-data-dir=%VSCODEUSERDATADIR%
|
||||
if %errorlevel% neq 0 exit /b %errorlevel%
|
||||
|
||||
:: Tests in commonJS (HTML, CSS, JSON language server tests...)
|
||||
|
||||
@@ -10,6 +10,7 @@ else
|
||||
fi
|
||||
|
||||
VSCODEUSERDATADIR=`mktemp -d 2>/dev/null`
|
||||
VSCODECRASHDIR=$ROOT/.build/crashes
|
||||
cd $ROOT
|
||||
|
||||
# Figure out which Electron to use for running tests
|
||||
@@ -18,6 +19,7 @@ then
|
||||
# Run out of sources: no need to compile as code.sh takes care of it
|
||||
INTEGRATION_TEST_ELECTRON_PATH="./scripts/code.sh"
|
||||
|
||||
echo "Storing crash reports into '$VSCODECRASHDIR'."
|
||||
echo "Running integration tests out of sources."
|
||||
else
|
||||
# Run from a built: need to compile all test extensions
|
||||
@@ -38,6 +40,7 @@ else
|
||||
export ELECTRON_ENABLE_STACK_DUMPING=1
|
||||
export ELECTRON_ENABLE_LOGGING=1
|
||||
|
||||
echo "Storing crash reports into '$VSCODECRASHDIR'."
|
||||
echo "Running integration tests with '$INTEGRATION_TEST_ELECTRON_PATH' as build."
|
||||
fi
|
||||
|
||||
@@ -45,13 +48,13 @@ fi
|
||||
./scripts/test.sh --runGlob **/*.integrationTest.js "$@"
|
||||
|
||||
# Tests in the extension host
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-notebook-tests/test --enable-proposed-api=vscode.vscode-notebook-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-notebook-tests --extensionTestsPath=$ROOT/extensions/vscode-notebook-tests/out/ --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testWorkspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/singlefolder-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-api-tests/testworkspace.code-workspace --enable-proposed-api=vscode.vscode-api-tests --extensionDevelopmentPath=$ROOT/extensions/vscode-api-tests --extensionTestsPath=$ROOT/extensions/vscode-api-tests/out/workspace-tests --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/vscode-colorize-tests/test --extensionDevelopmentPath=$ROOT/extensions/vscode-colorize-tests --extensionTestsPath=$ROOT/extensions/vscode-colorize-tests/out --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/markdown-language-features/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/markdown-language-features --extensionTestsPath=$ROOT/extensions/markdown-language-features/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/emmet/out/test/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/emmet --extensionTestsPath=$ROOT/extensions/emmet/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
# "$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $(mktemp -d 2>/dev/null) --enable-proposed-api=vscode.git --extensionDevelopmentPath=$ROOT/extensions/git --extensionTestsPath=$ROOT/extensions/git/out/test --disable-telemetry --crash-reporter-directory=$VSCODECRASHDIR --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
|
||||
"$INTEGRATION_TEST_ELECTRON_PATH" $LINUX_NO_SANDBOX $ROOT/extensions/azurecore/test-fixtures --extensionDevelopmentPath=$ROOT/extensions/azurecore --extensionTestsPath=$ROOT/extensions/azurecore/out/test --disable-telemetry --disable-crash-reporter --disable-updates --disable-extensions --user-data-dir=$VSCODEUSERDATADIR
|
||||
|
||||
|
||||
+21
-1
@@ -39,6 +39,25 @@ if (args['nogpu']) { // {{SQL CARBON EDIT}}
|
||||
const userDataPath = getUserDataPath(args);
|
||||
app.setPath('userData', userDataPath);
|
||||
|
||||
// Set temp directory based on crash-reporter-directory CLI argument
|
||||
// The crash reporter will store crashes in temp folder so we need
|
||||
// to change that location accordingly.
|
||||
let crashReporterDirectory = args['crash-reporter-directory'];
|
||||
if (crashReporterDirectory) {
|
||||
crashReporterDirectory = path.normalize(crashReporterDirectory);
|
||||
|
||||
if (!fs.existsSync(crashReporterDirectory)) {
|
||||
try {
|
||||
fs.mkdirSync(crashReporterDirectory);
|
||||
} catch (error) {
|
||||
console.error(`The path '${crashReporterDirectory}' specified for --crash-reporter-directory does not seem to exist or cannot be created.`);
|
||||
app.exit(1);
|
||||
}
|
||||
}
|
||||
console.log(`Found --crash-reporter-directory argument. Setting temp directory to be '${crashReporterDirectory}'`);
|
||||
app.setPath('temp', crashReporterDirectory);
|
||||
}
|
||||
|
||||
// Set logs path before app 'ready' event if running portable
|
||||
// to ensure that no 'logs' folder is created on disk at a
|
||||
// location outside of the portable directory
|
||||
@@ -336,7 +355,8 @@ function parseCLIArgs() {
|
||||
'user-data-dir',
|
||||
'locale',
|
||||
'js-flags',
|
||||
'max-memory'
|
||||
'max-memory',
|
||||
'crash-reporter-directory'
|
||||
]
|
||||
});
|
||||
}
|
||||
|
||||
@@ -477,27 +477,27 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
DOM.addClass(this.domNode, 'animated');
|
||||
}
|
||||
|
||||
let previousKey: KeyCode;
|
||||
let nextKey: KeyCode;
|
||||
let previousKeys: KeyCode[];
|
||||
let nextKeys: KeyCode[];
|
||||
|
||||
switch (this.options.orientation) {
|
||||
case ActionsOrientation.HORIZONTAL:
|
||||
previousKey = KeyCode.LeftArrow;
|
||||
nextKey = KeyCode.RightArrow;
|
||||
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
break;
|
||||
case ActionsOrientation.HORIZONTAL_REVERSE:
|
||||
previousKey = KeyCode.RightArrow;
|
||||
nextKey = KeyCode.LeftArrow;
|
||||
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
this.domNode.className += ' reverse';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL:
|
||||
previousKey = KeyCode.UpArrow;
|
||||
nextKey = KeyCode.DownArrow;
|
||||
previousKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
nextKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
this.domNode.className += ' vertical';
|
||||
break;
|
||||
case ActionsOrientation.VERTICAL_REVERSE:
|
||||
previousKey = KeyCode.DownArrow;
|
||||
nextKey = KeyCode.UpArrow;
|
||||
previousKeys = [KeyCode.RightArrow, KeyCode.DownArrow];
|
||||
nextKeys = [KeyCode.LeftArrow, KeyCode.UpArrow];
|
||||
this.domNode.className += ' vertical reverse';
|
||||
break;
|
||||
}
|
||||
@@ -506,9 +506,9 @@ export class ActionBar extends Disposable implements IActionRunner {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
let eventHandled = true;
|
||||
|
||||
if (event.equals(previousKey)) {
|
||||
if (previousKeys && (event.equals(previousKeys[0]) || event.equals(previousKeys[1]))) {
|
||||
this.focusPrevious();
|
||||
} else if (event.equals(nextKey)) {
|
||||
} else if (nextKeys && (event.equals(nextKeys[0]) || event.equals(nextKeys[1]))) {
|
||||
this.focusNext();
|
||||
} else if (event.equals(KeyCode.Escape)) {
|
||||
this._onDidCancel.fire();
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
.monaco-count-badge {
|
||||
padding: 3px 5px;
|
||||
padding: 3px 6px;
|
||||
border-radius: 11px;
|
||||
font-size: 11px;
|
||||
min-width: 18px;
|
||||
@@ -15,3 +15,8 @@
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-count-badge.long {
|
||||
padding: 2px 3px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ export interface IIndexTreeNode<T, TFilterData = void> extends ITreeNode<T, TFil
|
||||
collapsible: boolean;
|
||||
collapsed: boolean;
|
||||
renderNodeCount: number;
|
||||
visibility: TreeVisibility;
|
||||
visible: boolean;
|
||||
filterData: TFilterData | undefined;
|
||||
}
|
||||
@@ -95,6 +96,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
collapsible: false,
|
||||
collapsed: false,
|
||||
renderNodeCount: 0,
|
||||
visibility: TreeVisibility.Visible,
|
||||
visible: true,
|
||||
filterData: undefined
|
||||
};
|
||||
@@ -185,6 +187,17 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
}
|
||||
|
||||
this._onDidSplice.fire({ insertedNodes: nodesToInsert, deletedNodes });
|
||||
|
||||
let node: IIndexTreeNode<T, TFilterData> | undefined = parentNode;
|
||||
|
||||
while (node) {
|
||||
if (node.visibility === TreeVisibility.Recurse) {
|
||||
this.refilter();
|
||||
break;
|
||||
}
|
||||
|
||||
node = node.parent;
|
||||
}
|
||||
}
|
||||
|
||||
rerender(location: number[]): void {
|
||||
@@ -194,7 +207,7 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
|
||||
const { node, listIndex, revealed } = this.getTreeNodeWithListIndex(location);
|
||||
|
||||
if (revealed) {
|
||||
if (node.visible && revealed) {
|
||||
this.list.splice(listIndex, 1, [node]);
|
||||
}
|
||||
}
|
||||
@@ -355,11 +368,13 @@ export class IndexTreeModel<T extends Exclude<any, undefined>, TFilterData = voi
|
||||
collapsible: typeof treeElement.collapsible === 'boolean' ? treeElement.collapsible : (typeof treeElement.collapsed !== 'undefined'),
|
||||
collapsed: typeof treeElement.collapsed === 'undefined' ? this.collapseByDefault : treeElement.collapsed,
|
||||
renderNodeCount: 1,
|
||||
visibility: TreeVisibility.Visible,
|
||||
visible: true,
|
||||
filterData: undefined
|
||||
};
|
||||
|
||||
const visibility = this._filterNode(node, parentVisibility);
|
||||
node.visibility = visibility;
|
||||
|
||||
if (revealed) {
|
||||
treeListElements.push(node);
|
||||
|
||||
@@ -43,12 +43,12 @@ const _registry = new Registry();
|
||||
|
||||
export const iconRegistry: IIconRegistry = _registry;
|
||||
|
||||
export function registerIcon(id: string, def: Codicon) {
|
||||
export function registerIcon(id: string, def: Codicon, description?: string) {
|
||||
return new Codicon(id, def);
|
||||
}
|
||||
|
||||
export class Codicon {
|
||||
constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition) {
|
||||
constructor(public readonly id: string, public readonly definition: Codicon | IconDefinition, public description?: string) {
|
||||
_registry.add(this);
|
||||
}
|
||||
public get classNames() { return 'codicon codicon-' + this.id; }
|
||||
|
||||
@@ -63,6 +63,7 @@ export interface IJSONSchema {
|
||||
markdownEnumDescriptions?: string[];
|
||||
markdownDescription?: string;
|
||||
doNotSuggest?: boolean;
|
||||
suggestSortText?: string;
|
||||
allowComments?: boolean;
|
||||
allowTrailingCommas?: boolean;
|
||||
}
|
||||
|
||||
+27
-32
@@ -580,9 +580,7 @@ export const enum Touch {
|
||||
AsNew = 2
|
||||
}
|
||||
|
||||
export class LinkedMap<K, V> implements Map<K, V>{
|
||||
|
||||
readonly [Symbol.toStringTag] = 'LinkedMap';
|
||||
export class LinkedMap<K, V> {
|
||||
|
||||
private _map: Map<K, Item<K, V>>;
|
||||
private _head: Item<K, V> | undefined;
|
||||
@@ -634,7 +632,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
|
||||
return item.value;
|
||||
}
|
||||
|
||||
set(key: K, value: V, touch: Touch = Touch.None): this {
|
||||
set(key: K, value: V, touch: Touch = Touch.None): void {
|
||||
let item = this._map.get(key);
|
||||
if (item) {
|
||||
item.value = value;
|
||||
@@ -660,7 +658,6 @@ export class LinkedMap<K, V> implements Map<K, V>{
|
||||
this._map.set(key, item);
|
||||
this._size++;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
delete(key: K): boolean {
|
||||
@@ -704,8 +701,29 @@ export class LinkedMap<K, V> implements Map<K, V>{
|
||||
}
|
||||
}
|
||||
|
||||
keys(): IterableIterator<K> {
|
||||
values(): V[] {
|
||||
const result: V[] = [];
|
||||
let current = this._head;
|
||||
while (current) {
|
||||
result.push(current.value);
|
||||
current = current.next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
keys(): K[] {
|
||||
const result: K[] = [];
|
||||
let current = this._head;
|
||||
while (current) {
|
||||
result.push(current.key);
|
||||
current = current.next;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/* VS Code / Monaco editor runs on es5 which has no Symbol.iterator
|
||||
keys(): IterableIterator<K> {
|
||||
const current = this._head;
|
||||
const iterator: IterableIterator<K> = {
|
||||
[Symbol.iterator]() {
|
||||
return iterator;
|
||||
@@ -724,7 +742,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
|
||||
}
|
||||
|
||||
values(): IterableIterator<V> {
|
||||
let current = this._head;
|
||||
const current = this._head;
|
||||
const iterator: IterableIterator<V> = {
|
||||
[Symbol.iterator]() {
|
||||
return iterator;
|
||||
@@ -741,29 +759,7 @@ export class LinkedMap<K, V> implements Map<K, V>{
|
||||
};
|
||||
return iterator;
|
||||
}
|
||||
|
||||
entries(): IterableIterator<[K, V]> {
|
||||
let current = this._head;
|
||||
const iterator: IterableIterator<[K, V]> = {
|
||||
[Symbol.iterator]() {
|
||||
return iterator;
|
||||
},
|
||||
next(): IteratorResult<[K, V]> {
|
||||
if (current) {
|
||||
const result: IteratorResult<[K, V]> = { value: [current.key, current.value], done: false };
|
||||
current = current.next;
|
||||
return result;
|
||||
} else {
|
||||
return { value: undefined, done: true };
|
||||
}
|
||||
}
|
||||
};
|
||||
return iterator;
|
||||
}
|
||||
|
||||
[Symbol.iterator](): IterableIterator<[K, V]> {
|
||||
return this.entries();
|
||||
}
|
||||
*/
|
||||
|
||||
protected trimOld(newSize: number) {
|
||||
if (newSize >= this.size) {
|
||||
@@ -965,10 +961,9 @@ export class LRUCache<K, V> extends LinkedMap<K, V> {
|
||||
return super.get(key, Touch.None);
|
||||
}
|
||||
|
||||
set(key: K, value: V): this {
|
||||
set(key: K, value: V): void {
|
||||
super.set(key, value, Touch.AsNew);
|
||||
this.checkTrim();
|
||||
return this;
|
||||
}
|
||||
|
||||
private checkTrim() {
|
||||
|
||||
@@ -97,10 +97,14 @@
|
||||
align-self: center;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.quick-input-count .monaco-count-badge {
|
||||
vertical-align: middle;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.quick-input-action {
|
||||
@@ -108,9 +112,8 @@
|
||||
}
|
||||
|
||||
.quick-input-action .monaco-text-button {
|
||||
font-size: 85%;
|
||||
font-size: 11px;
|
||||
padding: 0 6px;
|
||||
line-height: initial;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
|
||||
@@ -4,13 +4,14 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as assert from 'assert';
|
||||
import { ITreeNode } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ITreeNode, ITreeFilter, TreeVisibility } from 'vs/base/browser/ui/tree/tree';
|
||||
import { ISpliceable } from 'vs/base/common/sequence';
|
||||
import { ObjectTreeModel } from 'vs/base/browser/ui/tree/objectTreeModel';
|
||||
|
||||
function toSpliceable<T>(arr: T[]): ISpliceable<T> {
|
||||
return {
|
||||
splice(start: number, deleteCount: number, elements: T[]): void {
|
||||
// console.log(`splice (${start}, ${deleteCount}, ${elements.length} [${elements.join(', ')}] )`); // debugging
|
||||
arr.splice(start, deleteCount, ...elements);
|
||||
}
|
||||
};
|
||||
@@ -240,4 +241,35 @@ suite('ObjectTreeModel', function () {
|
||||
model.expandTo(1000);
|
||||
assert.deepEqual(toArray(list), [0, 10, 100, 1000, 11, 12, 1, 2]);
|
||||
});
|
||||
|
||||
test('issue #95641', () => {
|
||||
const list: ITreeNode<string>[] = [];
|
||||
let fn = (_: string) => true;
|
||||
const filter = new class implements ITreeFilter<string> {
|
||||
filter(element: string, parentVisibility: TreeVisibility): TreeVisibility {
|
||||
if (element === 'file') {
|
||||
return TreeVisibility.Recurse;
|
||||
}
|
||||
|
||||
return fn(element) ? TreeVisibility.Visible : parentVisibility;
|
||||
}
|
||||
};
|
||||
const model = new ObjectTreeModel<string>('test', toSpliceable(list), { filter });
|
||||
|
||||
model.setChildren(null, [{ element: 'file', children: [{ element: 'hello' }] }]);
|
||||
assert.deepEqual(toArray(list), ['file', 'hello']);
|
||||
|
||||
fn = (el: string) => el === 'world';
|
||||
model.refilter();
|
||||
assert.deepEqual(toArray(list), []);
|
||||
|
||||
model.setChildren('file', [{ element: 'world' }]);
|
||||
assert.deepEqual(toArray(list), ['file', 'world']);
|
||||
|
||||
model.setChildren('file', [{ element: 'hello' }]);
|
||||
assert.deepEqual(toArray(list), []);
|
||||
|
||||
model.setChildren('file', [{ element: 'world' }]);
|
||||
assert.deepEqual(toArray(list), ['file', 'world']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -13,8 +13,8 @@ suite('Map', () => {
|
||||
let map = new LinkedMap<string, string>();
|
||||
map.set('ak', 'av');
|
||||
map.set('bk', 'bv');
|
||||
assert.deepStrictEqual([...map.keys()], ['ak', 'bk']);
|
||||
assert.deepStrictEqual([...map.values()], ['av', 'bv']);
|
||||
assert.deepStrictEqual(map.keys(), ['ak', 'bk']);
|
||||
assert.deepStrictEqual(map.values(), ['av', 'bv']);
|
||||
assert.equal(map.first, 'av');
|
||||
assert.equal(map.last, 'bv');
|
||||
});
|
||||
@@ -23,16 +23,16 @@ suite('Map', () => {
|
||||
let map = new LinkedMap<string, string>();
|
||||
map.set('ak', 'av');
|
||||
map.set('ak', 'av', Touch.AsOld);
|
||||
assert.deepStrictEqual([...map.keys()], ['ak']);
|
||||
assert.deepStrictEqual([...map.values()], ['av']);
|
||||
assert.deepStrictEqual(map.keys(), ['ak']);
|
||||
assert.deepStrictEqual(map.values(), ['av']);
|
||||
});
|
||||
|
||||
test('LinkedMap - Touch New one', () => {
|
||||
let map = new LinkedMap<string, string>();
|
||||
map.set('ak', 'av');
|
||||
map.set('ak', 'av', Touch.AsNew);
|
||||
assert.deepStrictEqual([...map.keys()], ['ak']);
|
||||
assert.deepStrictEqual([...map.values()], ['av']);
|
||||
assert.deepStrictEqual(map.keys(), ['ak']);
|
||||
assert.deepStrictEqual(map.values(), ['av']);
|
||||
});
|
||||
|
||||
test('LinkedMap - Touch Old two', () => {
|
||||
@@ -40,8 +40,8 @@ suite('Map', () => {
|
||||
map.set('ak', 'av');
|
||||
map.set('bk', 'bv');
|
||||
map.set('bk', 'bv', Touch.AsOld);
|
||||
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
|
||||
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
|
||||
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
|
||||
assert.deepStrictEqual(map.values(), ['bv', 'av']);
|
||||
});
|
||||
|
||||
test('LinkedMap - Touch New two', () => {
|
||||
@@ -49,8 +49,8 @@ suite('Map', () => {
|
||||
map.set('ak', 'av');
|
||||
map.set('bk', 'bv');
|
||||
map.set('ak', 'av', Touch.AsNew);
|
||||
assert.deepStrictEqual([...map.keys()], ['bk', 'ak']);
|
||||
assert.deepStrictEqual([...map.values()], ['bv', 'av']);
|
||||
assert.deepStrictEqual(map.keys(), ['bk', 'ak']);
|
||||
assert.deepStrictEqual(map.values(), ['bv', 'av']);
|
||||
});
|
||||
|
||||
test('LinkedMap - Touch Old from middle', () => {
|
||||
@@ -59,8 +59,8 @@ suite('Map', () => {
|
||||
map.set('bk', 'bv');
|
||||
map.set('ck', 'cv');
|
||||
map.set('bk', 'bv', Touch.AsOld);
|
||||
assert.deepStrictEqual([...map.keys()], ['bk', 'ak', 'ck']);
|
||||
assert.deepStrictEqual([...map.values()], ['bv', 'av', 'cv']);
|
||||
assert.deepStrictEqual(map.keys(), ['bk', 'ak', 'ck']);
|
||||
assert.deepStrictEqual(map.values(), ['bv', 'av', 'cv']);
|
||||
});
|
||||
|
||||
test('LinkedMap - Touch New from middle', () => {
|
||||
@@ -69,8 +69,8 @@ suite('Map', () => {
|
||||
map.set('bk', 'bv');
|
||||
map.set('ck', 'cv');
|
||||
map.set('bk', 'bv', Touch.AsNew);
|
||||
assert.deepStrictEqual([...map.keys()], ['ak', 'ck', 'bk']);
|
||||
assert.deepStrictEqual([...map.values()], ['av', 'cv', 'bv']);
|
||||
assert.deepStrictEqual(map.keys(), ['ak', 'ck', 'bk']);
|
||||
assert.deepStrictEqual(map.values(), ['av', 'cv', 'bv']);
|
||||
});
|
||||
|
||||
test('LinkedMap - basics', function () {
|
||||
@@ -136,15 +136,13 @@ suite('Map', () => {
|
||||
assert.strictEqual(cache.size, 5);
|
||||
cache.set(6, 6);
|
||||
assert.strictEqual(cache.size, 5);
|
||||
assert.deepStrictEqual([...cache.keys()], [2, 3, 4, 5, 6]);
|
||||
assert.deepStrictEqual(cache.keys(), [2, 3, 4, 5, 6]);
|
||||
cache.set(7, 7);
|
||||
assert.strictEqual(cache.size, 5);
|
||||
assert.deepStrictEqual([...cache.keys()], [3, 4, 5, 6, 7]);
|
||||
assert.deepStrictEqual(cache.keys(), [3, 4, 5, 6, 7]);
|
||||
let values: number[] = [];
|
||||
[3, 4, 5, 6, 7].forEach(key => values.push(cache.get(key)!));
|
||||
assert.deepStrictEqual(values, [3, 4, 5, 6, 7]);
|
||||
|
||||
assert.deepEqual([...cache.entries()], [[3, 3], [4, 4], [5, 5], [6, 6], [7, 7]]);
|
||||
});
|
||||
|
||||
test('LinkedMap - LRU Cache get', () => {
|
||||
@@ -152,11 +150,11 @@ suite('Map', () => {
|
||||
|
||||
[1, 2, 3, 4, 5].forEach(value => cache.set(value, value));
|
||||
assert.strictEqual(cache.size, 5);
|
||||
assert.deepStrictEqual([...cache.keys()], [1, 2, 3, 4, 5]);
|
||||
assert.deepStrictEqual(cache.keys(), [1, 2, 3, 4, 5]);
|
||||
cache.get(3);
|
||||
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
|
||||
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
|
||||
cache.peek(4);
|
||||
assert.deepStrictEqual([...cache.keys()], [1, 2, 4, 5, 3]);
|
||||
assert.deepStrictEqual(cache.keys(), [1, 2, 4, 5, 3]);
|
||||
let values: number[] = [];
|
||||
[1, 2, 3, 4, 5].forEach(key => values.push(cache.get(key)!));
|
||||
assert.deepStrictEqual(values, [1, 2, 3, 4, 5]);
|
||||
@@ -171,7 +169,7 @@ suite('Map', () => {
|
||||
assert.strictEqual(cache.size, 10);
|
||||
cache.limit = 5;
|
||||
assert.strictEqual(cache.size, 5);
|
||||
assert.deepStrictEqual([...cache.keys()], [6, 7, 8, 9, 10]);
|
||||
assert.deepStrictEqual(cache.keys(), [6, 7, 8, 9, 10]);
|
||||
cache.limit = 20;
|
||||
assert.strictEqual(cache.size, 5);
|
||||
for (let i = 11; i <= 20; i++) {
|
||||
@@ -183,7 +181,7 @@ suite('Map', () => {
|
||||
values.push(cache.get(i)!);
|
||||
assert.strictEqual(cache.get(i), i);
|
||||
}
|
||||
assert.deepStrictEqual([...cache.values()], values);
|
||||
assert.deepStrictEqual(cache.values(), values);
|
||||
});
|
||||
|
||||
test('LinkedMap - LRU Cache limit with ratio', () => {
|
||||
@@ -195,11 +193,11 @@ suite('Map', () => {
|
||||
assert.strictEqual(cache.size, 10);
|
||||
cache.set(11, 11);
|
||||
assert.strictEqual(cache.size, 5);
|
||||
assert.deepStrictEqual([...cache.keys()], [7, 8, 9, 10, 11]);
|
||||
assert.deepStrictEqual(cache.keys(), [7, 8, 9, 10, 11]);
|
||||
let values: number[] = [];
|
||||
[...cache.keys()].forEach(key => values.push(cache.get(key)!));
|
||||
cache.keys().forEach(key => values.push(cache.get(key)!));
|
||||
assert.deepStrictEqual(values, [7, 8, 9, 10, 11]);
|
||||
assert.deepStrictEqual([...cache.values()], values);
|
||||
assert.deepStrictEqual(cache.values(), values);
|
||||
});
|
||||
|
||||
test('LinkedMap - toJSON / fromJSON', () => {
|
||||
@@ -239,7 +237,7 @@ suite('Map', () => {
|
||||
map.delete('1');
|
||||
assert.equal(map.get('1'), undefined);
|
||||
assert.equal(map.size, 0);
|
||||
assert.equal([...map.keys()].length, 0);
|
||||
assert.equal(map.keys().length, 0);
|
||||
});
|
||||
|
||||
test('LinkedMap - delete Head', function () {
|
||||
@@ -253,8 +251,8 @@ suite('Map', () => {
|
||||
map.delete('1');
|
||||
assert.equal(map.get('2'), 2);
|
||||
assert.equal(map.size, 1);
|
||||
assert.equal([...map.keys()].length, 1);
|
||||
assert.equal([...map.keys()][0], 2);
|
||||
assert.equal(map.keys().length, 1);
|
||||
assert.equal(map.keys()[0], 2);
|
||||
});
|
||||
|
||||
test('LinkedMap - delete Tail', function () {
|
||||
@@ -268,8 +266,8 @@ suite('Map', () => {
|
||||
map.delete('2');
|
||||
assert.equal(map.get('1'), 1);
|
||||
assert.equal(map.size, 1);
|
||||
assert.equal([...map.keys()].length, 1);
|
||||
assert.equal([...map.keys()][0], 1);
|
||||
assert.equal(map.keys().length, 1);
|
||||
assert.equal(map.keys()[0], 1);
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -31,84 +31,6 @@ function gestureChangeEventMerger(lastEvent: IThrottledGestureEvent | null, curr
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically IE10 and IE11
|
||||
*/
|
||||
class MsPointerHandler extends MouseHandler implements IDisposable {
|
||||
|
||||
private _lastPointerType: string;
|
||||
private _installGestureHandlerTimeout: number;
|
||||
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
super(context, viewController, viewHelper);
|
||||
|
||||
(this.viewHelper.linesContentDomNode.style as any).msTouchAction = 'none';
|
||||
(this.viewHelper.linesContentDomNode.style as any).msContentZooming = 'none';
|
||||
|
||||
// TODO@Alex -> this expects that the view is added in 100 ms, might not be the case
|
||||
// This handler should be added when the dom node is in the dom tree
|
||||
this._installGestureHandlerTimeout = window.setTimeout(() => {
|
||||
this._installGestureHandlerTimeout = -1;
|
||||
if ((<any>window).MSGesture) {
|
||||
const touchGesture = new MSGesture();
|
||||
const penGesture = new MSGesture();
|
||||
touchGesture.target = this.viewHelper.linesContentDomNode;
|
||||
penGesture.target = this.viewHelper.linesContentDomNode;
|
||||
this.viewHelper.linesContentDomNode.addEventListener(<any>'MSPointerDown', (e: MSPointerEvent) => {
|
||||
// Circumvent IE11 breaking change in e.pointerType & TypeScript's stale definitions
|
||||
const pointerType = <any>e.pointerType;
|
||||
if (pointerType === ((<any>e).MSPOINTER_TYPE_MOUSE || 'mouse')) {
|
||||
this._lastPointerType = 'mouse';
|
||||
return;
|
||||
} else if (pointerType === ((<any>e).MSPOINTER_TYPE_TOUCH || 'touch')) {
|
||||
this._lastPointerType = 'touch';
|
||||
touchGesture.addPointer(e.pointerId);
|
||||
} else {
|
||||
this._lastPointerType = 'pen';
|
||||
penGesture.addPointer(e.pointerId);
|
||||
}
|
||||
});
|
||||
this._register(dom.addDisposableThrottledListener<IThrottledGestureEvent, MSGestureEvent>(this.viewHelper.linesContentDomNode, 'MSGestureChange', (e) => this._onGestureChange(e), gestureChangeEventMerger));
|
||||
this._register(dom.addDisposableListener(this.viewHelper.linesContentDomNode, 'MSGestureTap', (e) => this._onCaptureGestureTap(e), true));
|
||||
}
|
||||
}, 100);
|
||||
this._lastPointerType = 'mouse';
|
||||
}
|
||||
|
||||
public _onMouseDown(e: EditorMouseEvent): void {
|
||||
if (this._lastPointerType === 'mouse') {
|
||||
super._onMouseDown(e);
|
||||
}
|
||||
}
|
||||
|
||||
private _onCaptureGestureTap(rawEvent: MSGestureEvent): void {
|
||||
const e = new EditorMouseEvent(<MouseEvent><any>rawEvent, this.viewHelper.viewDomNode);
|
||||
const t = this._createMouseTarget(e, false);
|
||||
if (t.position) {
|
||||
this.viewController.moveTo(t.position);
|
||||
}
|
||||
// IE does not want to focus when coming in from the browser's address bar
|
||||
if ((<any>e.browserEvent).fromElement) {
|
||||
e.preventDefault();
|
||||
this.viewHelper.focusTextArea();
|
||||
} else {
|
||||
// TODO@Alex -> cancel this is focus is lost
|
||||
setTimeout(() => {
|
||||
this.viewHelper.focusTextArea();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private _onGestureChange(e: IThrottledGestureEvent): void {
|
||||
this._context.viewLayout.deltaScrollNow(-e.translationX, -e.translationY);
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
window.clearTimeout(this._installGestureHandlerTimeout);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Basically Edge but should be modified to handle any pointerEnabled, even without support of MSGesture
|
||||
*/
|
||||
@@ -302,9 +224,7 @@ export class PointerHandler extends Disposable {
|
||||
|
||||
constructor(context: ViewContext, viewController: ViewController, viewHelper: IPointerHandlerHelper) {
|
||||
super();
|
||||
if (window.navigator.msPointerEnabled) {
|
||||
this.handler = this._register(new MsPointerHandler(context, viewController, viewHelper));
|
||||
} else if ((platform.isIOS && BrowserFeatures.pointerEvents)) {
|
||||
if ((platform.isIOS && BrowserFeatures.pointerEvents)) {
|
||||
this.handler = this._register(new PointerEventHandler(context, viewController, viewHelper));
|
||||
} else if ((<any>window).TouchEvent) {
|
||||
this.handler = this._register(new TouchHandler(context, viewController, viewHelper));
|
||||
|
||||
@@ -111,7 +111,7 @@ export class EditorScrollbar extends ViewPart {
|
||||
const minimap = options.get(EditorOption.minimap);
|
||||
const side = minimap.side;
|
||||
if (side === 'right') {
|
||||
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimapWidth);
|
||||
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth + layoutInfo.minimap.minimapWidth);
|
||||
} else {
|
||||
this.scrollbarDomNode.setWidth(layoutInfo.contentWidth);
|
||||
}
|
||||
|
||||
@@ -104,30 +104,31 @@ class MinimapOptions {
|
||||
const options = configuration.options;
|
||||
const pixelRatio = options.get(EditorOption.pixelRatio);
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
const minimapLayout = layoutInfo.minimap;
|
||||
const fontInfo = options.get(EditorOption.fontInfo);
|
||||
const minimapOpts = options.get(EditorOption.minimap);
|
||||
|
||||
this.renderMinimap = layoutInfo.renderMinimap | 0;
|
||||
this.renderMinimap = minimapLayout.renderMinimap;
|
||||
this.size = minimapOpts.size;
|
||||
this.minimapHeightIsEditorHeight = layoutInfo.minimapHeightIsEditorHeight;
|
||||
this.minimapHeightIsEditorHeight = minimapLayout.minimapHeightIsEditorHeight;
|
||||
this.scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
|
||||
this.showSlider = minimapOpts.showSlider;
|
||||
this.pixelRatio = pixelRatio;
|
||||
this.typicalHalfwidthCharacterWidth = fontInfo.typicalHalfwidthCharacterWidth;
|
||||
this.lineHeight = options.get(EditorOption.lineHeight);
|
||||
this.minimapLeft = layoutInfo.minimapLeft;
|
||||
this.minimapWidth = layoutInfo.minimapWidth;
|
||||
this.minimapLeft = minimapLayout.minimapLeft;
|
||||
this.minimapWidth = minimapLayout.minimapWidth;
|
||||
this.minimapHeight = layoutInfo.height;
|
||||
|
||||
this.canvasInnerWidth = layoutInfo.minimapCanvasInnerWidth;
|
||||
this.canvasInnerHeight = layoutInfo.minimapCanvasInnerHeight;
|
||||
this.canvasOuterWidth = layoutInfo.minimapCanvasOuterWidth;
|
||||
this.canvasOuterHeight = layoutInfo.minimapCanvasOuterHeight;
|
||||
this.canvasInnerWidth = minimapLayout.minimapCanvasInnerWidth;
|
||||
this.canvasInnerHeight = minimapLayout.minimapCanvasInnerHeight;
|
||||
this.canvasOuterWidth = minimapLayout.minimapCanvasOuterWidth;
|
||||
this.canvasOuterHeight = minimapLayout.minimapCanvasOuterHeight;
|
||||
|
||||
this.isSampling = layoutInfo.minimapIsSampling;
|
||||
this.isSampling = minimapLayout.minimapIsSampling;
|
||||
this.editorHeight = layoutInfo.height;
|
||||
this.fontScale = layoutInfo.minimapScale;
|
||||
this.minimapLineHeight = layoutInfo.minimapLineHeight;
|
||||
this.fontScale = minimapLayout.minimapScale;
|
||||
this.minimapLineHeight = minimapLayout.minimapLineHeight;
|
||||
this.minimapCharWidth = Constants.BASE_CHAR_WIDTH * this.fontScale;
|
||||
|
||||
this.charRenderer = once(() => MinimapCharRendererFactory.create(this.fontScale, fontInfo.fontFamily));
|
||||
@@ -262,7 +263,8 @@ class MinimapLayout {
|
||||
const computedSliderRatio = (maxMinimapSliderTop) / (scrollHeight - viewportHeight);
|
||||
const sliderTop = (scrollTop * computedSliderRatio);
|
||||
const sliderNeeded = (maxMinimapSliderTop > 0);
|
||||
return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, 1, lineCount);
|
||||
const maxLinesFitting = Math.floor(options.canvasInnerHeight / options.minimapLineHeight);
|
||||
return new MinimapLayout(scrollTop, scrollHeight, sliderNeeded, computedSliderRatio, sliderTop, sliderHeight, 1, Math.min(lineCount, maxLinesFitting));
|
||||
}
|
||||
|
||||
// The visible line count in a viewport can change due to a number of reasons:
|
||||
|
||||
@@ -42,7 +42,7 @@ export class ViewOverlayWidgets extends ViewPart {
|
||||
|
||||
this._widgets = {};
|
||||
this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;
|
||||
this._minimapWidth = layoutInfo.minimapWidth;
|
||||
this._minimapWidth = layoutInfo.minimap.minimapWidth;
|
||||
this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;
|
||||
this._editorHeight = layoutInfo.height;
|
||||
this._editorWidth = layoutInfo.width;
|
||||
@@ -68,7 +68,7 @@ export class ViewOverlayWidgets extends ViewPart {
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
|
||||
this._verticalScrollbarWidth = layoutInfo.verticalScrollbarWidth;
|
||||
this._minimapWidth = layoutInfo.minimapWidth;
|
||||
this._minimapWidth = layoutInfo.minimap.minimapWidth;
|
||||
this._horizontalScrollbarHeight = layoutInfo.horizontalScrollbarHeight;
|
||||
this._editorHeight = layoutInfo.height;
|
||||
this._editorWidth = layoutInfo.width;
|
||||
|
||||
@@ -58,10 +58,10 @@ export class ScrollDecorationViewPart extends ViewPart {
|
||||
const options = this._context.configuration.options;
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
|
||||
if (layoutInfo.renderMinimap === 0 || (layoutInfo.minimapWidth > 0 && layoutInfo.minimapLeft === 0)) {
|
||||
if (layoutInfo.minimap.renderMinimap === 0 || (layoutInfo.minimap.minimapWidth > 0 && layoutInfo.minimap.minimapLeft === 0)) {
|
||||
this._width = layoutInfo.width;
|
||||
} else {
|
||||
this._width = layoutInfo.width - layoutInfo.minimapWidth - layoutInfo.verticalScrollbarWidth;
|
||||
this._width = layoutInfo.width - layoutInfo.minimap.minimapWidth - layoutInfo.verticalScrollbarWidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { IEditorOptions, editorOptionsRegistry, ValidatedEditorOptions, IEnvironmentalOptions, IComputedEditorOptions, ConfigurationChangedEvent, EDITOR_MODEL_DEFAULTS, EditorOption, FindComputedEditorOptionValueById } from 'vs/editor/common/config/editorOptions';
|
||||
import { IEditorOptions, editorOptionsRegistry, ValidatedEditorOptions, IEnvironmentalOptions, IComputedEditorOptions, ConfigurationChangedEvent, EDITOR_MODEL_DEFAULTS, EditorOption, FindComputedEditorOptionValueById, ComputeOptionsMemory } from 'vs/editor/common/config/editorOptions';
|
||||
import { EditorZoom } from 'vs/editor/common/config/editorZoom';
|
||||
import { BareFontInfo, FontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { IConfiguration, IDimension } from 'vs/editor/common/editorCommon';
|
||||
@@ -284,6 +284,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
public readonly onDidChange: Event<ConfigurationChangedEvent> = this._onDidChange.event;
|
||||
|
||||
public readonly isSimpleWidget: boolean;
|
||||
private _computeOptionsMemory: ComputeOptionsMemory;
|
||||
public options!: ComputedEditorOptions;
|
||||
|
||||
private _isDominatedByLongLines: boolean;
|
||||
@@ -299,6 +300,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
this.isSimpleWidget = isSimpleWidget;
|
||||
|
||||
this._isDominatedByLongLines = false;
|
||||
this._computeOptionsMemory = new ComputeOptionsMemory();
|
||||
this._viewLineCount = 1;
|
||||
this._lineNumbersDigitCount = 1;
|
||||
|
||||
@@ -344,6 +346,7 @@ export abstract class CommonEditorConfiguration extends Disposable implements IC
|
||||
const partialEnv = this._getEnvConfiguration();
|
||||
const bareFontInfo = BareFontInfo.createFromValidatedSettings(this._validatedOptions, partialEnv.zoomLevel, this.isSimpleWidget);
|
||||
const env: IEnvironmentalOptions = {
|
||||
memory: this._computeOptionsMemory,
|
||||
outerWidth: partialEnv.outerWidth,
|
||||
outerHeight: partialEnv.outerHeight,
|
||||
fontInfo: this.readConfiguration(bareFontInfo),
|
||||
|
||||
@@ -693,6 +693,7 @@ export interface IComputedEditorOptions {
|
||||
* @internal
|
||||
*/
|
||||
export interface IEnvironmentalOptions {
|
||||
readonly memory: ComputeOptionsMemory | null;
|
||||
readonly outerWidth: number;
|
||||
readonly outerHeight: number;
|
||||
readonly fontInfo: FontInfo;
|
||||
@@ -706,6 +707,22 @@ export interface IEnvironmentalOptions {
|
||||
readonly accessibilitySupport: AccessibilitySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class ComputeOptionsMemory {
|
||||
|
||||
public stableMinimapLayoutInput: IMinimapLayoutInput | null;
|
||||
public stableFitMaxMinimapScale: number;
|
||||
public stableFitRemainingWidth: number;
|
||||
|
||||
constructor() {
|
||||
this.stableMinimapLayoutInput = null;
|
||||
this.stableFitMaxMinimapScale = 0;
|
||||
this.stableFitRemainingWidth = 0;
|
||||
}
|
||||
}
|
||||
|
||||
export interface IEditorOption<K1 extends EditorOption, V> {
|
||||
readonly id: K1;
|
||||
readonly name: string;
|
||||
@@ -1717,32 +1734,19 @@ export interface EditorLayoutInfo {
|
||||
readonly contentWidth: number;
|
||||
|
||||
/**
|
||||
* The position for the minimap
|
||||
* Layout information for the minimap
|
||||
*/
|
||||
readonly minimapLeft: number;
|
||||
/**
|
||||
* The width of the minimap
|
||||
*/
|
||||
readonly minimapWidth: number;
|
||||
readonly minimapHeightIsEditorHeight: boolean;
|
||||
readonly minimapIsSampling: boolean;
|
||||
readonly minimapScale: number;
|
||||
readonly minimapLineHeight: number;
|
||||
readonly minimapCanvasInnerWidth: number;
|
||||
readonly minimapCanvasInnerHeight: number;
|
||||
readonly minimapCanvasOuterWidth: number;
|
||||
readonly minimapCanvasOuterHeight: number;
|
||||
|
||||
/**
|
||||
* Minimap render type
|
||||
*/
|
||||
readonly renderMinimap: RenderMinimap;
|
||||
readonly minimap: EditorMinimapLayoutInfo;
|
||||
|
||||
/**
|
||||
* The number of columns (of typical characters) fitting on a viewport line.
|
||||
*/
|
||||
readonly viewportColumn: number;
|
||||
|
||||
readonly isWordWrapMinified: boolean;
|
||||
readonly isViewportWrapping: boolean;
|
||||
readonly wrappingColumn: number;
|
||||
|
||||
/**
|
||||
* The width of the vertical scrollbar.
|
||||
*/
|
||||
@@ -1758,18 +1762,80 @@ export interface EditorLayoutInfo {
|
||||
readonly overviewRuler: OverviewRulerPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal layout details of the editor.
|
||||
*/
|
||||
export interface EditorMinimapLayoutInfo {
|
||||
readonly renderMinimap: RenderMinimap;
|
||||
readonly minimapLeft: number;
|
||||
readonly minimapWidth: number;
|
||||
readonly minimapHeightIsEditorHeight: boolean;
|
||||
readonly minimapIsSampling: boolean;
|
||||
readonly minimapScale: number;
|
||||
readonly minimapLineHeight: number;
|
||||
readonly minimapCanvasInnerWidth: number;
|
||||
readonly minimapCanvasInnerHeight: number;
|
||||
readonly minimapCanvasOuterWidth: number;
|
||||
readonly minimapCanvasOuterHeight: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface EditorLayoutInfoComputerEnv {
|
||||
outerWidth: number;
|
||||
outerHeight: number;
|
||||
lineHeight: number;
|
||||
viewLineCount: number;
|
||||
lineNumbersDigitCount: number;
|
||||
typicalHalfwidthCharacterWidth: number;
|
||||
maxDigitWidth: number;
|
||||
pixelRatio: number;
|
||||
readonly memory: ComputeOptionsMemory | null;
|
||||
readonly outerWidth: number;
|
||||
readonly outerHeight: number;
|
||||
readonly isDominatedByLongLines: boolean
|
||||
readonly lineHeight: number;
|
||||
readonly viewLineCount: number;
|
||||
readonly lineNumbersDigitCount: number;
|
||||
readonly typicalHalfwidthCharacterWidth: number;
|
||||
readonly maxDigitWidth: number;
|
||||
readonly pixelRatio: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IEditorLayoutComputerInput {
|
||||
readonly outerWidth: number;
|
||||
readonly outerHeight: number;
|
||||
readonly isDominatedByLongLines: boolean
|
||||
readonly lineHeight: number;
|
||||
readonly lineNumbersDigitCount: number;
|
||||
readonly typicalHalfwidthCharacterWidth: number;
|
||||
readonly maxDigitWidth: number;
|
||||
readonly pixelRatio: number;
|
||||
readonly glyphMargin: boolean;
|
||||
readonly lineDecorationsWidth: string | number;
|
||||
readonly folding: boolean;
|
||||
readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
|
||||
readonly scrollbar: InternalEditorScrollbarOptions;
|
||||
readonly lineNumbers: InternalEditorRenderLineNumbersOptions;
|
||||
readonly lineNumbersMinChars: number;
|
||||
readonly scrollBeyondLastLine: boolean;
|
||||
readonly wordWrap: 'wordWrapColumn' | 'on' | 'off' | 'bounded';
|
||||
readonly wordWrapColumn: number;
|
||||
readonly wordWrapMinified: boolean;
|
||||
readonly accessibilitySupport: AccessibilitySupport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export interface IMinimapLayoutInput {
|
||||
readonly outerWidth: number;
|
||||
readonly outerHeight: number;
|
||||
readonly lineHeight: number;
|
||||
readonly typicalHalfwidthCharacterWidth: number;
|
||||
readonly pixelRatio: number;
|
||||
readonly scrollBeyondLastLine: boolean;
|
||||
readonly minimap: Readonly<Required<IEditorMinimapOptions>>;
|
||||
readonly verticalScrollbarWidth: number;
|
||||
readonly viewLineCount: number;
|
||||
readonly remainingWidth: number;
|
||||
readonly isViewportWrapping: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1780,14 +1846,22 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
constructor() {
|
||||
super(
|
||||
EditorOption.layoutInfo,
|
||||
[EditorOption.glyphMargin, EditorOption.lineDecorationsWidth, EditorOption.folding, EditorOption.minimap, EditorOption.scrollbar, EditorOption.lineNumbers]
|
||||
[
|
||||
EditorOption.glyphMargin, EditorOption.lineDecorationsWidth, EditorOption.folding,
|
||||
EditorOption.minimap, EditorOption.scrollbar, EditorOption.lineNumbers,
|
||||
EditorOption.lineNumbersMinChars, EditorOption.scrollBeyondLastLine,
|
||||
EditorOption.wordWrap, EditorOption.wordWrapColumn, EditorOption.wordWrapMinified,
|
||||
EditorOption.accessibilitySupport
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorLayoutInfo): EditorLayoutInfo {
|
||||
return EditorLayoutInfoComputer.computeLayout(options, {
|
||||
memory: env.memory,
|
||||
outerWidth: env.outerWidth,
|
||||
outerHeight: env.outerHeight,
|
||||
isDominatedByLongLines: env.isDominatedByLongLines,
|
||||
lineHeight: env.fontInfo.lineHeight,
|
||||
viewLineCount: env.viewLineCount,
|
||||
lineNumbersDigitCount: env.lineNumbersDigitCount,
|
||||
@@ -1811,6 +1885,172 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
return { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount };
|
||||
}
|
||||
|
||||
private static _computeMinimapLayout(input: IMinimapLayoutInput, memory: ComputeOptionsMemory): EditorMinimapLayoutInfo {
|
||||
const outerWidth = input.outerWidth;
|
||||
const outerHeight = input.outerHeight;
|
||||
const pixelRatio = input.pixelRatio;
|
||||
|
||||
if (!input.minimap.enabled) {
|
||||
return {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
minimapHeightIsEditorHeight: false,
|
||||
minimapIsSampling: false,
|
||||
minimapScale: 1,
|
||||
minimapLineHeight: 1,
|
||||
minimapCanvasInnerWidth: 0,
|
||||
minimapCanvasInnerHeight: Math.floor(pixelRatio * outerHeight),
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: outerHeight,
|
||||
};
|
||||
}
|
||||
|
||||
// Can use memory if only the `viewLineCount` and `remainingWidth` have changed
|
||||
const stableMinimapLayoutInput = memory.stableMinimapLayoutInput;
|
||||
const couldUseMemory = (
|
||||
stableMinimapLayoutInput
|
||||
// && input.outerWidth === lastMinimapLayoutInput.outerWidth !!! INTENTIONAL OMITTED
|
||||
&& input.outerHeight === stableMinimapLayoutInput.outerHeight
|
||||
&& input.lineHeight === stableMinimapLayoutInput.lineHeight
|
||||
&& input.typicalHalfwidthCharacterWidth === stableMinimapLayoutInput.typicalHalfwidthCharacterWidth
|
||||
&& input.pixelRatio === stableMinimapLayoutInput.pixelRatio
|
||||
&& input.scrollBeyondLastLine === stableMinimapLayoutInput.scrollBeyondLastLine
|
||||
&& input.minimap.enabled === stableMinimapLayoutInput.minimap.enabled
|
||||
&& input.minimap.side === stableMinimapLayoutInput.minimap.side
|
||||
&& input.minimap.size === stableMinimapLayoutInput.minimap.size
|
||||
&& input.minimap.showSlider === stableMinimapLayoutInput.minimap.showSlider
|
||||
&& input.minimap.renderCharacters === stableMinimapLayoutInput.minimap.renderCharacters
|
||||
&& input.minimap.maxColumn === stableMinimapLayoutInput.minimap.maxColumn
|
||||
&& input.minimap.scale === stableMinimapLayoutInput.minimap.scale
|
||||
&& input.verticalScrollbarWidth === stableMinimapLayoutInput.verticalScrollbarWidth
|
||||
// && input.viewLineCount === lastMinimapLayoutInput.viewLineCount !!! INTENTIONAL OMITTED
|
||||
// && input.remainingWidth === lastMinimapLayoutInput.remainingWidth !!! INTENTIONAL OMITTED
|
||||
&& input.isViewportWrapping === stableMinimapLayoutInput.isViewportWrapping
|
||||
);
|
||||
|
||||
const lineHeight = input.lineHeight;
|
||||
const typicalHalfwidthCharacterWidth = input.typicalHalfwidthCharacterWidth;
|
||||
const scrollBeyondLastLine = input.scrollBeyondLastLine;
|
||||
const minimapRenderCharacters = input.minimap.renderCharacters;
|
||||
let minimapScale = (pixelRatio >= 2 ? Math.round(input.minimap.scale * 2) : input.minimap.scale);
|
||||
const minimapMaxColumn = input.minimap.maxColumn;
|
||||
const minimapSize = input.minimap.size;
|
||||
const minimapSide = input.minimap.side;
|
||||
const verticalScrollbarWidth = input.verticalScrollbarWidth;
|
||||
const viewLineCount = input.viewLineCount;
|
||||
const remainingWidth = input.remainingWidth;
|
||||
const isViewportWrapping = input.isViewportWrapping;
|
||||
|
||||
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
|
||||
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
|
||||
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
|
||||
let minimapHeightIsEditorHeight = false;
|
||||
let minimapIsSampling = false;
|
||||
let minimapLineHeight = baseCharHeight * minimapScale;
|
||||
let minimapCharWidth = minimapScale / pixelRatio;
|
||||
let minimapWidthMultiplier: number = 1;
|
||||
|
||||
if (minimapSize === 'fill' || minimapSize === 'fit') {
|
||||
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
||||
viewLineCount: viewLineCount,
|
||||
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||
height: outerHeight,
|
||||
lineHeight: lineHeight,
|
||||
pixelRatio: pixelRatio
|
||||
});
|
||||
// ratio is intentionally not part of the layout to avoid the layout changing all the time
|
||||
// when doing sampling
|
||||
const ratio = viewLineCount / minimapLineCount;
|
||||
|
||||
if (ratio > 1) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
minimapIsSampling = true;
|
||||
minimapScale = 1;
|
||||
minimapLineHeight = 1;
|
||||
minimapCharWidth = minimapScale / pixelRatio;
|
||||
} else {
|
||||
let fitBecomesFill = false;
|
||||
let maxMinimapScale = minimapScale + 1;
|
||||
|
||||
if (minimapSize === 'fit') {
|
||||
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||
if (isViewportWrapping && couldUseMemory && remainingWidth <= memory.stableFitRemainingWidth) {
|
||||
// There is a loop when using `fit` and viewport wrapping:
|
||||
// - view line count impacts minimap layout
|
||||
// - minimap layout impacts viewport width
|
||||
// - viewport width impacts view line count
|
||||
// To break the loop, once we go to a smaller minimap scale, we try to stick with it.
|
||||
fitBecomesFill = true;
|
||||
maxMinimapScale = memory.stableFitMaxMinimapScale;
|
||||
} else {
|
||||
fitBecomesFill = (effectiveMinimapHeight > minimapCanvasInnerHeight);
|
||||
if (isViewportWrapping && fitBecomesFill) {
|
||||
// remember for next time
|
||||
memory.stableMinimapLayoutInput = input;
|
||||
memory.stableFitRemainingWidth = remainingWidth;
|
||||
} else {
|
||||
memory.stableMinimapLayoutInput = null;
|
||||
memory.stableFitRemainingWidth = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (minimapSize === 'fill' || fitBecomesFill) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
const configuredMinimapScale = minimapScale;
|
||||
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
|
||||
minimapScale = Math.min(maxMinimapScale, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
|
||||
if (minimapScale > configuredMinimapScale) {
|
||||
minimapWidthMultiplier = Math.min(2, minimapScale / configuredMinimapScale);
|
||||
}
|
||||
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
|
||||
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
|
||||
if (isViewportWrapping && fitBecomesFill) {
|
||||
memory.stableFitMaxMinimapScale = minimapScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Given:
|
||||
// (leaving 2px for the cursor to have space after the last character)
|
||||
// viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth
|
||||
// minimapWidth = viewportColumn * minimapCharWidth
|
||||
// contentWidth = remainingWidth - minimapWidth
|
||||
// What are good values for contentWidth and minimapWidth ?
|
||||
|
||||
// minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth
|
||||
// typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth)
|
||||
|
||||
const minimapMaxWidth = Math.floor(minimapMaxColumn * minimapCharWidth);
|
||||
const minimapWidth = Math.min(minimapMaxWidth, Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH);
|
||||
|
||||
let minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
|
||||
const minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
|
||||
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
|
||||
|
||||
const renderMinimap = (minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks);
|
||||
const minimapLeft = (minimapSide === 'left' ? 0 : (outerWidth - minimapWidth - verticalScrollbarWidth));
|
||||
|
||||
return {
|
||||
renderMinimap,
|
||||
minimapLeft,
|
||||
minimapWidth,
|
||||
minimapHeightIsEditorHeight,
|
||||
minimapIsSampling,
|
||||
minimapScale,
|
||||
minimapLineHeight,
|
||||
minimapCanvasInnerWidth,
|
||||
minimapCanvasInnerHeight,
|
||||
minimapCanvasOuterWidth,
|
||||
minimapCanvasOuterHeight,
|
||||
};
|
||||
}
|
||||
|
||||
public static computeLayout(options: IComputedEditorOptions, env: EditorLayoutInfoComputerEnv): EditorLayoutInfo {
|
||||
const outerWidth = env.outerWidth | 0;
|
||||
const outerHeight = env.outerHeight | 0;
|
||||
@@ -1819,24 +2059,25 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
const typicalHalfwidthCharacterWidth = env.typicalHalfwidthCharacterWidth;
|
||||
const maxDigitWidth = env.maxDigitWidth;
|
||||
const pixelRatio = env.pixelRatio;
|
||||
const viewLineCount = env.viewLineCount;
|
||||
|
||||
const wordWrap = options.get(EditorOption.wordWrap);
|
||||
const wordWrapColumn = options.get(EditorOption.wordWrapColumn);
|
||||
const wordWrapMinified = options.get(EditorOption.wordWrapMinified);
|
||||
const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
|
||||
const isDominatedByLongLines = env.isDominatedByLongLines;
|
||||
|
||||
const showGlyphMargin = options.get(EditorOption.glyphMargin);
|
||||
const showLineNumbers = (options.get(EditorOption.lineNumbers).renderType !== RenderLineNumbersType.Off);
|
||||
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars) | 0;
|
||||
const lineNumbersMinChars = options.get(EditorOption.lineNumbersMinChars);
|
||||
const scrollBeyondLastLine = options.get(EditorOption.scrollBeyondLastLine);
|
||||
const minimap = options.get(EditorOption.minimap);
|
||||
const minimapEnabled = minimap.enabled;
|
||||
const minimapSide = minimap.side;
|
||||
const minimapRenderCharacters = minimap.renderCharacters;
|
||||
let minimapScale = (pixelRatio >= 2 ? Math.round(minimap.scale * 2) : minimap.scale);
|
||||
const minimapMaxColumn = minimap.maxColumn | 0;
|
||||
const minimapSize = minimap.size;
|
||||
|
||||
const scrollbar = options.get(EditorOption.scrollbar);
|
||||
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize | 0;
|
||||
const verticalScrollbarWidth = scrollbar.verticalScrollbarSize;
|
||||
const verticalScrollbarHasArrows = scrollbar.verticalHasArrows;
|
||||
const scrollbarArrowSize = scrollbar.arrowSize | 0;
|
||||
const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize | 0;
|
||||
const scrollbarArrowSize = scrollbar.arrowSize;
|
||||
const horizontalScrollbarHeight = scrollbar.horizontalScrollbarSize;
|
||||
|
||||
const rawLineDecorationsWidth = options.get(EditorOption.lineDecorationsWidth);
|
||||
const folding = options.get(EditorOption.folding);
|
||||
@@ -1870,107 +2111,62 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
|
||||
const remainingWidth = outerWidth - glyphMarginWidth - lineNumbersWidth - lineDecorationsWidth;
|
||||
|
||||
const baseCharHeight = minimapRenderCharacters ? 2 : 3;
|
||||
let renderMinimap: RenderMinimap;
|
||||
let minimapLeft: number;
|
||||
let minimapWidth: number;
|
||||
let minimapCanvasInnerWidth: number;
|
||||
let minimapCanvasInnerHeight = Math.floor(pixelRatio * outerHeight);
|
||||
let minimapCanvasOuterWidth: number;
|
||||
const minimapCanvasOuterHeight = minimapCanvasInnerHeight / pixelRatio;
|
||||
let minimapHeightIsEditorHeight = false;
|
||||
let minimapIsSampling = false;
|
||||
let minimapLineHeight = baseCharHeight * minimapScale;
|
||||
let contentWidth: number;
|
||||
if (!minimapEnabled) {
|
||||
minimapLeft = 0;
|
||||
minimapWidth = 0;
|
||||
minimapCanvasInnerWidth = 0;
|
||||
minimapCanvasOuterWidth = 0;
|
||||
minimapLineHeight = 1;
|
||||
renderMinimap = RenderMinimap.None;
|
||||
contentWidth = remainingWidth;
|
||||
} else {
|
||||
let minimapCharWidth = minimapScale / pixelRatio;
|
||||
let minimapWidthMultiplier: number = 1;
|
||||
let isWordWrapMinified = false;
|
||||
let isViewportWrapping = false;
|
||||
let wrappingColumn = -1;
|
||||
|
||||
if (minimapSize === 'fill' || minimapSize === 'fit') {
|
||||
const viewLineCount = env.viewLineCount;
|
||||
const { typicalViewportLineCount, extraLinesBeyondLastLine, desiredRatio, minimapLineCount } = EditorLayoutInfoComputer.computeContainedMinimapLineCount({
|
||||
viewLineCount: viewLineCount,
|
||||
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||
height: outerHeight,
|
||||
if (accessibilitySupport !== AccessibilitySupport.Enabled) {
|
||||
// See https://github.com/Microsoft/vscode/issues/27766
|
||||
// Never enable wrapping when a screen reader is attached
|
||||
// because arrow down etc. will not move the cursor in the way
|
||||
// a screen reader expects.
|
||||
if (wordWrapMinified && isDominatedByLongLines) {
|
||||
// Force viewport width wrapping if model is dominated by long lines
|
||||
isWordWrapMinified = true;
|
||||
isViewportWrapping = true;
|
||||
} else if (wordWrap === 'on' || wordWrap === 'bounded') {
|
||||
isViewportWrapping = true;
|
||||
} else if (wordWrap === 'wordWrapColumn') {
|
||||
wrappingColumn = wordWrapColumn;
|
||||
}
|
||||
}
|
||||
|
||||
const minimapLayout = EditorLayoutInfoComputer._computeMinimapLayout({
|
||||
outerWidth: outerWidth,
|
||||
outerHeight: outerHeight,
|
||||
lineHeight: lineHeight,
|
||||
pixelRatio: pixelRatio
|
||||
});
|
||||
// ratio is intentionally not part of the layout to avoid the layout changing all the time
|
||||
// when doing sampling
|
||||
const ratio = viewLineCount / minimapLineCount;
|
||||
typicalHalfwidthCharacterWidth: typicalHalfwidthCharacterWidth,
|
||||
pixelRatio: pixelRatio,
|
||||
scrollBeyondLastLine: scrollBeyondLastLine,
|
||||
minimap: minimap,
|
||||
verticalScrollbarWidth: verticalScrollbarWidth,
|
||||
viewLineCount: viewLineCount,
|
||||
remainingWidth: remainingWidth,
|
||||
isViewportWrapping: isViewportWrapping,
|
||||
}, env.memory || new ComputeOptionsMemory());
|
||||
|
||||
if (ratio > 1) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
minimapIsSampling = true;
|
||||
minimapScale = 1;
|
||||
minimapLineHeight = 1;
|
||||
minimapCharWidth = minimapScale / pixelRatio;
|
||||
} else {
|
||||
const effectiveMinimapHeight = Math.ceil((viewLineCount + extraLinesBeyondLastLine) * minimapLineHeight);
|
||||
if (minimapSize === 'fill' || effectiveMinimapHeight > minimapCanvasInnerHeight) {
|
||||
minimapHeightIsEditorHeight = true;
|
||||
const configuredFontScale = minimapScale;
|
||||
minimapLineHeight = Math.min(lineHeight * pixelRatio, Math.max(1, Math.floor(1 / desiredRatio)));
|
||||
minimapScale = Math.min(configuredFontScale + 1, Math.max(1, Math.floor(minimapLineHeight / baseCharHeight)));
|
||||
if (minimapScale > configuredFontScale) {
|
||||
minimapWidthMultiplier = Math.min(2, minimapScale / configuredFontScale);
|
||||
}
|
||||
minimapCharWidth = minimapScale / pixelRatio / minimapWidthMultiplier;
|
||||
minimapCanvasInnerHeight = Math.ceil((Math.max(typicalViewportLineCount, viewLineCount + extraLinesBeyondLastLine)) * minimapLineHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderMinimap = minimapRenderCharacters ? RenderMinimap.Text : RenderMinimap.Blocks;
|
||||
|
||||
// Given:
|
||||
// (leaving 2px for the cursor to have space after the last character)
|
||||
// viewportColumn = (contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth
|
||||
// minimapWidth = viewportColumn * minimapCharWidth
|
||||
// contentWidth = remainingWidth - minimapWidth
|
||||
// What are good values for contentWidth and minimapWidth ?
|
||||
|
||||
// minimapWidth = ((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth) * minimapCharWidth
|
||||
// typicalHalfwidthCharacterWidth * minimapWidth = (contentWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// typicalHalfwidthCharacterWidth * minimapWidth = (remainingWidth - minimapWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// (typicalHalfwidthCharacterWidth + minimapCharWidth) * minimapWidth = (remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth
|
||||
// minimapWidth = ((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth)
|
||||
|
||||
minimapWidth = Math.max(0, Math.floor(((remainingWidth - verticalScrollbarWidth - 2) * minimapCharWidth) / (typicalHalfwidthCharacterWidth + minimapCharWidth))) + MINIMAP_GUTTER_WIDTH;
|
||||
let minimapColumns = minimapWidth / minimapCharWidth;
|
||||
if (minimapColumns > minimapMaxColumn) {
|
||||
minimapWidth = Math.floor(minimapMaxColumn * minimapCharWidth);
|
||||
}
|
||||
contentWidth = remainingWidth - minimapWidth;
|
||||
|
||||
if (minimapSide === 'left') {
|
||||
minimapLeft = 0;
|
||||
glyphMarginLeft += minimapWidth;
|
||||
lineNumbersLeft += minimapWidth;
|
||||
decorationsLeft += minimapWidth;
|
||||
contentLeft += minimapWidth;
|
||||
} else {
|
||||
minimapLeft = outerWidth - minimapWidth - verticalScrollbarWidth;
|
||||
}
|
||||
|
||||
minimapCanvasInnerWidth = Math.floor(pixelRatio * minimapWidth);
|
||||
minimapCanvasOuterWidth = minimapCanvasInnerWidth / pixelRatio;
|
||||
minimapCanvasInnerWidth = Math.floor(minimapCanvasInnerWidth * minimapWidthMultiplier);
|
||||
if (minimapLayout.renderMinimap !== RenderMinimap.None && minimapLayout.minimapLeft === 0) {
|
||||
// the minimap is rendered to the left, so move everything to the right
|
||||
glyphMarginLeft += minimapLayout.minimapWidth;
|
||||
lineNumbersLeft += minimapLayout.minimapWidth;
|
||||
decorationsLeft += minimapLayout.minimapWidth;
|
||||
contentLeft += minimapLayout.minimapWidth;
|
||||
}
|
||||
const contentWidth = remainingWidth - minimapLayout.minimapWidth;
|
||||
|
||||
// (leaving 2px for the cursor to have space after the last character)
|
||||
const viewportColumn = Math.max(1, Math.floor((contentWidth - verticalScrollbarWidth - 2) / typicalHalfwidthCharacterWidth));
|
||||
|
||||
const verticalArrowSize = (verticalScrollbarHasArrows ? scrollbarArrowSize : 0);
|
||||
|
||||
if (isViewportWrapping) {
|
||||
// compute the actual wrappingColumn
|
||||
wrappingColumn = Math.max(1, viewportColumn);
|
||||
if (wordWrap === 'bounded') {
|
||||
wrappingColumn = Math.min(wrappingColumn, wordWrapColumn);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
width: outerWidth,
|
||||
height: outerHeight,
|
||||
@@ -1987,20 +2183,14 @@ export class EditorLayoutInfoComputer extends ComputedEditorOption<EditorOption.
|
||||
contentLeft: contentLeft,
|
||||
contentWidth: contentWidth,
|
||||
|
||||
renderMinimap: renderMinimap,
|
||||
minimapLeft: minimapLeft,
|
||||
minimapWidth: minimapWidth,
|
||||
minimapHeightIsEditorHeight: minimapHeightIsEditorHeight,
|
||||
minimapIsSampling: minimapIsSampling,
|
||||
minimapScale: minimapScale,
|
||||
minimapLineHeight: minimapLineHeight,
|
||||
minimapCanvasInnerWidth: minimapCanvasInnerWidth,
|
||||
minimapCanvasInnerHeight: minimapCanvasInnerHeight,
|
||||
minimapCanvasOuterWidth: minimapCanvasOuterWidth,
|
||||
minimapCanvasOuterHeight: minimapCanvasOuterHeight,
|
||||
minimap: minimapLayout,
|
||||
|
||||
viewportColumn: viewportColumn,
|
||||
|
||||
isWordWrapMinified: isWordWrapMinified,
|
||||
isViewportWrapping: isViewportWrapping,
|
||||
wrappingColumn: wrappingColumn,
|
||||
|
||||
verticalScrollbarWidth: verticalScrollbarWidth,
|
||||
horizontalScrollbarHeight: horizontalScrollbarHeight,
|
||||
|
||||
@@ -3231,67 +3421,17 @@ export interface EditorWrappingInfo {
|
||||
class EditorWrappingInfoComputer extends ComputedEditorOption<EditorOption.wrappingInfo, EditorWrappingInfo> {
|
||||
|
||||
constructor() {
|
||||
super(EditorOption.wrappingInfo, [EditorOption.wordWrap, EditorOption.wordWrapColumn, EditorOption.wordWrapMinified, EditorOption.layoutInfo, EditorOption.accessibilitySupport]);
|
||||
super(EditorOption.wrappingInfo, [EditorOption.layoutInfo]);
|
||||
}
|
||||
|
||||
public compute(env: IEnvironmentalOptions, options: IComputedEditorOptions, _: EditorWrappingInfo): EditorWrappingInfo {
|
||||
const wordWrap = options.get(EditorOption.wordWrap);
|
||||
const wordWrapColumn = options.get(EditorOption.wordWrapColumn);
|
||||
const wordWrapMinified = options.get(EditorOption.wordWrapMinified);
|
||||
const layoutInfo = options.get(EditorOption.layoutInfo);
|
||||
const accessibilitySupport = options.get(EditorOption.accessibilitySupport);
|
||||
|
||||
let bareWrappingInfo: { isWordWrapMinified: boolean; isViewportWrapping: boolean; wrappingColumn: number; } | null = null;
|
||||
{
|
||||
if (accessibilitySupport === AccessibilitySupport.Enabled) {
|
||||
// See https://github.com/Microsoft/vscode/issues/27766
|
||||
// Never enable wrapping when a screen reader is attached
|
||||
// because arrow down etc. will not move the cursor in the way
|
||||
// a screen reader expects.
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1
|
||||
};
|
||||
} else if (wordWrapMinified && env.isDominatedByLongLines) {
|
||||
// Force viewport width wrapping if model is dominated by long lines
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: true,
|
||||
isViewportWrapping: true,
|
||||
wrappingColumn: Math.max(1, layoutInfo.viewportColumn)
|
||||
};
|
||||
} else if (wordWrap === 'on') {
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: true,
|
||||
wrappingColumn: Math.max(1, layoutInfo.viewportColumn)
|
||||
};
|
||||
} else if (wordWrap === 'bounded') {
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: true,
|
||||
wrappingColumn: Math.min(Math.max(1, layoutInfo.viewportColumn), wordWrapColumn)
|
||||
};
|
||||
} else if (wordWrap === 'wordWrapColumn') {
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: wordWrapColumn
|
||||
};
|
||||
} else {
|
||||
bareWrappingInfo = {
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
isDominatedByLongLines: env.isDominatedByLongLines,
|
||||
isWordWrapMinified: bareWrappingInfo.isWordWrapMinified,
|
||||
isViewportWrapping: bareWrappingInfo.isViewportWrapping,
|
||||
wrappingColumn: bareWrappingInfo.wrappingColumn,
|
||||
isWordWrapMinified: layoutInfo.isWordWrapMinified,
|
||||
isViewportWrapping: layoutInfo.isViewportWrapping,
|
||||
wrappingColumn: layoutInfo.wrappingColumn,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,7 +701,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
}
|
||||
|
||||
const editorWidth = layoutInfo.width;
|
||||
const minimapWidth = layoutInfo.minimapWidth;
|
||||
const minimapWidth = layoutInfo.minimap.minimapWidth;
|
||||
let collapsedFindWidget = false;
|
||||
let reducedFindWidget = false;
|
||||
let narrowFindWidget = false;
|
||||
@@ -1218,7 +1218,7 @@ export class FindWidget extends Widget implements IOverlayWidget, IHorizontalSas
|
||||
// 1. never resized before, double click should maximizes it
|
||||
// 2. users resized it already but its width is the same as default
|
||||
const layoutInfo = this._codeEditor.getLayoutInfo();
|
||||
width = layoutInfo.width - 28 - layoutInfo.minimapWidth - 15;
|
||||
width = layoutInfo.width - 28 - layoutInfo.minimap.minimapWidth - 15;
|
||||
this._resized = true;
|
||||
} else {
|
||||
/**
|
||||
|
||||
@@ -254,13 +254,13 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
}
|
||||
|
||||
private _getWidth(info: EditorLayoutInfo): number {
|
||||
return info.width - info.minimapWidth - info.verticalScrollbarWidth;
|
||||
return info.width - info.minimap.minimapWidth - info.verticalScrollbarWidth;
|
||||
}
|
||||
|
||||
private _getLeft(info: EditorLayoutInfo): number {
|
||||
// If minimap is to the left, we move beyond it
|
||||
if (info.minimapWidth > 0 && info.minimapLeft === 0) {
|
||||
return info.minimapWidth;
|
||||
if (info.minimap.minimapWidth > 0 && info.minimap.minimapLeft === 0) {
|
||||
return info.minimap.minimapWidth;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -526,6 +526,6 @@ export abstract class ZoneWidget implements IHorizontalSashLayoutProvider {
|
||||
|
||||
getHorizontalSashWidth() {
|
||||
const layoutInfo = this.editor.getLayoutInfo();
|
||||
return layoutInfo.width - layoutInfo.minimapWidth;
|
||||
return layoutInfo.width - layoutInfo.minimap.minimapWidth;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,16 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
};
|
||||
options._write(EditorOption.lineNumbers, lineNumbersOptions);
|
||||
|
||||
options._write(EditorOption.wordWrap, 'off');
|
||||
options._write(EditorOption.wordWrapColumn, 80);
|
||||
options._write(EditorOption.wordWrapMinified, true);
|
||||
options._write(EditorOption.accessibilitySupport, 'auto');
|
||||
|
||||
const actual = EditorLayoutInfoComputer.computeLayout(options, {
|
||||
memory: null,
|
||||
outerWidth: input.outerWidth,
|
||||
outerHeight: input.outerHeight,
|
||||
isDominatedByLongLines: false,
|
||||
lineHeight: input.lineHeight,
|
||||
viewLineCount: input.maxLineNumber || Math.pow(10, input.lineNumbersDigitCount) - 1,
|
||||
lineNumbersDigitCount: input.lineNumbersDigitCount,
|
||||
@@ -126,6 +133,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -137,7 +145,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 98,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -188,6 +201,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 990,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -199,7 +213,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 97,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 11,
|
||||
horizontalScrollbarHeight: 12,
|
||||
@@ -250,6 +269,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -261,7 +281,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -312,6 +337,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -323,7 +349,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -374,6 +405,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 890,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -385,7 +417,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 88,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -436,6 +473,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -447,7 +485,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -498,6 +541,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 60,
|
||||
contentWidth: 840,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -509,7 +553,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -560,6 +609,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 70,
|
||||
contentWidth: 830,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -571,7 +621,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 82,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -622,6 +677,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -633,7 +689,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 171,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -684,6 +745,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 40,
|
||||
contentWidth: 860,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.None,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 0,
|
||||
@@ -695,7 +757,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 900,
|
||||
minimapCanvasOuterWidth: 0,
|
||||
minimapCanvasOuterHeight: 900,
|
||||
},
|
||||
|
||||
viewportColumn: 169,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -746,6 +813,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
@@ -757,7 +825,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 800,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -808,6 +881,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
@@ -819,7 +893,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -870,6 +949,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
@@ -881,7 +961,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -932,6 +1017,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 65,
|
||||
contentWidth: 935,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 0,
|
||||
minimapWidth: 55,
|
||||
@@ -943,7 +1029,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 3200,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -996,6 +1087,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
@@ -1007,7 +1099,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 1560,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1060,6 +1157,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
@@ -1071,7 +1169,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1124,6 +1227,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 893,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 903,
|
||||
minimapWidth: 97,
|
||||
@@ -1135,7 +1239,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 97,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 89,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1188,6 +1297,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 10,
|
||||
contentWidth: 935,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 945,
|
||||
minimapWidth: 55,
|
||||
@@ -1199,7 +1309,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 1600,
|
||||
minimapCanvasOuterWidth: 55,
|
||||
minimapCanvasOuterHeight: 800,
|
||||
},
|
||||
|
||||
viewportColumn: 93,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 0,
|
||||
horizontalScrollbarHeight: 0,
|
||||
@@ -1250,6 +1365,7 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
contentLeft: 92,
|
||||
contentWidth: 1018,
|
||||
|
||||
minimap: {
|
||||
renderMinimap: RenderMinimap.Text,
|
||||
minimapLeft: 1096,
|
||||
minimapWidth: 91,
|
||||
@@ -1261,7 +1377,12 @@ suite('Editor ViewLayout - EditorLayoutProvider', () => {
|
||||
minimapCanvasInnerHeight: 844,
|
||||
minimapCanvasOuterWidth: 91,
|
||||
minimapCanvasOuterHeight: 422,
|
||||
},
|
||||
|
||||
viewportColumn: 83,
|
||||
isWordWrapMinified: false,
|
||||
isViewportWrapping: false,
|
||||
wrappingColumn: -1,
|
||||
|
||||
verticalScrollbarWidth: 14,
|
||||
horizontalScrollbarHeight: 10,
|
||||
|
||||
Vendored
+22
-18
@@ -3404,29 +3404,16 @@ declare namespace monaco.editor {
|
||||
*/
|
||||
readonly contentWidth: number;
|
||||
/**
|
||||
* The position for the minimap
|
||||
* Layout information for the minimap
|
||||
*/
|
||||
readonly minimapLeft: number;
|
||||
/**
|
||||
* The width of the minimap
|
||||
*/
|
||||
readonly minimapWidth: number;
|
||||
readonly minimapHeightIsEditorHeight: boolean;
|
||||
readonly minimapIsSampling: boolean;
|
||||
readonly minimapScale: number;
|
||||
readonly minimapLineHeight: number;
|
||||
readonly minimapCanvasInnerWidth: number;
|
||||
readonly minimapCanvasInnerHeight: number;
|
||||
readonly minimapCanvasOuterWidth: number;
|
||||
readonly minimapCanvasOuterHeight: number;
|
||||
/**
|
||||
* Minimap render type
|
||||
*/
|
||||
readonly renderMinimap: RenderMinimap;
|
||||
readonly minimap: EditorMinimapLayoutInfo;
|
||||
/**
|
||||
* The number of columns (of typical characters) fitting on a viewport line.
|
||||
*/
|
||||
readonly viewportColumn: number;
|
||||
readonly isWordWrapMinified: boolean;
|
||||
readonly isViewportWrapping: boolean;
|
||||
readonly wrappingColumn: number;
|
||||
/**
|
||||
* The width of the vertical scrollbar.
|
||||
*/
|
||||
@@ -3441,6 +3428,23 @@ declare namespace monaco.editor {
|
||||
readonly overviewRuler: OverviewRulerPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal layout details of the editor.
|
||||
*/
|
||||
export interface EditorMinimapLayoutInfo {
|
||||
readonly renderMinimap: RenderMinimap;
|
||||
readonly minimapLeft: number;
|
||||
readonly minimapWidth: number;
|
||||
readonly minimapHeightIsEditorHeight: boolean;
|
||||
readonly minimapIsSampling: boolean;
|
||||
readonly minimapScale: number;
|
||||
readonly minimapLineHeight: number;
|
||||
readonly minimapCanvasInnerWidth: number;
|
||||
readonly minimapCanvasInnerHeight: number;
|
||||
readonly minimapCanvasOuterWidth: number;
|
||||
readonly minimapCanvasOuterHeight: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration options for editor lightbulb
|
||||
*/
|
||||
|
||||
@@ -324,7 +324,8 @@ export class ConfigurationModelParser {
|
||||
result[key] = this.filterByScope(properties[key], configurationProperties, false, scopes);
|
||||
} else {
|
||||
const scope = this.getScope(key, configurationProperties);
|
||||
if (scopes.indexOf(scope) !== -1) {
|
||||
// Load unregistered configurations always.
|
||||
if (scope === undefined || scopes.indexOf(scope) !== -1) {
|
||||
result[key] = properties[key];
|
||||
}
|
||||
}
|
||||
@@ -332,9 +333,9 @@ export class ConfigurationModelParser {
|
||||
return result;
|
||||
}
|
||||
|
||||
private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope {
|
||||
private getScope(key: string, configurationProperties: { [qualifiedKey: string]: IConfigurationPropertySchema }): ConfigurationScope | undefined {
|
||||
const propertySchema = configurationProperties[key];
|
||||
return propertySchema && typeof propertySchema.scope !== 'undefined' ? propertySchema.scope : ConfigurationScope.WINDOW;
|
||||
return propertySchema ? typeof propertySchema.scope !== 'undefined' ? propertySchema.scope : ConfigurationScope.WINDOW : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import * as osLib from 'os';
|
||||
import { virtualMachineHint } from 'vs/base/node/id';
|
||||
import { IMachineInfo, WorkspaceStats, WorkspaceStatItem, PerformanceInfo, SystemInfo, IRemoteDiagnosticInfo, IRemoteDiagnosticError, isRemoteDiagnosticError, IWorkspaceInformation } from 'vs/platform/diagnostics/common/diagnostics';
|
||||
import { readdir, stat, exists, readFile } from 'fs';
|
||||
import { readdir, exists, readFile } from 'fs';
|
||||
import { join, basename } from 'vs/base/common/path';
|
||||
import { parse, ParseError, getNodeType } from 'vs/base/common/json';
|
||||
import { listProcesses } from 'vs/base/node/ps';
|
||||
@@ -17,6 +17,7 @@ import { ProcessItem } from 'vs/base/common/processes';
|
||||
import { IMainProcessInfo } from 'vs/platform/launch/common/launch';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { Iterable } from 'vs/base/common/iterator';
|
||||
|
||||
export const ID = 'diagnosticsService';
|
||||
export const IDiagnosticsService = createDecorator<IDiagnosticsService>(ID);
|
||||
@@ -42,24 +43,31 @@ export interface ProcessInfo {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export function collectWorkspaceStats(folder: string, filter: string[]): Promise<WorkspaceStats> {
|
||||
const configFilePatterns = [
|
||||
{ 'tag': 'grunt.js', 'pattern': /^gruntfile\.js$/i },
|
||||
{ 'tag': 'gulp.js', 'pattern': /^gulpfile\.js$/i },
|
||||
{ 'tag': 'tsconfig.json', 'pattern': /^tsconfig\.json$/i },
|
||||
{ 'tag': 'package.json', 'pattern': /^package\.json$/i },
|
||||
{ 'tag': 'jsconfig.json', 'pattern': /^jsconfig\.json$/i },
|
||||
{ 'tag': 'tslint.json', 'pattern': /^tslint\.json$/i },
|
||||
{ 'tag': 'eslint.json', 'pattern': /^eslint\.json$/i },
|
||||
{ 'tag': 'tasks.json', 'pattern': /^tasks\.json$/i },
|
||||
{ 'tag': 'launch.json', 'pattern': /^launch\.json$/i },
|
||||
{ 'tag': 'settings.json', 'pattern': /^settings\.json$/i },
|
||||
{ 'tag': 'webpack.config.js', 'pattern': /^webpack\.config\.js$/i },
|
||||
{ 'tag': 'project.json', 'pattern': /^project\.json$/i },
|
||||
{ 'tag': 'makefile', 'pattern': /^makefile$/i },
|
||||
{ 'tag': 'sln', 'pattern': /^.+\.sln$/i },
|
||||
{ 'tag': 'csproj', 'pattern': /^.+\.csproj$/i },
|
||||
{ 'tag': 'cmake', 'pattern': /^.+\.cmake$/i }
|
||||
interface ConfigFilePatterns {
|
||||
tag: string;
|
||||
filePattern: RegExp;
|
||||
relativePathPattern?: RegExp;
|
||||
}
|
||||
|
||||
export async function collectWorkspaceStats(folder: string, filter: string[]): Promise<WorkspaceStats> {
|
||||
const configFilePatterns: ConfigFilePatterns[] = [
|
||||
{ tag: 'grunt.js', filePattern: /^gruntfile\.js$/i },
|
||||
{ tag: 'gulp.js', filePattern: /^gulpfile\.js$/i },
|
||||
{ tag: 'tsconfig.json', filePattern: /^tsconfig\.json$/i },
|
||||
{ tag: 'package.json', filePattern: /^package\.json$/i },
|
||||
{ tag: 'jsconfig.json', filePattern: /^jsconfig\.json$/i },
|
||||
{ tag: 'tslint.json', filePattern: /^tslint\.json$/i },
|
||||
{ tag: 'eslint.json', filePattern: /^eslint\.json$/i },
|
||||
{ tag: 'tasks.json', filePattern: /^tasks\.json$/i },
|
||||
{ tag: 'launch.json', filePattern: /^launch\.json$/i },
|
||||
{ tag: 'settings.json', filePattern: /^settings\.json$/i },
|
||||
{ tag: 'webpack.config.js', filePattern: /^webpack\.config\.js$/i },
|
||||
{ tag: 'project.json', filePattern: /^project\.json$/i },
|
||||
{ tag: 'makefile', filePattern: /^makefile$/i },
|
||||
{ tag: 'sln', filePattern: /^.+\.sln$/i },
|
||||
{ tag: 'csproj', filePattern: /^.+\.csproj$/i },
|
||||
{ tag: 'cmake', filePattern: /^.+\.cmake$/i },
|
||||
{ tag: 'github-actions', filePattern: /^.+\.yml$/i, relativePathPattern: /^\.github(?:\/|\\)workflows$/i }
|
||||
];
|
||||
|
||||
const fileTypes = new Map<string, number>();
|
||||
@@ -67,23 +75,28 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Promise
|
||||
|
||||
const MAX_FILES = 20000;
|
||||
|
||||
function walk(dir: string, filter: string[], token: { count: number, maxReached: boolean }, done: (allFiles: string[]) => void): void {
|
||||
let results: string[] = [];
|
||||
readdir(dir, async (err, files) => {
|
||||
function collect(root: string, dir: string, filter: string[], token: { count: number, maxReached: boolean }): Promise<void> {
|
||||
const relativePath = dir.substring(root.length + 1);
|
||||
|
||||
return new Promise(resolve => {
|
||||
readdir(dir, { withFileTypes: true }, async (err, files) => {
|
||||
// Ignore folders that can't be read
|
||||
if (err) {
|
||||
return done(results);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
if (token.count > MAX_FILES) {
|
||||
token.count += files.length;
|
||||
token.maxReached = true;
|
||||
return done(results);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let pending = files.length;
|
||||
if (pending === 0) {
|
||||
return done(results);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
let filesToRead = files;
|
||||
@@ -96,94 +109,57 @@ export function collectWorkspaceStats(folder: string, filter: string[]): Promise
|
||||
token.count += files.length;
|
||||
|
||||
for (const file of filesToRead) {
|
||||
stat(join(dir, file), (err, stats) => {
|
||||
// Ignore files that can't be read
|
||||
if (err) {
|
||||
if (--pending === 0) {
|
||||
return done(results);
|
||||
if (file.isDirectory()) {
|
||||
if (!filter.includes(file.name)) {
|
||||
await collect(root, join(dir, file.name), filter, token);
|
||||
}
|
||||
} else {
|
||||
if (stats.isDirectory()) {
|
||||
if (filter.indexOf(file) === -1) {
|
||||
walk(join(dir, file), filter, token, (res: string[]) => {
|
||||
results = results.concat(res);
|
||||
|
||||
if (--pending === 0) {
|
||||
return done(results);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (--pending === 0) {
|
||||
done(results);
|
||||
}
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
results.push(file);
|
||||
const index = file.name.lastIndexOf('.');
|
||||
if (index >= 0) {
|
||||
const fileType = file.name.substring(index + 1);
|
||||
if (fileType) {
|
||||
fileTypes.set(fileType, (fileTypes.get(fileType) ?? 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
for (const configFile of configFilePatterns) {
|
||||
if (configFile.relativePathPattern?.test(relativePath) !== false && configFile.filePattern.test(file.name)) {
|
||||
configFiles.set(configFile.tag, (configFiles.get(configFile.tag) ?? 0) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (--pending === 0) {
|
||||
done(results);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const addFileType = (fileType: string) => {
|
||||
if (fileTypes.has(fileType)) {
|
||||
fileTypes.set(fileType, fileTypes.get(fileType)! + 1);
|
||||
}
|
||||
else {
|
||||
fileTypes.set(fileType, 1);
|
||||
}
|
||||
};
|
||||
|
||||
const addConfigFiles = (fileName: string) => {
|
||||
for (const each of configFilePatterns) {
|
||||
if (each.pattern.test(fileName)) {
|
||||
if (configFiles.has(each.tag)) {
|
||||
configFiles.set(each.tag, configFiles.get(each.tag)! + 1);
|
||||
} else {
|
||||
configFiles.set(each.tag, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const acceptFile = (name: string) => {
|
||||
if (name.lastIndexOf('.') >= 0) {
|
||||
const suffix: string | undefined = name.split('.').pop();
|
||||
if (suffix) {
|
||||
addFileType(suffix);
|
||||
}
|
||||
}
|
||||
addConfigFiles(name);
|
||||
};
|
||||
|
||||
const token: { count: number, maxReached: boolean } = { count: 0, maxReached: false };
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
walk(folder, filter, token, async (files) => {
|
||||
files.forEach(acceptFile);
|
||||
|
||||
await collect(folder, folder, filter, token);
|
||||
const launchConfigs = await collectLaunchConfigs(folder);
|
||||
|
||||
resolve({
|
||||
return {
|
||||
configFiles: asSortedItems(configFiles),
|
||||
fileTypes: asSortedItems(fileTypes),
|
||||
fileCount: token.count,
|
||||
maxFilesReached: token.maxReached,
|
||||
launchConfigFiles: launchConfigs
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function asSortedItems(map: Map<string, number>): WorkspaceStatItem[] {
|
||||
const a: WorkspaceStatItem[] = [];
|
||||
map.forEach((value, index) => a.push({ name: index, count: value }));
|
||||
return a.sort((a, b) => b.count - a.count);
|
||||
function asSortedItems(items: Map<string, number>): WorkspaceStatItem[] {
|
||||
return [
|
||||
...Iterable.map(items.entries(), ([name, count]) => ({ name: name, count: count }))
|
||||
].sort((a, b) => b.count - a.count);
|
||||
}
|
||||
|
||||
export function getMachineInfo(): IMachineInfo {
|
||||
@@ -540,11 +516,15 @@ export class DiagnosticsService implements IDiagnosticsService {
|
||||
}
|
||||
|
||||
public async reportWorkspaceStats(workspace: IWorkspaceInformation): Promise<void> {
|
||||
workspace.folders.forEach(folder => {
|
||||
const folderUri = URI.revive(folder.uri);
|
||||
if (folderUri.scheme === 'file') {
|
||||
for (const { uri } of workspace.folders) {
|
||||
const folderUri = URI.revive(uri);
|
||||
if (folderUri.scheme !== 'file') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const folder = folderUri.fsPath;
|
||||
collectWorkspaceStats(folder, ['node_modules', '.git']).then(stats => {
|
||||
try {
|
||||
const stats = await collectWorkspaceStats(folder, ['node_modules', '.git']);
|
||||
type WorkspaceStatsClassification = {
|
||||
'workspace.id': { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
rendererSessionId: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
|
||||
@@ -588,10 +568,9 @@ export class DiagnosticsService implements IDiagnosticsService {
|
||||
count: e.count
|
||||
});
|
||||
});
|
||||
}).catch(_ => {
|
||||
} catch {
|
||||
// Report nothing if collecting metadata fails.
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +170,12 @@ export interface IEditorOptions {
|
||||
*/
|
||||
readonly pinned?: boolean;
|
||||
|
||||
/**
|
||||
* An editor that is sticky moves to the beginning of the editors list within the group and will remain
|
||||
* there unless explicitly closed. Operations such as "Close All" will not close sticky editors.
|
||||
*/
|
||||
readonly sticky?: boolean;
|
||||
|
||||
/**
|
||||
* The index in the document stack where to insert the editor into when opening.
|
||||
*/
|
||||
|
||||
@@ -62,6 +62,7 @@ export interface ParsedArgs {
|
||||
'install-source'?: string;
|
||||
'disable-updates'?: boolean;
|
||||
'disable-crash-reporter'?: boolean;
|
||||
'crash-reporter-directory'?: string;
|
||||
'skip-add-to-recently-opened'?: boolean;
|
||||
'max-memory'?: string;
|
||||
'file-write'?: boolean;
|
||||
@@ -186,6 +187,7 @@ export const OPTIONS: OptionDescriptions<Required<ParsedArgs>> = {
|
||||
'disable-telemetry': { type: 'boolean' },
|
||||
'disable-updates': { type: 'boolean' },
|
||||
'disable-crash-reporter': { type: 'boolean' },
|
||||
'crash-reporter-directory': { type: 'string' },
|
||||
'disable-user-env-probe': { type: 'boolean' },
|
||||
'skip-add-to-recently-opened': { type: 'boolean' },
|
||||
'unity-launch': { type: 'boolean' },
|
||||
|
||||
@@ -253,6 +253,7 @@ export class EnvironmentService implements INativeEnvironmentService {
|
||||
|
||||
get disableUpdates(): boolean { return !!this._args['disable-updates']; }
|
||||
get disableCrashReporter(): boolean { return !!this._args['disable-crash-reporter']; }
|
||||
get crashReporterDirectory(): string | undefined { return this._args['crash-reporter-directory']; }
|
||||
|
||||
get driverHandle(): string | undefined { return this._args['driver']; }
|
||||
get driverVerbose(): boolean { return !!this._args['driver-verbose']; }
|
||||
|
||||
Vendored
+113
@@ -5452,6 +5452,12 @@ declare module 'vscode' {
|
||||
*/
|
||||
readonly extensionPath: string;
|
||||
|
||||
/**
|
||||
* Gets the extension's environment variable collection for this workspace, enabling changes
|
||||
* to be applied to terminal environment variables.
|
||||
*/
|
||||
readonly environmentVariableCollection: EnvironmentVariableCollection;
|
||||
|
||||
/**
|
||||
* Get the absolute path of a resource contained in the extension.
|
||||
*
|
||||
@@ -8257,6 +8263,113 @@ declare module 'vscode' {
|
||||
readonly code: number | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* A type of mutation that can be applied to an environment variable.
|
||||
*/
|
||||
export enum EnvironmentVariableMutatorType {
|
||||
/**
|
||||
* Replace the variable's existing value.
|
||||
*/
|
||||
Replace = 1,
|
||||
/**
|
||||
* Append to the end of the variable's existing value.
|
||||
*/
|
||||
Append = 2,
|
||||
/**
|
||||
* Prepend to the start of the variable's existing value.
|
||||
*/
|
||||
Prepend = 3
|
||||
}
|
||||
|
||||
/**
|
||||
* A type of mutation and its value to be applied to an environment variable.
|
||||
*/
|
||||
export interface EnvironmentVariableMutator {
|
||||
/**
|
||||
* The type of mutation that will occur to the variable.
|
||||
*/
|
||||
readonly type: EnvironmentVariableMutatorType;
|
||||
|
||||
/**
|
||||
* The value to use for the variable.
|
||||
*/
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of mutations that an extension can apply to a process environment.
|
||||
*/
|
||||
export interface EnvironmentVariableCollection {
|
||||
/**
|
||||
* Whether the collection should be cached for the workspace and applied to the terminal
|
||||
* across window reloads. When true the collection will be active immediately such when the
|
||||
* window reloads. Additionally, this API will return the cached version if it exists. The
|
||||
* collection will be invalidated when the extension is uninstalled or when the collection
|
||||
* is cleared. Defaults to true.
|
||||
*/
|
||||
persistent: boolean;
|
||||
|
||||
/**
|
||||
* Replace an environment variable with a value.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*
|
||||
* @param variable The variable to replace.
|
||||
* @param value The value to replace the variable with.
|
||||
*/
|
||||
replace(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Append a value to an environment variable.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*
|
||||
* @param variable The variable to append to.
|
||||
* @param value The value to append to the variable.
|
||||
*/
|
||||
append(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Prepend a value to an environment variable.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*
|
||||
* @param variable The variable to prepend.
|
||||
* @param value The value to prepend to the variable.
|
||||
*/
|
||||
prepend(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Gets the mutator that this collection applies to a variable, if any.
|
||||
*
|
||||
* @param variable The variable to get the mutator for.
|
||||
*/
|
||||
get(variable: string): EnvironmentVariableMutator | undefined;
|
||||
|
||||
/**
|
||||
* Iterate over each mutator in this collection.
|
||||
*
|
||||
* @param callback Function to execute for each entry.
|
||||
* @param thisArg The `this` context used when invoking the handler function.
|
||||
*/
|
||||
forEach(callback: (variable: string, mutator: EnvironmentVariableMutator, collection: EnvironmentVariableCollection) => any, thisArg?: any): void;
|
||||
|
||||
/**
|
||||
* Deletes this collection's mutator for a variable.
|
||||
*
|
||||
* @param variable The variable to delete the mutator for.
|
||||
*/
|
||||
delete(variable: string): void;
|
||||
|
||||
/**
|
||||
* Clears all mutators from this collection.
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
/**
|
||||
* A location in the editor at which progress information can be shown. It depends on the
|
||||
* location how progress is visually represented.
|
||||
|
||||
Vendored
+37
-108
@@ -930,103 +930,6 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Contribute to terminal environment https://github.com/microsoft/vscode/issues/46696
|
||||
|
||||
export enum EnvironmentVariableMutatorType {
|
||||
/**
|
||||
* Replace the variable's existing value.
|
||||
*/
|
||||
Replace = 1,
|
||||
/**
|
||||
* Append to the end of the variable's existing value.
|
||||
*/
|
||||
Append = 2,
|
||||
/**
|
||||
* Prepend to the start of the variable's existing value.
|
||||
*/
|
||||
Prepend = 3
|
||||
}
|
||||
|
||||
export interface EnvironmentVariableMutator {
|
||||
/**
|
||||
* The type of mutation that will occur to the variable.
|
||||
*/
|
||||
readonly type: EnvironmentVariableMutatorType;
|
||||
|
||||
/**
|
||||
* The value to use for the variable.
|
||||
*/
|
||||
readonly value: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of mutations that an extension can apply to a process environment.
|
||||
*/
|
||||
export interface EnvironmentVariableCollection {
|
||||
/**
|
||||
* Whether the collection should be cached for the workspace and applied to the terminal
|
||||
* across window reloads. When true the collection will be active immediately such when the
|
||||
* window reloads. Additionally, this API will return the cached version if it exists. The
|
||||
* collection will be invalidated when the extension is uninstalled or when the collection
|
||||
* is cleared. Defaults to true.
|
||||
*/
|
||||
persistent: boolean;
|
||||
|
||||
/**
|
||||
* Replace an environment variable with a value.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*/
|
||||
replace(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Append a value to an environment variable.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*/
|
||||
append(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Prepend a value to an environment variable.
|
||||
*
|
||||
* Note that an extension can only make a single change to any one variable, so this will
|
||||
* overwrite any previous calls to replace, append or prepend.
|
||||
*/
|
||||
prepend(variable: string, value: string): void;
|
||||
|
||||
/**
|
||||
* Gets the mutator that this collection applies to a variable, if any.
|
||||
*/
|
||||
get(variable: string): EnvironmentVariableMutator | undefined;
|
||||
|
||||
/**
|
||||
* Iterate over each mutator in this collection.
|
||||
*/
|
||||
forEach(callback: (variable: string, mutator: EnvironmentVariableMutator, collection: EnvironmentVariableCollection) => any, thisArg?: any): void;
|
||||
|
||||
/**
|
||||
* Deletes this collection's mutator for a variable.
|
||||
*/
|
||||
delete(variable: string): void;
|
||||
|
||||
/**
|
||||
* Clears all mutators from this collection.
|
||||
*/
|
||||
clear(): void;
|
||||
}
|
||||
|
||||
export interface ExtensionContext {
|
||||
/**
|
||||
* Gets the extension's environment variable collection for this workspace, enabling changes
|
||||
* to be applied to terminal environment variables.
|
||||
*/
|
||||
readonly environmentVariableCollection: EnvironmentVariableCollection;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region @jrieken -> exclusive document filters
|
||||
|
||||
export interface DocumentFilter {
|
||||
@@ -1737,12 +1640,6 @@ declare module 'vscode' {
|
||||
edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable<boolean>;
|
||||
}
|
||||
|
||||
export interface NotebookProvider {
|
||||
resolveNotebook(editor: NotebookEditor): Promise<void>;
|
||||
executeCell(document: NotebookDocument, cell: NotebookCell | undefined, token: CancellationToken): Promise<void>;
|
||||
save(document: NotebookDocument): Promise<boolean>;
|
||||
}
|
||||
|
||||
export interface NotebookOutputSelector {
|
||||
type: string;
|
||||
subTypes?: string[];
|
||||
@@ -1805,11 +1702,6 @@ declare module 'vscode' {
|
||||
provider: NotebookContentProvider
|
||||
): Disposable;
|
||||
|
||||
export function registerNotebookProvider(
|
||||
notebookType: string,
|
||||
provider: NotebookProvider
|
||||
): Disposable;
|
||||
|
||||
export function registerNotebookOutputRenderer(
|
||||
type: string,
|
||||
outputSelector: NotebookOutputSelector,
|
||||
@@ -1839,6 +1731,43 @@ declare module 'vscode' {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region @connor4312 extension mode: https://github.com/microsoft/vscode/issues/95926
|
||||
|
||||
/**
|
||||
* The ExtensionMode is provided on the `ExtensionContext` and indicates the
|
||||
* mode the specific extension is running in.
|
||||
*/
|
||||
export enum ExtensionMode {
|
||||
/**
|
||||
* The extension is installed normally (for example, from the marketplace
|
||||
* or VSIX) in VS Code.
|
||||
*/
|
||||
Release = 1,
|
||||
|
||||
/**
|
||||
* The extension is running from an `--extensionDevelopmentPath` provided
|
||||
* when launching VS Code.
|
||||
*/
|
||||
Development = 2,
|
||||
|
||||
/**
|
||||
* The extension is running from an `--extensionDevelopmentPath` and
|
||||
* the extension host is running unit tests.
|
||||
*/
|
||||
Test = 3,
|
||||
}
|
||||
|
||||
export interface ExtensionContext {
|
||||
/**
|
||||
* The mode the extension is running in. This is specific to the current
|
||||
* extension. One extension may be in `ExtensionMode.Development` while
|
||||
* other extensions in the host run in `ExtensionMode.Release`.
|
||||
*/
|
||||
readonly extensionMode: ExtensionMode;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region https://github.com/microsoft/vscode/issues/39441
|
||||
|
||||
export interface CompletionItem {
|
||||
|
||||
@@ -8,7 +8,7 @@ import { MainContext, MainThreadNotebookShape, NotebookExtensionDescription, IEx
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { INotebookService, IMainNotebookController } from 'vs/workbench/contrib/notebook/common/notebookService';
|
||||
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, CellKind, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookTextModel, INotebookMimeTypeSelector, NOTEBOOK_DISPLAY_ORDER, NotebookCellOutputsSplice, NotebookDocumentMetadata, NotebookCellMetadata, ICellEditOperation, ACCESSIBLE_NOTEBOOK_DISPLAY_ORDER, CellEditType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { NotebookTextModel } from 'vs/workbench/contrib/notebook/common/model/notebookTextModel';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -84,7 +84,9 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
|
||||
registerListeners() {
|
||||
this._register(this._notebookService.onDidChangeActiveEditor(e => {
|
||||
this._proxy.$updateActiveEditor(e.viewType, e.uri);
|
||||
this._proxy.$acceptDocumentAndEditorsDelta({
|
||||
newActiveEditor: e.uri
|
||||
});
|
||||
}));
|
||||
|
||||
const updateOrder = () => {
|
||||
@@ -129,16 +131,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
return;
|
||||
}
|
||||
|
||||
async $createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void> {
|
||||
let controller = this._notebookProviders.get(viewType);
|
||||
|
||||
if (controller) {
|
||||
controller.createNotebookDocument(handle, viewType, resource);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
async $updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void> {
|
||||
let controller = this._notebookProviders.get(viewType);
|
||||
|
||||
@@ -163,11 +155,6 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
}
|
||||
}
|
||||
|
||||
async resolveNotebook(viewType: string, uri: URI): Promise<number | undefined> {
|
||||
let handle = await this._proxy.$resolveNotebook(viewType, uri);
|
||||
return handle;
|
||||
}
|
||||
|
||||
async $spliceNotebookCellOutputs(viewType: string, resource: UriComponents, cellHandle: number, splices: NotebookCellOutputsSplice[], renderers: number[]): Promise<void> {
|
||||
let controller = this._notebookProviders.get(viewType);
|
||||
controller?.spliceNotebookCellOutputs(resource, cellHandle, splices, renderers);
|
||||
@@ -195,6 +182,7 @@ export class MainThreadNotebooks extends Disposable implements MainThreadNoteboo
|
||||
|
||||
export class MainThreadNotebookController implements IMainNotebookController {
|
||||
private _mapping: Map<string, MainThreadNotebookDocument> = new Map();
|
||||
static documentHandle: number = 0;
|
||||
|
||||
constructor(
|
||||
private readonly _proxy: ExtHostNotebookShape,
|
||||
@@ -203,26 +191,44 @@ export class MainThreadNotebookController implements IMainNotebookController {
|
||||
) {
|
||||
}
|
||||
|
||||
async resolveNotebook(viewType: string, uri: URI): Promise<NotebookTextModel | undefined> {
|
||||
// TODO: resolve notebook should wait for all notebook document destory operations to finish.
|
||||
async createNotebook(viewType: string, uri: URI, forBackup: boolean, forceReload: boolean): Promise<NotebookTextModel | undefined> {
|
||||
let mainthreadNotebook = this._mapping.get(URI.from(uri).toString());
|
||||
|
||||
if (mainthreadNotebook) {
|
||||
if (forceReload) {
|
||||
const data = await this._proxy.$resolveNotebookData(viewType, uri);
|
||||
if (!data) {
|
||||
return undefined; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
|
||||
mainthreadNotebook.textModel.languages = data.languages;
|
||||
mainthreadNotebook.textModel.metadata = data.metadata;
|
||||
mainthreadNotebook.textModel.applyEdit(mainthreadNotebook.textModel.versionId, [
|
||||
{ editType: CellEditType.Delete, count: mainthreadNotebook.textModel.cells.length, index: 0 },
|
||||
{ editType: CellEditType.Insert, index: 0, cells: data.cells }
|
||||
]);
|
||||
}
|
||||
return mainthreadNotebook.textModel;
|
||||
}
|
||||
|
||||
let notebookHandle = await this._mainThreadNotebook.resolveNotebook(viewType, uri);
|
||||
if (notebookHandle !== undefined) {
|
||||
mainthreadNotebook = this._mapping.get(URI.from(uri).toString());
|
||||
if (mainthreadNotebook && mainthreadNotebook.textModel.cells.length === 0) {
|
||||
// it's empty, we should create an empty template one
|
||||
const mainCell = mainthreadNotebook.textModel.createCellTextModel([''], mainthreadNotebook.textModel.languages.length ? mainthreadNotebook.textModel.languages[0] : '', CellKind.Code, [], undefined);
|
||||
mainthreadNotebook.textModel.insertTemplateCell(mainCell);
|
||||
}
|
||||
return mainthreadNotebook?.textModel;
|
||||
let document = new MainThreadNotebookDocument(this._proxy, MainThreadNotebookController.documentHandle++, viewType, uri);
|
||||
await this.createNotebookDocument(document);
|
||||
|
||||
if (forBackup) {
|
||||
return document.textModel;
|
||||
}
|
||||
|
||||
return undefined;
|
||||
// open notebook document
|
||||
const data = await this._proxy.$resolveNotebookData(viewType, uri);
|
||||
if (!data) {
|
||||
return undefined; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
|
||||
document.textModel.languages = data.languages;
|
||||
document.textModel.metadata = data.metadata;
|
||||
document.textModel.initialize(data!.cells);
|
||||
|
||||
return document.textModel;
|
||||
}
|
||||
|
||||
async tryApplyEdits(resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean> {
|
||||
@@ -250,12 +256,32 @@ export class MainThreadNotebookController implements IMainNotebookController {
|
||||
this._proxy.$onDidReceiveMessage(uri, message);
|
||||
}
|
||||
|
||||
// Methods for ExtHost
|
||||
async createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void> {
|
||||
let document = new MainThreadNotebookDocument(this._proxy, handle, viewType, URI.revive(resource));
|
||||
this._mapping.set(URI.revive(resource).toString(), document);
|
||||
async createNotebookDocument(document: MainThreadNotebookDocument): Promise<void> {
|
||||
this._mapping.set(document.uri.toString(), document);
|
||||
|
||||
await this._proxy.$acceptDocumentAndEditorsDelta({
|
||||
addedDocuments: [{
|
||||
viewType: document.viewType,
|
||||
handle: document.handle,
|
||||
uri: document.uri
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
async removeNotebookDocument(notebook: INotebookTextModel): Promise<void> {
|
||||
let document = this._mapping.get(URI.from(notebook.uri).toString());
|
||||
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this._proxy.$acceptDocumentAndEditorsDelta({ removedDocuments: [notebook.uri] });
|
||||
document.dispose();
|
||||
this._mapping.delete(URI.from(notebook.uri).toString());
|
||||
}
|
||||
|
||||
// Methods for ExtHost
|
||||
|
||||
updateLanguages(resource: UriComponents, languages: string[]) {
|
||||
let document = this._mapping.get(URI.from(resource).toString());
|
||||
document?.textModel.updateLanguages(languages);
|
||||
@@ -280,21 +306,12 @@ export class MainThreadNotebookController implements IMainNotebookController {
|
||||
return this._proxy.$executeNotebook(this._viewType, uri, handle, token);
|
||||
}
|
||||
|
||||
async destoryNotebookDocument(notebook: INotebookTextModel): Promise<void> {
|
||||
let document = this._mapping.get(URI.from(notebook.uri).toString());
|
||||
|
||||
if (!document) {
|
||||
return;
|
||||
}
|
||||
|
||||
let removeFromExtHost = await this._proxy.$destoryNotebookDocument(this._viewType, notebook.uri);
|
||||
if (removeFromExtHost) {
|
||||
document.dispose();
|
||||
this._mapping.delete(URI.from(notebook.uri).toString());
|
||||
}
|
||||
}
|
||||
|
||||
async save(uri: URI, token: CancellationToken): Promise<boolean> {
|
||||
return this._proxy.$saveNotebook(this._viewType, uri, token);
|
||||
}
|
||||
|
||||
async saveAs(uri: URI, target: URI, token: CancellationToken): Promise<boolean> {
|
||||
return this._proxy.$saveNotebookAs(this._viewType, uri, target, token);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +368,9 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
}
|
||||
|
||||
private addViews(extensions: readonly IExtensionPointUser<ViewExtensionPointType>[]): void {
|
||||
const viewIds: Set<string> = new Set<string>();
|
||||
const allViewDescriptors: { views: IViewDescriptor[], viewContainer: ViewContainer }[] = [];
|
||||
|
||||
for (const extension of extensions) {
|
||||
const { value, collector } = extension;
|
||||
|
||||
@@ -386,10 +389,9 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
collector.warn(localize('ViewContainerDoesnotExist', "View container '{0}' does not exist and all views registered to it will be added to 'Explorer'.", entry.key));
|
||||
}
|
||||
const container = viewContainer || this.getDefaultViewContainer();
|
||||
const viewIds: string[] = [];
|
||||
const viewDescriptors = coalesce(entry.value.map((item, index) => {
|
||||
// validate
|
||||
if (viewIds.indexOf(item.id) !== -1) {
|
||||
if (viewIds.has(item.id)) {
|
||||
collector.error(localize('duplicateView1', "Cannot register multiple views with same id `{0}`", item.id));
|
||||
return null;
|
||||
}
|
||||
@@ -421,12 +423,16 @@ class ViewsExtensionHandler implements IWorkbenchContribution {
|
||||
remoteAuthority: item.remoteName || (<any>item).remoteAuthority // TODO@roblou - delete after remote extensions are updated
|
||||
};
|
||||
|
||||
viewIds.push(viewDescriptor.id);
|
||||
viewIds.add(viewDescriptor.id);
|
||||
return viewDescriptor;
|
||||
}));
|
||||
this.viewsRegistry.registerViews(viewDescriptors, container);
|
||||
|
||||
allViewDescriptors.push({ viewContainer: container, views: viewDescriptors });
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
this.viewsRegistry.registerViews2(allViewDescriptors);
|
||||
}
|
||||
|
||||
private getDefaultViewContainer(): ViewContainer {
|
||||
|
||||
@@ -931,10 +931,6 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.onDidCloseNotebookDocument;
|
||||
},
|
||||
registerNotebookProvider: (viewType: string, provider: vscode.NotebookProvider) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookProvider(extension, viewType, provider);
|
||||
},
|
||||
registerNotebookContentProvider: (viewType: string, provider: vscode.NotebookContentProvider) => {
|
||||
checkProposedApiEnabled(extension);
|
||||
return extHostNotebook.registerNotebookContentProvider(extension, viewType, provider);
|
||||
@@ -1015,6 +1011,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
|
||||
EvaluatableExpression: extHostTypes.EvaluatableExpression,
|
||||
EventEmitter: Emitter,
|
||||
ExtensionKind: extHostTypes.ExtensionKind,
|
||||
ExtensionMode: extHostTypes.ExtensionMode,
|
||||
CustomExecution: extHostTypes.CustomExecution,
|
||||
CustomExecution2: extHostTypes.CustomExecution,
|
||||
FileChangeType: extHostTypes.FileChangeType,
|
||||
|
||||
@@ -51,7 +51,7 @@ import { TunnelDto } from 'vs/workbench/api/common/extHostTunnelService';
|
||||
import { TunnelOptions } from 'vs/platform/remote/common/tunnel';
|
||||
import { Timeline, TimelineChangeEvent, TimelineOptions, TimelineProviderDescriptor, InternalTimelineOptions } from 'vs/workbench/contrib/timeline/common/timeline';
|
||||
import { revive } from 'vs/base/common/marshalling';
|
||||
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookMimeTypeSelector, IOutput, INotebookDisplayOrder, NotebookCellMetadata, NotebookDocumentMetadata, ICellEditOperation, NotebookCellsChangedEvent, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CallHierarchyItem } from 'vs/workbench/contrib/callHierarchy/common/callHierarchy';
|
||||
import { Dto } from 'vs/base/common/types';
|
||||
import { ISerializableEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable';
|
||||
@@ -695,7 +695,6 @@ export interface MainThreadNotebookShape extends IDisposable {
|
||||
$unregisterNotebookProvider(viewType: string): Promise<void>;
|
||||
$registerNotebookRenderer(extension: NotebookExtensionDescription, type: string, selectors: INotebookMimeTypeSelector, handle: number, preloads: UriComponents[]): Promise<void>;
|
||||
$unregisterNotebookRenderer(handle: number): Promise<void>;
|
||||
$createNotebookDocument(handle: number, viewType: string, resource: UriComponents): Promise<void>;
|
||||
$tryApplyEdits(viewType: string, resource: UriComponents, modelVersionId: number, edits: ICellEditOperation[], renderers: number[]): Promise<boolean>;
|
||||
$updateNotebookLanguages(viewType: string, resource: UriComponents, languages: string[]): Promise<void>;
|
||||
$updateNotebookMetadata(viewType: string, resource: UriComponents, metadata: NotebookDocumentMetadata): Promise<void>;
|
||||
@@ -1542,16 +1541,31 @@ export interface INotebookEditorPropertiesChangeData {
|
||||
selections: INotebookSelectionChangeEvent | null;
|
||||
}
|
||||
|
||||
export interface INotebookModelAddedData {
|
||||
uri: UriComponents;
|
||||
handle: number;
|
||||
// versionId: number;
|
||||
viewType: string;
|
||||
}
|
||||
|
||||
export interface INotebookDocumentsAndEditorsDelta {
|
||||
removedDocuments?: UriComponents[];
|
||||
addedDocuments?: INotebookModelAddedData[];
|
||||
// removedEditors?: string[];
|
||||
// addedEditors?: ITextEditorAddData[];
|
||||
newActiveEditor?: UriComponents | null;
|
||||
}
|
||||
|
||||
export interface ExtHostNotebookShape {
|
||||
$resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined>;
|
||||
$resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined>;
|
||||
$executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void>;
|
||||
$saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$updateActiveEditor(viewType: string, uri: UriComponents): Promise<void>;
|
||||
$destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean>;
|
||||
$saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean>;
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void;
|
||||
$onDidReceiveMessage(uri: UriComponents, message: any): void;
|
||||
$acceptModelChanged(uriComponents: UriComponents, event: NotebookCellsChangedEvent): void;
|
||||
$acceptEditorPropertiesChanged(uriComponents: UriComponents, data: INotebookEditorPropertiesChangeData): void;
|
||||
$acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta): Promise<void>;
|
||||
}
|
||||
|
||||
export interface ExtHostStorageShape {
|
||||
|
||||
@@ -25,7 +25,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { ExtensionMemento } from 'vs/workbench/api/common/extHostMemento';
|
||||
import { RemoteAuthorityResolverError } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { RemoteAuthorityResolverError, ExtensionMode } from 'vs/workbench/api/common/extHostTypes';
|
||||
import { ResolvedAuthority, ResolvedOptions, RemoteAuthorityResolverErrorCode } from 'vs/platform/remote/common/remoteAuthorityResolver';
|
||||
import { IInstantiationService, createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitDataService';
|
||||
@@ -358,8 +358,12 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
|
||||
const globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
|
||||
const workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
|
||||
const extensionMode = extensionDescription.isUnderDevelopment
|
||||
? (this._initData.environment.extensionTestsLocationURI ? ExtensionMode.Test : ExtensionMode.Development)
|
||||
: ExtensionMode.Release;
|
||||
|
||||
this._logService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
|
||||
|
||||
return Promise.all([
|
||||
globalState.whenReady,
|
||||
workspaceState.whenReady,
|
||||
@@ -376,10 +380,11 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
|
||||
get globalStoragePath() { return that._storagePath.globalValue(extensionDescription); },
|
||||
asAbsolutePath(relativePath: string) { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
|
||||
get logPath() { return path.join(that._initData.logsLocation.fsPath, extensionDescription.identifier.value); },
|
||||
get environmentVariableCollection() {
|
||||
get extensionMode() {
|
||||
checkProposedApiEnabled(extensionDescription);
|
||||
return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription);
|
||||
}
|
||||
return extensionMode;
|
||||
},
|
||||
get environmentVariableCollection() { return that._extHostTerminalService.getEnvironmentVariableCollection(extensionDescription); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ import { Disposable, DisposableStore, IDisposable } from 'vs/base/common/lifecyc
|
||||
import { ISplice } from 'vs/base/common/sequence';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { CellKind, CellOutputKind, ExtHostNotebookShape, IMainContext, MainContext, MainThreadNotebookShape, NotebookCellOutputsSplice, MainThreadDocumentsShape, INotebookEditorPropertiesChangeData, INotebookDocumentsAndEditorsDelta } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostCommands } from 'vs/workbench/api/common/extHostCommands';
|
||||
import { ExtHostDocumentsAndEditors } from 'vs/workbench/api/common/extHostDocumentsAndEditors';
|
||||
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellEditType, CellUri, diff, ICellEditOperation, ICellInsertEdit, IErrorOutput, INotebookDisplayOrder, INotebookEditData, IOrderedMimeType, IStreamOutput, ITransformedDisplayOutputDto, mimeTypeSupportedByCore, NotebookCellsChangedEvent, NotebookCellsSplice2, sortMimeTypes, ICellDeleteEdit, notebookDocumentMetadataDefaults, NotebookCellsChangeType, NotebookDataDto } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { Disposable as VSCodeDisposable } from './extHostTypes';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtHostDocumentData } from 'vs/workbench/api/common/extHostDocumentData';
|
||||
@@ -345,8 +345,6 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
|
||||
transformMimeTypes(output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
|
||||
let mimeTypes = Object.keys(output.data);
|
||||
|
||||
// TODO@rebornix, the document display order might be assigned a bit later. We need to postpone sending the outputs to the core side.
|
||||
let coreDisplayOrder = this.renderingHandler.outputDisplayOrder;
|
||||
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], this._displayOrder, coreDisplayOrder?.defaultOrder || []);
|
||||
|
||||
@@ -415,7 +413,7 @@ export class ExtHostNotebookDocument extends Disposable implements vscode.Notebo
|
||||
}
|
||||
}
|
||||
|
||||
export class NotebookEditorCellEdit {
|
||||
export class NotebookEditorCellEditBuilder implements vscode.NotebookEditorCellEdit {
|
||||
private _finalized: boolean = false;
|
||||
private readonly _documentVersionId: number;
|
||||
private _collectedEdits: ICellEditOperation[] = [];
|
||||
@@ -526,13 +524,13 @@ export class ExtHostNotebookEditor extends Disposable implements vscode.Notebook
|
||||
}));
|
||||
}
|
||||
|
||||
edit(callback: (editBuilder: NotebookEditorCellEdit) => void): Thenable<boolean> {
|
||||
const edit = new NotebookEditorCellEdit(this);
|
||||
edit(callback: (editBuilder: NotebookEditorCellEditBuilder) => void): Thenable<boolean> {
|
||||
const edit = new NotebookEditorCellEditBuilder(this);
|
||||
callback(edit);
|
||||
return this._applyEdit(edit);
|
||||
}
|
||||
|
||||
private _applyEdit(editBuilder: NotebookEditorCellEdit): Promise<boolean> {
|
||||
private _applyEdit(editBuilder: NotebookEditorCellEditBuilder): Promise<boolean> {
|
||||
const editData = editBuilder.finalize();
|
||||
|
||||
// return when there is nothing to do
|
||||
@@ -625,7 +623,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
private static _handlePool: number = 0;
|
||||
|
||||
private readonly _proxy: MainThreadNotebookShape;
|
||||
private readonly _notebookProviders = new Map<string, { readonly provider: vscode.NotebookProvider, readonly extension: IExtensionDescription; }>();
|
||||
private readonly _notebookContentProviders = new Map<string, { readonly provider: vscode.NotebookContentProvider, readonly extension: IExtensionDescription; }>();
|
||||
private readonly _documents = new Map<string, ExtHostNotebookDocument>();
|
||||
private readonly _editors = new Map<string, { editor: ExtHostNotebookEditor, onDidReceiveMessage: Emitter<any>; }>();
|
||||
@@ -706,31 +703,13 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return matches;
|
||||
}
|
||||
|
||||
registerNotebookProvider(
|
||||
extension: IExtensionDescription,
|
||||
viewType: string,
|
||||
provider: vscode.NotebookProvider,
|
||||
): vscode.Disposable {
|
||||
|
||||
if (this._notebookProviders.has(viewType)) {
|
||||
throw new Error(`Notebook provider for '${viewType}' already registered`);
|
||||
}
|
||||
|
||||
this._notebookProviders.set(viewType, { extension, provider });
|
||||
this._proxy.$registerNotebookProvider({ id: extension.identifier, location: extension.extensionLocation }, viewType);
|
||||
return new VSCodeDisposable(() => {
|
||||
this._notebookProviders.delete(viewType);
|
||||
this._proxy.$unregisterNotebookProvider(viewType);
|
||||
});
|
||||
}
|
||||
|
||||
registerNotebookContentProvider(
|
||||
extension: IExtensionDescription,
|
||||
viewType: string,
|
||||
provider: vscode.NotebookContentProvider,
|
||||
): vscode.Disposable {
|
||||
|
||||
if (this._notebookProviders.has(viewType)) {
|
||||
if (this._notebookContentProviders.has(viewType)) {
|
||||
throw new Error(`Notebook provider for '${viewType}' already registered`);
|
||||
}
|
||||
|
||||
@@ -742,97 +721,99 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
});
|
||||
}
|
||||
|
||||
async _resolveNotebookFromContentProvider(viewType: string, uri: UriComponents): Promise<number | undefined> {
|
||||
async $resolveNotebookData(viewType: string, uri: UriComponents): Promise<NotebookDataDto | undefined> {
|
||||
let provider = this._notebookContentProviders.get(viewType);
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
|
||||
if (provider) {
|
||||
const revivedUri = URI.revive(uri);
|
||||
if (!this._documents.has(revivedUri.toString())) {
|
||||
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
|
||||
await this._proxy.$createNotebookDocument(
|
||||
document.handle,
|
||||
viewType,
|
||||
uri
|
||||
);
|
||||
|
||||
this._documents.set(revivedUri.toString(), document);
|
||||
}
|
||||
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
|
||||
let editor = new ExtHostNotebookEditor(
|
||||
viewType,
|
||||
`${ExtHostNotebookController._handlePool++}`,
|
||||
revivedUri,
|
||||
this._proxy,
|
||||
onDidReceiveMessage,
|
||||
this._documents.get(revivedUri.toString())!,
|
||||
this._documentsAndEditors
|
||||
);
|
||||
|
||||
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
|
||||
|
||||
const data = await provider.provider.openNotebook(revivedUri);
|
||||
editor.document.languages = data.languages;
|
||||
editor.document.metadata = {
|
||||
if (provider && document) {
|
||||
const rawCells = await provider.provider.openNotebook(URI.revive(uri));
|
||||
const renderers = new Set<number>();
|
||||
const dto = {
|
||||
metadata: {
|
||||
...notebookDocumentMetadataDefaults,
|
||||
...data.metadata
|
||||
};
|
||||
...rawCells.metadata
|
||||
},
|
||||
languages: rawCells.languages,
|
||||
cells: rawCells.cells.map(cell => {
|
||||
let transformedOutputs = cell.outputs.map(output => {
|
||||
if (output.outputKind === CellOutputKind.Rich) {
|
||||
// TODO display string[]
|
||||
const ret = this._transformMimeTypes(document!, (rawCells.metadata.displayOrder as string[]) || [], output);
|
||||
|
||||
await editor.edit(editBuilder => {
|
||||
for (let i = 0; i < data.cells.length; i++) {
|
||||
const cell = data.cells[i];
|
||||
editBuilder.insert(0, cell.source, cell.language, cell.cellKind, cell.outputs, cell.metadata);
|
||||
if (ret.orderedMimeTypes[ret.pickedMimeTypeIndex].isResolved) {
|
||||
renderers.add(ret.orderedMimeTypes[ret.pickedMimeTypeIndex].rendererId!);
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
return output as IStreamOutput | IErrorOutput;
|
||||
}
|
||||
});
|
||||
|
||||
this._onDidOpenNotebookDocument.fire(editor.document);
|
||||
return editor.document.handle;
|
||||
return {
|
||||
language: cell.language,
|
||||
cellKind: cell.cellKind,
|
||||
metadata: cell.metadata,
|
||||
source: cell.source,
|
||||
outputs: transformedOutputs
|
||||
};
|
||||
})
|
||||
};
|
||||
|
||||
return dto;
|
||||
}
|
||||
|
||||
return undefined; // {{SQL CARBON EDIT}}
|
||||
}
|
||||
|
||||
private _transformMimeTypes(document: ExtHostNotebookDocument, displayOrder: string[], output: vscode.CellDisplayOutput): ITransformedDisplayOutputDto {
|
||||
let mimeTypes = Object.keys(output.data);
|
||||
let coreDisplayOrder = this.outputDisplayOrder;
|
||||
const sorted = sortMimeTypes(mimeTypes, coreDisplayOrder?.userOrder || [], displayOrder, coreDisplayOrder?.defaultOrder || []);
|
||||
|
||||
let orderMimeTypes: IOrderedMimeType[] = [];
|
||||
|
||||
sorted.forEach(mimeType => {
|
||||
let handlers = this.findBestMatchedRenderer(mimeType);
|
||||
|
||||
if (handlers.length) {
|
||||
let renderedOutput = handlers[0].render(document, output, mimeType);
|
||||
|
||||
orderMimeTypes.push({
|
||||
mimeType: mimeType,
|
||||
isResolved: true,
|
||||
rendererId: handlers[0].handle,
|
||||
output: renderedOutput
|
||||
});
|
||||
|
||||
for (let i = 1; i < handlers.length; i++) {
|
||||
orderMimeTypes.push({
|
||||
mimeType: mimeType,
|
||||
isResolved: false,
|
||||
rendererId: handlers[i].handle
|
||||
});
|
||||
}
|
||||
|
||||
if (mimeTypeSupportedByCore(mimeType)) {
|
||||
orderMimeTypes.push({
|
||||
mimeType: mimeType,
|
||||
isResolved: false,
|
||||
rendererId: -1
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
orderMimeTypes.push({
|
||||
mimeType: mimeType,
|
||||
isResolved: false
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async $resolveNotebook(viewType: string, uri: UriComponents): Promise<number | undefined> {
|
||||
let notebookFromNotebookContentProvider = await this._resolveNotebookFromContentProvider(viewType, uri);
|
||||
|
||||
if (notebookFromNotebookContentProvider !== undefined) {
|
||||
return notebookFromNotebookContentProvider;
|
||||
}
|
||||
|
||||
let provider = this._notebookProviders.get(viewType);
|
||||
|
||||
if (provider) {
|
||||
if (!this._documents.has(URI.revive(uri).toString())) {
|
||||
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, URI.revive(uri), this);
|
||||
await this._proxy.$createNotebookDocument(
|
||||
document.handle,
|
||||
viewType,
|
||||
uri
|
||||
);
|
||||
|
||||
this._documents.set(URI.revive(uri).toString(), document);
|
||||
}
|
||||
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
|
||||
let editor = new ExtHostNotebookEditor(
|
||||
viewType,
|
||||
`${ExtHostNotebookController._handlePool++}`,
|
||||
URI.revive(uri),
|
||||
this._proxy,
|
||||
onDidReceiveMessage,
|
||||
this._documents.get(URI.revive(uri).toString())!,
|
||||
this._documentsAndEditors
|
||||
);
|
||||
|
||||
this._editors.set(URI.revive(uri).toString(), { editor, onDidReceiveMessage });
|
||||
await provider.provider.resolveNotebook(editor);
|
||||
// await editor.document.$updateCells();
|
||||
return editor.document.handle;
|
||||
}
|
||||
|
||||
return Promise.resolve(undefined);
|
||||
return {
|
||||
outputKind: output.outputKind,
|
||||
data: output.data,
|
||||
orderedMimeTypes: orderMimeTypes,
|
||||
pickedMimeTypeIndex: 0
|
||||
};
|
||||
}
|
||||
|
||||
async $executeNotebook(viewType: string, uri: UriComponents, cellHandle: number | undefined, token: CancellationToken): Promise<void> {
|
||||
@@ -847,15 +828,6 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
|
||||
return this._notebookContentProviders.get(viewType)!.provider.executeCell(document, cell, token);
|
||||
}
|
||||
|
||||
let provider = this._notebookProviders.get(viewType);
|
||||
|
||||
if (!provider) {
|
||||
return;
|
||||
}
|
||||
|
||||
let cell = cellHandle !== undefined ? document.getCell(cellHandle) : undefined;
|
||||
return provider.provider.executeCell(document!, cell, token);
|
||||
}
|
||||
|
||||
async $saveNotebook(viewType: string, uri: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
@@ -874,46 +846,28 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
return true;
|
||||
}
|
||||
|
||||
let provider = this._notebookProviders.get(viewType);
|
||||
|
||||
if (provider && document) {
|
||||
return await provider.provider.save(document);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
async $updateActiveEditor(viewType: string, uri: UriComponents): Promise<void> {
|
||||
this._activeNotebookDocument = this._documents.get(URI.revive(uri).toString());
|
||||
this._activeNotebookEditor = this._editors.get(URI.revive(uri).toString())?.editor;
|
||||
}
|
||||
|
||||
async $destoryNotebookDocument(viewType: string, uri: UriComponents): Promise<boolean> {
|
||||
let provider = this._notebookProviders.get(viewType);
|
||||
|
||||
if (!provider) {
|
||||
return false;
|
||||
}
|
||||
|
||||
async $saveNotebookAs(viewType: string, uri: UriComponents, target: UriComponents, token: CancellationToken): Promise<boolean> {
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
|
||||
if (document) {
|
||||
document.dispose();
|
||||
this._documents.delete(URI.revive(uri).toString());
|
||||
this._onDidCloseNotebookDocument.fire(document);
|
||||
if (!document) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let editor = this._editors.get(URI.revive(uri).toString());
|
||||
|
||||
if (editor) {
|
||||
editor.editor.dispose();
|
||||
editor.onDidReceiveMessage.dispose();
|
||||
this._editors.delete(URI.revive(uri).toString());
|
||||
if (this._notebookContentProviders.has(viewType)) {
|
||||
try {
|
||||
await this._notebookContentProviders.get(viewType)!.provider.saveNotebookAs(URI.revive(target), document, token);
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$acceptDisplayOrder(displayOrder: INotebookDisplayOrder): void {
|
||||
this._outputDisplayOrder = displayOrder;
|
||||
}
|
||||
@@ -957,4 +911,60 @@ export class ExtHostNotebookController implements ExtHostNotebookShape, ExtHostN
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async $acceptDocumentAndEditorsDelta(delta: INotebookDocumentsAndEditorsDelta) {
|
||||
if (delta.removedDocuments) {
|
||||
delta.removedDocuments.forEach((uri) => {
|
||||
let document = this._documents.get(URI.revive(uri).toString());
|
||||
|
||||
if (document) {
|
||||
document.dispose();
|
||||
this._documents.delete(URI.revive(uri).toString());
|
||||
this._onDidCloseNotebookDocument.fire(document);
|
||||
}
|
||||
|
||||
let editor = this._editors.get(URI.revive(uri).toString());
|
||||
|
||||
if (editor) {
|
||||
editor.editor.dispose();
|
||||
editor.onDidReceiveMessage.dispose();
|
||||
this._editors.delete(URI.revive(uri).toString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (delta.addedDocuments) {
|
||||
delta.addedDocuments.forEach(modelData => {
|
||||
const revivedUri = URI.revive(modelData.uri);
|
||||
const viewType = modelData.viewType;
|
||||
if (!this._documents.has(revivedUri.toString())) {
|
||||
let document = new ExtHostNotebookDocument(this._proxy, this._documentsAndEditors, viewType, revivedUri, this);
|
||||
this._documents.set(revivedUri.toString(), document);
|
||||
}
|
||||
|
||||
const onDidReceiveMessage = new Emitter<any>();
|
||||
const document = this._documents.get(revivedUri.toString())!;
|
||||
|
||||
let editor = new ExtHostNotebookEditor(
|
||||
viewType,
|
||||
`${ExtHostNotebookController._handlePool++}`,
|
||||
revivedUri,
|
||||
this._proxy,
|
||||
onDidReceiveMessage,
|
||||
document,
|
||||
this._documentsAndEditors
|
||||
);
|
||||
|
||||
this._onDidOpenNotebookDocument.fire(document);
|
||||
|
||||
// TODO, does it already exist?
|
||||
this._editors.set(revivedUri.toString(), { editor, onDidReceiveMessage });
|
||||
});
|
||||
}
|
||||
|
||||
if (delta.newActiveEditor) {
|
||||
this._activeNotebookDocument = this._documents.get(URI.revive(delta.newActiveEditor).toString());
|
||||
this._activeNotebookEditor = this._editors.get(URI.revive(delta.newActiveEditor).toString())?.editor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2742,3 +2742,27 @@ export class TimelineItem implements vscode.TimelineItem {
|
||||
}
|
||||
|
||||
//#endregion Timeline
|
||||
|
||||
//#region ExtensionContext
|
||||
|
||||
export enum ExtensionMode {
|
||||
/**
|
||||
* The extension is installed normally (for example, from the marketplace
|
||||
* or VSIX) in VS Code.
|
||||
*/
|
||||
Release = 1,
|
||||
|
||||
/**
|
||||
* The extension is running from an `--extensionDevelopmentPath` provided
|
||||
* when launching VS Code.
|
||||
*/
|
||||
Development = 2,
|
||||
|
||||
/**
|
||||
* The extension is running from an `--extensionDevelopmentPath` and
|
||||
* the extension host is running unit tests.
|
||||
*/
|
||||
Test = 3,
|
||||
}
|
||||
|
||||
//#endregion ExtensionContext
|
||||
|
||||
@@ -37,7 +37,6 @@ namespace schema {
|
||||
case 'debug/callstack/context': return MenuId.DebugCallStackContext;
|
||||
case 'debug/toolbar': return MenuId.DebugToolBar;
|
||||
case 'debug/toolBar': return MenuId.DebugToolBar;
|
||||
case 'menuBar/file': return MenuId.MenubarFileMenu;
|
||||
case 'menuBar/webNavigation': return MenuId.MenubarWebNavigationMenu;
|
||||
case 'scm/title': return MenuId.SCMTitle;
|
||||
case 'scm/sourceControl': return MenuId.SCMSourceControl;
|
||||
@@ -70,7 +69,6 @@ namespace schema {
|
||||
export function isProposedAPI(menuId: MenuId): boolean {
|
||||
switch (menuId) {
|
||||
case MenuId.StatusBarWindowIndicatorMenu:
|
||||
case MenuId.MenubarFileMenu:
|
||||
case MenuId.MenubarWebNavigationMenu:
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -230,13 +230,10 @@ export class ExtHostTerminalService extends BaseExtHostTerminalService {
|
||||
|
||||
public getEnvironmentVariableCollection(extension: IExtensionDescription): vscode.EnvironmentVariableCollection {
|
||||
let collection = this._environmentVariableCollections.get(extension.identifier.value);
|
||||
|
||||
if (!collection) {
|
||||
// TODO: Disable dispose
|
||||
collection = new EnvironmentVariableCollection();
|
||||
this._setEnvironmentVariableCollection(extension.identifier.value, collection);
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,8 +202,9 @@ class NavigateDownAction extends BaseNavigationAction {
|
||||
}
|
||||
|
||||
function findVisibleNeighbour(layoutService: IWorkbenchLayoutService, part: Parts, next: boolean): Parts {
|
||||
const neighbour = part === Parts.EDITOR_PART ? (next ? Parts.STATUSBAR_PART : Parts.PANEL_PART) : part === Parts.STATUSBAR_PART ? (next ? Parts.SIDEBAR_PART : Parts.EDITOR_PART) :
|
||||
part === Parts.SIDEBAR_PART ? (next ? Parts.PANEL_PART : Parts.STATUSBAR_PART) : part === Parts.PANEL_PART ? (next ? Parts.EDITOR_PART : Parts.SIDEBAR_PART) : Parts.EDITOR_PART;
|
||||
const neighbour = part === Parts.EDITOR_PART ? (next ? Parts.STATUSBAR_PART : Parts.PANEL_PART) : part === Parts.STATUSBAR_PART ? (next ? Parts.ACTIVITYBAR_PART : Parts.EDITOR_PART) :
|
||||
part === Parts.ACTIVITYBAR_PART ? (next ? Parts.SIDEBAR_PART : Parts.STATUSBAR_PART) : part === Parts.SIDEBAR_PART ? (next ? Parts.PANEL_PART : Parts.ACTIVITYBAR_PART) :
|
||||
part === Parts.PANEL_PART ? (next ? Parts.EDITOR_PART : Parts.SIDEBAR_PART) : Parts.EDITOR_PART;
|
||||
if (layoutService.isVisible(neighbour) || neighbour === Parts.EDITOR_PART) {
|
||||
return neighbour;
|
||||
}
|
||||
@@ -212,8 +213,8 @@ function findVisibleNeighbour(layoutService: IWorkbenchLayoutService, part: Part
|
||||
}
|
||||
|
||||
function focusNextOrPreviousPart(layoutService: IWorkbenchLayoutService, next: boolean): void {
|
||||
const currentlyFocusedPart = layoutService.hasFocus(Parts.EDITOR_PART) ? Parts.EDITOR_PART : layoutService.hasFocus(Parts.STATUSBAR_PART) ? Parts.STATUSBAR_PART :
|
||||
layoutService.hasFocus(Parts.SIDEBAR_PART) ? Parts.SIDEBAR_PART : layoutService.hasFocus(Parts.PANEL_PART) ? Parts.PANEL_PART : undefined;
|
||||
const currentlyFocusedPart = layoutService.hasFocus(Parts.EDITOR_PART) ? Parts.EDITOR_PART : layoutService.hasFocus(Parts.ACTIVITYBAR_PART) ? Parts.ACTIVITYBAR_PART :
|
||||
layoutService.hasFocus(Parts.STATUSBAR_PART) ? Parts.STATUSBAR_PART : layoutService.hasFocus(Parts.SIDEBAR_PART) ? Parts.SIDEBAR_PART : layoutService.hasFocus(Parts.PANEL_PART) ? Parts.PANEL_PART : undefined;
|
||||
let partToFocus = Parts.EDITOR_PART;
|
||||
if (currentlyFocusedPart) {
|
||||
partToFocus = findVisibleNeighbour(layoutService, currentlyFocusedPart, next);
|
||||
|
||||
@@ -11,7 +11,7 @@ import { IWindowOpenable } from 'vs/platform/windows/common/windows';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ITextFileService, stringToSnapshot } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IEditorViewState } from 'vs/editor/common/editorCommon';
|
||||
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { DataTransfers, IDragAndDropData } from 'vs/base/browser/dnd';
|
||||
import { DragMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
import { normalizeDriveLetter } from 'vs/base/common/labels';
|
||||
@@ -58,7 +58,7 @@ export interface IDraggedEditor extends IDraggedResource {
|
||||
content?: string;
|
||||
encoding?: string;
|
||||
mode?: string;
|
||||
viewState?: IEditorViewState;
|
||||
options?: ITextEditorOptions;
|
||||
}
|
||||
|
||||
export interface ISerializedDraggedEditor {
|
||||
@@ -66,7 +66,7 @@ export interface ISerializedDraggedEditor {
|
||||
content?: string;
|
||||
encoding?: string;
|
||||
mode?: string;
|
||||
viewState?: IEditorViewState;
|
||||
options?: ITextEditorOptions;
|
||||
}
|
||||
|
||||
export const CodeDataTransfers = {
|
||||
@@ -90,7 +90,7 @@ export function extractResources(e: DragEvent, externalOnly?: boolean): Array<ID
|
||||
resources.push({
|
||||
resource: URI.parse(draggedEditor.resource),
|
||||
content: draggedEditor.content,
|
||||
viewState: draggedEditor.viewState,
|
||||
options: draggedEditor.options,
|
||||
encoding: draggedEditor.encoding,
|
||||
mode: draggedEditor.mode,
|
||||
isExternal: false
|
||||
@@ -202,9 +202,9 @@ export class ResourcesDropHandler {
|
||||
encoding: (untitledOrFileResource as IDraggedEditor).encoding,
|
||||
mode: (untitledOrFileResource as IDraggedEditor).mode,
|
||||
options: {
|
||||
...(untitledOrFileResource as IDraggedEditor).options,
|
||||
pinned: true,
|
||||
index: targetIndex,
|
||||
viewState: (untitledOrFileResource as IDraggedEditor).viewState
|
||||
index: targetIndex
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -311,7 +311,7 @@ export class ResourcesDropHandler {
|
||||
}
|
||||
}
|
||||
|
||||
export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], event: DragMouseEvent | DragEvent): void {
|
||||
export function fillResourceDataTransfers(accessor: ServicesAccessor, resources: (URI | { resource: URI, isDirectory: boolean })[], optionsCallback: ((resource: URI) => ITextEditorOptions) | undefined, event: DragMouseEvent | DragEvent): void {
|
||||
if (resources.length === 0 || !event.dataTransfer) {
|
||||
return;
|
||||
}
|
||||
@@ -346,20 +346,32 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
|
||||
|
||||
const draggedEditors: ISerializedDraggedEditor[] = [];
|
||||
files.forEach(file => {
|
||||
let options: ITextEditorOptions | undefined = undefined;
|
||||
|
||||
// Try to find editor view state from the visible editors that match given resource
|
||||
let viewState: IEditorViewState | undefined = undefined;
|
||||
// Use provided callback for editor options
|
||||
if (typeof optionsCallback === 'function') {
|
||||
options = optionsCallback(file.resource);
|
||||
}
|
||||
|
||||
// Otherwise try to figure out the view state from opened editors that match
|
||||
else {
|
||||
options = {
|
||||
viewState: (() => {
|
||||
const textEditorControls = editorService.visibleTextEditorControls;
|
||||
for (const textEditorControl of textEditorControls) {
|
||||
if (isCodeEditor(textEditorControl)) {
|
||||
const model = textEditorControl.getModel();
|
||||
if (model?.uri?.toString() === file.resource.toString()) {
|
||||
viewState = withNullAsUndefined(textEditorControl.saveViewState());
|
||||
break;
|
||||
return withNullAsUndefined(textEditorControl.saveViewState());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
})()
|
||||
};
|
||||
}
|
||||
|
||||
// Try to find encoding and mode from text model
|
||||
let encoding: string | undefined = undefined;
|
||||
let mode: string | undefined = undefined;
|
||||
@@ -378,7 +390,7 @@ export function fillResourceDataTransfers(accessor: ServicesAccessor, resources:
|
||||
}
|
||||
|
||||
// Add as dragged editor
|
||||
draggedEditors.push({ resource: file.resource.toString(), content, viewState, encoding, mode });
|
||||
draggedEditors.push({ resource: file.resource.toString(), content, options, encoding, mode });
|
||||
});
|
||||
|
||||
if (draggedEditors.length) {
|
||||
|
||||
@@ -42,8 +42,21 @@ function toResource(props: IResourceLabelProps | undefined): URI | undefined {
|
||||
}
|
||||
|
||||
export interface IResourceLabelOptions extends IIconLabelValueOptions {
|
||||
|
||||
/**
|
||||
* A hint to the file kind of the resource.
|
||||
*/
|
||||
fileKind?: FileKind;
|
||||
|
||||
/**
|
||||
* File decorations to use for the label.
|
||||
*/
|
||||
fileDecorations?: { colors: boolean, badges: boolean };
|
||||
|
||||
/**
|
||||
* Will take the provided label as is and e.g. not override it for untitled files.
|
||||
*/
|
||||
forceLabel?: boolean;
|
||||
}
|
||||
|
||||
export interface IFileLabelOptions extends IResourceLabelOptions {
|
||||
@@ -368,7 +381,7 @@ class ResourceLabelWidget extends IconLabel {
|
||||
/*const resource = toResource(label); {{SQL CARBON EDIT}} we don't want to special case untitled files
|
||||
const isMasterDetail = label?.resource && !URI.isUri(label.resource);
|
||||
|
||||
if (!isMasterDetail && resource?.scheme === Schemas.untitled) {
|
||||
if (!options.forceLabel && !isMasterDetail && resource?.scheme === Schemas.untitled) {
|
||||
// Untitled labels are very dynamic because they may change
|
||||
// whenever the content changes (unless a path is associated).
|
||||
// As such we always ask the actual editor for it's name and
|
||||
@@ -528,7 +541,6 @@ class ResourceLabelWidget extends IconLabel {
|
||||
);
|
||||
|
||||
if (deco) {
|
||||
|
||||
this.renderDisposables.add(deco);
|
||||
|
||||
if (deco.tooltip) {
|
||||
|
||||
@@ -177,6 +177,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
private backupFileService!: IBackupFileService;
|
||||
private notificationService!: INotificationService;
|
||||
private themeService!: IThemeService;
|
||||
private activityBarService!: IActivityBarService;
|
||||
|
||||
protected readonly state = {
|
||||
fullscreen: false,
|
||||
@@ -260,8 +261,8 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
this.viewDescriptorService = accessor.get(IViewDescriptorService);
|
||||
this.titleService = accessor.get(ITitleService);
|
||||
this.notificationService = accessor.get(INotificationService);
|
||||
this.activityBarService = accessor.get(IActivityBarService);
|
||||
accessor.get(IStatusbarService); // not used, but called to ensure instantiated
|
||||
accessor.get(IActivityBarService); // not used, but called to ensure instantiated
|
||||
|
||||
// Listeners
|
||||
this.registerLayoutListeners();
|
||||
@@ -846,6 +847,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
|
||||
activeViewlet.focus();
|
||||
}
|
||||
break;
|
||||
case Parts.ACTIVITYBAR_PART:
|
||||
this.activityBarService.focusActivityBar();
|
||||
break;
|
||||
default:
|
||||
// Status Bar, Activity Bar and Title Bar simply pass focus to container
|
||||
const container = this.getContainer(part);
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
.monaco-workbench .part > .drop-block-overlay.visible {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.monaco-workbench .part > .drop-block-overlay {
|
||||
@@ -18,10 +17,8 @@
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
backdrop-filter: brightness(97%) blur(2px);
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
transition: opacity .5s, visibility .5s;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
|
||||
@@ -168,6 +168,10 @@ export class ActivitybarPart extends Part implements IActivityBarService {
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
focusActivityBar(): void {
|
||||
this.compositeBar.focus();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// View Container Changes
|
||||
|
||||
@@ -66,8 +66,6 @@ export class CompositeDragAndDrop implements ICompositeDragAndDrop {
|
||||
if (targetCompositeId) {
|
||||
this.moveComposite(currentContainer.id, targetCompositeId, before);
|
||||
}
|
||||
|
||||
this.openComposite(currentContainer.id, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,6 +253,12 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
return actionBarDiv;
|
||||
}
|
||||
|
||||
focus(): void {
|
||||
if (this.compositeSwitcherBar) {
|
||||
this.compositeSwitcherBar.focus();
|
||||
}
|
||||
}
|
||||
|
||||
layout(dimension: Dimension): void {
|
||||
this.dimension = dimension;
|
||||
if (dimension.height === 0 || dimension.width === 0) {
|
||||
@@ -275,8 +279,7 @@ export class CompositeBar extends Widget implements ICompositeBar {
|
||||
// Add to the model
|
||||
if (this.model.add(id, name, order)) {
|
||||
this.computeSizes([this.model.findItem(id)]);
|
||||
// Set timeout helps prevent flicker
|
||||
setTimeout(() => this.updateCompositeSwitcher(), 0);
|
||||
this.updateCompositeSwitcher();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -548,11 +548,8 @@ export class CompositeActionViewItem extends ActivityActionViewItem {
|
||||
if (e.eventData.dataTransfer) {
|
||||
e.eventData.dataTransfer.effectAllowed = 'move';
|
||||
}
|
||||
|
||||
// Trigger the action even on drag start to prevent clicks from failing that started a drag
|
||||
if (!this.getAction().checked) {
|
||||
this.getAction().run();
|
||||
}
|
||||
// Remove focus indicator when dragging
|
||||
this.blur();
|
||||
}
|
||||
}));
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import { MementoObject } from 'vs/workbench/common/memento';
|
||||
import { isEqualOrParent, joinPath } from 'vs/base/common/resources';
|
||||
import { isLinux } from 'vs/base/common/platform';
|
||||
import { indexOfPath } from 'vs/base/common/extpath';
|
||||
import { IDisposable } from 'vs/base/common/lifecycle';
|
||||
|
||||
/**
|
||||
* The base class of editors in the workbench. Editors register themselves for specific editor inputs.
|
||||
@@ -171,6 +172,7 @@ interface MapGroupToMemento<T> {
|
||||
export class EditorMemento<T> implements IEditorMemento<T> {
|
||||
private cache: LRUCache<string, MapGroupToMemento<T>> | undefined;
|
||||
private cleanedUp = false;
|
||||
private editorDisposables: Map<EditorInput, IDisposable> | undefined;
|
||||
|
||||
constructor(
|
||||
public readonly id: string,
|
||||
@@ -200,9 +202,18 @@ export class EditorMemento<T> implements IEditorMemento<T> {
|
||||
|
||||
// Automatically clear when editor input gets disposed if any
|
||||
if (resourceOrEditor instanceof EditorInput) {
|
||||
Event.once(resourceOrEditor.onDispose)(() => {
|
||||
const editor = resourceOrEditor;
|
||||
|
||||
if (!this.editorDisposables) {
|
||||
this.editorDisposables = new Map<EditorInput, IDisposable>();
|
||||
}
|
||||
|
||||
if (!this.editorDisposables.has(editor)) {
|
||||
this.editorDisposables.set(editor, Event.once(resourceOrEditor.onDispose)(() => {
|
||||
this.clearEditorState(resource);
|
||||
});
|
||||
this.editorDisposables?.delete(editor);
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import * as nls from 'vs/nls';
|
||||
import { URI, UriComponents } from 'vs/base/common/uri';
|
||||
import { IEditorRegistry, EditorDescriptor, Extensions as EditorExtensions } from 'vs/workbench/browser/editor';
|
||||
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext } from 'vs/workbench/common/editor';
|
||||
import { EditorInput, IEditorInputFactory, SideBySideEditorInput, IEditorInputFactoryRegistry, Extensions as EditorInputExtensions, TextCompareEditorActiveContext, EditorPinnedContext, EditorGroupEditorsCountContext, EditorStickyContext } from 'vs/workbench/common/editor';
|
||||
import { TextResourceEditor } from 'vs/workbench/browser/parts/editor/textResourceEditor';
|
||||
import { SideBySideEditor } from 'vs/workbench/browser/parts/editor/sideBySideEditor';
|
||||
import { DiffEditorInput } from 'vs/workbench/common/editor/diffEditorInput';
|
||||
@@ -433,6 +433,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCo
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: nls.localize('closeAllSaved', "Close Saved") }, group: '1_close', order: 40 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: nls.localize('closeAll', "Close All") }, group: '1_close', order: 50 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: nls.localize('keepOpen', "Keep Open"), precondition: EditorPinnedContext.toNegated() }, group: '3_preview', order: 10, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: nls.localize('pin', "Pin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')) });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: nls.localize('unpin', "Unpin") }, group: '3_preview', order: 20, when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')) });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_UP, title: nls.localize('splitUp', "Split Up") }, group: '5_split', order: 10 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_DOWN, title: nls.localize('splitDown', "Split Down") }, group: '5_split', order: 20 });
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitleContext, { command: { id: editorCommands.SPLIT_EDITOR_LEFT, title: nls.localize('splitLeft', "Split Left") }, group: '5_split', order: 30 });
|
||||
@@ -579,6 +581,8 @@ appendEditorToolItem(
|
||||
// Editor Commands for Command Palette
|
||||
const viewCategory = { value: nls.localize('view', "View"), original: 'View' };
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.KEEP_EDITOR_COMMAND_ID, title: { value: nls.localize('keepEditor', "Keep Editor"), original: 'Keep Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.enablePreview') });
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.PIN_EDITOR_COMMAND_ID, title: { value: nls.localize('pinEditor', "Pin Editor"), original: 'Pin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.UNPIN_EDITOR_COMMAND_ID, title: { value: nls.localize('unpinEditor', "Unpin Editor"), original: 'Unpin Editor' }, category: viewCategory }, when: ContextKeyExpr.has('config.workbench.editor.showTabs') });
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeEditorsInGroup', "Close All Editors in Group"), original: 'Close All Editors in Group' }, category: viewCategory } });
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_SAVED_EDITORS_COMMAND_ID, title: { value: nls.localize('closeSavedEditors', "Close Saved Editors in Group"), original: 'Close Saved Editors in Group' }, category: viewCategory } });
|
||||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { command: { id: editorCommands.CLOSE_OTHER_EDITORS_IN_GROUP_COMMAND_ID, title: { value: nls.localize('closeOtherEditors', "Close Other Editors in Group"), original: 'Close Other Editors in Group' }, category: viewCategory } });
|
||||
|
||||
@@ -500,7 +500,7 @@ export class CloseLeftEditorsInGroupAction extends Action {
|
||||
async run(context?: IEditorIdentifier): Promise<void> {
|
||||
const { group, editor } = getTarget(this.editorService, this.editorGroupService, context);
|
||||
if (group && editor) {
|
||||
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor });
|
||||
return group.closeEditors({ direction: CloseDirection.LEFT, except: editor, excludeSticky: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,7 +514,7 @@ function getTarget(editorService: IEditorService, editorGroupService: IEditorGro
|
||||
return { group: editorGroupService.activeGroup, editor: editorGroupService.activeGroup.activeEditor };
|
||||
}
|
||||
|
||||
export abstract class BaseCloseAllAction extends Action {
|
||||
abstract class BaseCloseAllAction extends Action {
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -554,7 +554,7 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
// to bring each dirty editor to the front so that the user
|
||||
// can review if the files should be changed or not.
|
||||
await Promise.all(this.groupsToClose.map(async groupToClose => {
|
||||
for (const editor of groupToClose.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE)) {
|
||||
for (const editor of groupToClose.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: this.excludeSticky })) {
|
||||
if (editor.isDirty() && !editor.isSaving() /* ignore editors that are being saved */) {
|
||||
return groupToClose.openEditor(editor);
|
||||
}
|
||||
@@ -566,7 +566,7 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
const dirtyEditorsToConfirm = new Set<string>();
|
||||
const dirtyEditorsToAutoSave = new Set<IEditorInput>();
|
||||
|
||||
for (const editor of this.editorService.editors) {
|
||||
for (const editor of this.editorService.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: this.excludeSticky }).map(({ editor }) => editor)) {
|
||||
if (!editor.isDirty() || editor.isSaving()) {
|
||||
continue; // only interested in dirty editors (unless in the process of saving)
|
||||
}
|
||||
@@ -601,21 +601,29 @@ export abstract class BaseCloseAllAction extends Action {
|
||||
confirmation = ConfirmResult.DONT_SAVE;
|
||||
}
|
||||
|
||||
if (confirmation === ConfirmResult.CANCEL) {
|
||||
// Handle result from asking user
|
||||
let result: boolean | undefined = undefined;
|
||||
switch (confirmation) {
|
||||
case ConfirmResult.CANCEL:
|
||||
return;
|
||||
case ConfirmResult.DONT_SAVE:
|
||||
result = await this.editorService.revertAll({ soft: true, includeUntitled: true, excludeSticky: this.excludeSticky });
|
||||
break;
|
||||
case ConfirmResult.SAVE:
|
||||
result = await this.editorService.saveAll({ reason: saveReason, includeUntitled: true, excludeSticky: this.excludeSticky });
|
||||
break;
|
||||
}
|
||||
|
||||
if (confirmation === ConfirmResult.DONT_SAVE) {
|
||||
await this.editorService.revertAll({ soft: true, includeUntitled: true });
|
||||
} else {
|
||||
await this.editorService.saveAll({ reason: saveReason, includeUntitled: true });
|
||||
}
|
||||
|
||||
if (!this.workingCopyService.hasDirty) {
|
||||
// Only continue to close editors if we either have no more dirty
|
||||
// editors or the result from the save/revert was successful
|
||||
if (!this.workingCopyService.hasDirty || result) {
|
||||
return this.doCloseAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract get excludeSticky(): boolean;
|
||||
|
||||
protected abstract doCloseAll(): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -636,8 +644,12 @@ export class CloseAllEditorsAction extends BaseCloseAllAction {
|
||||
super(id, label, Codicon.closeAll.classNames, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
|
||||
}
|
||||
|
||||
protected get excludeSticky(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected async doCloseAll(): Promise<void> {
|
||||
await Promise.all(this.groupsToClose.map(g => g.closeAllEditors()));
|
||||
await Promise.all(this.groupsToClose.map(group => group.closeAllEditors({ excludeSticky: true })));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,6 +670,10 @@ export class CloseAllEditorGroupsAction extends BaseCloseAllAction {
|
||||
super(id, label, undefined, workingCopyService, fileDialogService, editorGroupService, editorService, filesConfigurationService);
|
||||
}
|
||||
|
||||
protected get excludeSticky(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected async doCloseAll(): Promise<void> {
|
||||
await Promise.all(this.groupsToClose.map(group => group.closeAllEditors()));
|
||||
|
||||
@@ -680,12 +696,12 @@ export class CloseEditorsInOtherGroupsAction extends Action {
|
||||
|
||||
async run(context?: IEditorIdentifier): Promise<void> {
|
||||
const groupToSkip = context ? this.editorGroupService.getGroup(context.groupId) : this.editorGroupService.activeGroup;
|
||||
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(async g => {
|
||||
if (groupToSkip && g.id === groupToSkip.id) {
|
||||
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(async group => {
|
||||
if (groupToSkip && group.id === groupToSkip.id) {
|
||||
return;
|
||||
}
|
||||
|
||||
return g.closeAllEditors();
|
||||
return group.closeAllEditors({ excludeSticky: true });
|
||||
}));
|
||||
}
|
||||
}
|
||||
@@ -707,7 +723,7 @@ export class CloseEditorInAllGroupsAction extends Action {
|
||||
async run(): Promise<void> {
|
||||
const activeEditor = this.editorService.activeEditor;
|
||||
if (activeEditor) {
|
||||
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(g => g.closeEditor(activeEditor)));
|
||||
await Promise.all(this.editorGroupService.getGroups(GroupsOrder.MOST_RECENTLY_ACTIVE).map(group => group.closeEditor(activeEditor)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import * as nls from 'vs/nls';
|
||||
import * as types from 'vs/base/common/types';
|
||||
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane } from 'vs/workbench/common/editor';
|
||||
import { TextCompareEditorVisibleContext, EditorInput, IEditorIdentifier, IEditorCommandsContext, ActiveEditorGroupEmptyContext, MultipleEditorGroupsContext, CloseDirection, IEditorInput, IVisibleEditorPane, EditorStickyContext, EditorsOrder } from 'vs/workbench/common/editor';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
import { TextDiffEditor } from 'vs/workbench/browser/parts/editor/textDiffEditor';
|
||||
@@ -37,6 +37,9 @@ export const LAYOUT_EDITOR_GROUPS_COMMAND_ID = 'layoutEditorGroups';
|
||||
export const KEEP_EDITOR_COMMAND_ID = 'workbench.action.keepEditor';
|
||||
export const SHOW_EDITORS_IN_GROUP = 'workbench.action.showEditorsInGroup';
|
||||
|
||||
export const PIN_EDITOR_COMMAND_ID = 'workbench.action.pinEditor';
|
||||
export const UNPIN_EDITOR_COMMAND_ID = 'workbench.action.unpinEditor';
|
||||
|
||||
export const TOGGLE_DIFF_SIDE_BY_SIDE = 'toggle.diff.renderSideBySide';
|
||||
export const GOTO_NEXT_CHANGE = 'workbench.action.compareEditor.nextChange';
|
||||
export const GOTO_PREVIOUS_CHANGE = 'workbench.action.compareEditor.previousChange';
|
||||
@@ -258,7 +261,7 @@ function registerDiffEditorCommands(): void {
|
||||
|
||||
function navigateInDiffEditor(accessor: ServicesAccessor, next: boolean): void {
|
||||
const editorService = accessor.get(IEditorService);
|
||||
const candidates = [editorService.activeEditorPane, ...editorService.visibleEditorPanes].filter(e => e instanceof TextDiffEditor);
|
||||
const candidates = [editorService.activeEditorPane, ...editorService.visibleEditorPanes].filter(editor => editor instanceof TextDiffEditor);
|
||||
|
||||
if (candidates.length > 0) {
|
||||
const navigator = (<TextDiffEditor>candidates[0]).getDiffNavigator();
|
||||
@@ -491,7 +494,7 @@ function registerCloseEditorCommands() {
|
||||
return Promise.all(distinct(contexts.map(c => c.groupId)).map(async groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
if (group) {
|
||||
return group.closeEditors({ savedOnly: true });
|
||||
return group.closeEditors({ savedOnly: true, excludeSticky: true });
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -514,7 +517,7 @@ function registerCloseEditorCommands() {
|
||||
return Promise.all(distinctGroupIds.map(async groupId => {
|
||||
const group = editorGroupService.getGroup(groupId);
|
||||
if (group) {
|
||||
return group.closeAllEditors();
|
||||
return group.closeAllEditors({ excludeSticky: true });
|
||||
}
|
||||
}));
|
||||
}
|
||||
@@ -596,7 +599,8 @@ function registerCloseEditorCommands() {
|
||||
const editors = contexts
|
||||
.filter(context => context.groupId === groupId)
|
||||
.map(context => typeof context.editorIndex === 'number' ? group.getEditorByIndex(context.editorIndex) : group.activeEditor);
|
||||
const editorsToClose = group.editors.filter(e => editors.indexOf(e) === -1);
|
||||
|
||||
const editorsToClose = group.getEditors(EditorsOrder.SEQUENTIAL, { excludeSticky: true }).filter(editor => editors.indexOf(editor) === -1);
|
||||
|
||||
if (group.activeEditor) {
|
||||
group.pinEditor(group.activeEditor);
|
||||
@@ -622,7 +626,7 @@ function registerCloseEditorCommands() {
|
||||
group.pinEditor(group.activeEditor);
|
||||
}
|
||||
|
||||
return group.closeEditors({ direction: CloseDirection.RIGHT, except: editor });
|
||||
return group.closeEditors({ direction: CloseDirection.RIGHT, except: editor, excludeSticky: true });
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -642,6 +646,36 @@ function registerCloseEditorCommands() {
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: PIN_EDITOR_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(EditorStickyContext.toNegated(), ContextKeyExpr.has('config.workbench.editor.showTabs')),
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.Enter),
|
||||
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
|
||||
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
|
||||
if (group && editor) {
|
||||
return group.stickEditor(editor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: UNPIN_EDITOR_COMMAND_ID,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
when: ContextKeyExpr.and(EditorStickyContext, ContextKeyExpr.has('config.workbench.editor.showTabs')),
|
||||
primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.Enter),
|
||||
handler: async (accessor, resourceOrContext: URI | IEditorCommandsContext, context?: IEditorCommandsContext) => {
|
||||
const editorGroupService = accessor.get(IEditorGroupsService);
|
||||
|
||||
const { group, editor } = resolveCommandsContext(editorGroupService, getCommandsContext(resourceOrContext, context));
|
||||
if (group && editor) {
|
||||
return group.unstickEditor(editor);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: SHOW_EDITORS_IN_GROUP,
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
|
||||
@@ -266,7 +266,10 @@ class DropOverlay extends Themable {
|
||||
}
|
||||
|
||||
// Open in target group
|
||||
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({ pinned: true }));
|
||||
const options = getActiveTextEditorOptions(sourceGroup, draggedEditor.editor, EditorOptions.create({
|
||||
pinned: true, // always pin dropped editor
|
||||
sticky: sourceGroup.isSticky(draggedEditor.editor) // preserve sticky state
|
||||
}));
|
||||
targetGroup.openEditor(draggedEditor.editor, options);
|
||||
|
||||
// Ensure target has focus
|
||||
|
||||
@@ -17,7 +17,7 @@ import { attachProgressBarStyler } from 'vs/platform/theme/common/styler';
|
||||
import { IThemeService, registerThemingParticipant, Themable } from 'vs/platform/theme/common/themeService';
|
||||
import { editorBackground, contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { EDITOR_GROUP_HEADER_TABS_BACKGROUND, EDITOR_GROUP_HEADER_NO_TABS_BACKGROUND, EDITOR_GROUP_EMPTY_BACKGROUND, EDITOR_GROUP_FOCUSED_EMPTY_BORDER, EDITOR_GROUP_HEADER_BORDER } from 'vs/workbench/common/theme';
|
||||
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, GroupsOrder, ICloseEditorOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { IMoveEditorOptions, ICopyEditorOptions, ICloseEditorsFilter, IGroupChangeEvent, GroupChangeKind, GroupsOrder, ICloseEditorOptions, ICloseAllEditorsOptions } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { TabsTitleControl } from 'vs/workbench/browser/parts/editor/tabsTitleControl';
|
||||
import { EditorControl } from 'vs/workbench/browser/parts/editor/editorControl';
|
||||
import { IEditorProgressService } from 'vs/platform/progress/common/progress';
|
||||
@@ -441,6 +441,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
options.pinned = this._group.isPinned(activeEditor); // preserve pinned state
|
||||
options.sticky = this._group.isSticky(activeEditor); // preserve sticky state
|
||||
options.preserveFocus = true; // handle focus after editor is opened
|
||||
|
||||
const activeElement = document.activeElement;
|
||||
@@ -732,6 +733,10 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this._group.count;
|
||||
}
|
||||
|
||||
get stickyCount(): number {
|
||||
return this._group.stickyCount;
|
||||
}
|
||||
|
||||
get activeEditorPane(): IVisibleEditorPane | undefined {
|
||||
return this.editorControl ? withNullAsUndefined(this.editorControl.activeEditorPane) : undefined;
|
||||
}
|
||||
@@ -748,12 +753,16 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return this._group.isPinned(editor);
|
||||
}
|
||||
|
||||
isSticky(editorOrIndex: EditorInput | number): boolean {
|
||||
return this._group.isSticky(editorOrIndex);
|
||||
}
|
||||
|
||||
isActive(editor: EditorInput): boolean {
|
||||
return this._group.isActive(editor);
|
||||
}
|
||||
|
||||
getEditors(order: EditorsOrder): EditorInput[] {
|
||||
return this._group.getEditors(order);
|
||||
getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): EditorInput[] {
|
||||
return this._group.getEditors(order, options);
|
||||
}
|
||||
|
||||
getEditorByIndex(index: number): EditorInput | undefined {
|
||||
@@ -794,6 +803,43 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
}
|
||||
|
||||
stickEditor(candidate: EditorInput | undefined = this.activeEditor || undefined): void {
|
||||
this.doStickEditor(candidate, true);
|
||||
}
|
||||
|
||||
unstickEditor(candidate: EditorInput | undefined = this.activeEditor || undefined): void {
|
||||
this.doStickEditor(candidate, false);
|
||||
}
|
||||
|
||||
private doStickEditor(candidate: EditorInput | undefined, sticky: boolean): void {
|
||||
if (candidate && this._group.isSticky(candidate) !== sticky) {
|
||||
const oldIndexOfEditor = this.getIndexOfEditor(candidate);
|
||||
|
||||
// Update model
|
||||
const editor = sticky ? this._group.stick(candidate) : this._group.unstick(candidate);
|
||||
if (!editor) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the index of the editor changed, we need to forward this to
|
||||
// title control and also make sure to emit this as an event
|
||||
const newIndexOfEditor = this.getIndexOfEditor(editor);
|
||||
if (newIndexOfEditor !== oldIndexOfEditor) {
|
||||
this.titleAreaControl.moveEditor(editor, oldIndexOfEditor, newIndexOfEditor);
|
||||
|
||||
// Event
|
||||
this._onDidGroupChange.fire({ kind: GroupChangeKind.EDITOR_MOVE, editor });
|
||||
}
|
||||
|
||||
// Forward sticky state to title control
|
||||
if (sticky) {
|
||||
this.titleAreaControl.stickEditor(editor);
|
||||
} else {
|
||||
this.titleAreaControl.unstickEditor(editor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
invokeWithinContext<T>(fn: (accessor: ServicesAccessor) => T): T {
|
||||
return this.scopedInstantiationService.invokeFunction(fn);
|
||||
}
|
||||
@@ -833,11 +879,19 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
// Determine options
|
||||
const openEditorOptions: IEditorOpenOptions = {
|
||||
index: options ? options.index : undefined,
|
||||
pinned: !this.accessor.partOptions.enablePreview || editor.isDirty() || (options?.pinned ?? typeof options?.index === 'number'), // unless specified, prefer to pin when opening with index
|
||||
pinned: options?.sticky || !this.accessor.partOptions.enablePreview || editor.isDirty() || (options?.pinned ?? typeof options?.index === 'number' /* unless specified, prefer to pin when opening with index */) || (typeof options?.index === 'number' && this._group.isSticky(options.index)),
|
||||
sticky: options?.sticky || (typeof options?.index === 'number' && this._group.isSticky(options.index)),
|
||||
active: this._group.count === 0 || !options || !options.inactive
|
||||
};
|
||||
|
||||
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && this._group.isPreview(this._group.activeEditor)) {
|
||||
if (options?.sticky && typeof options?.index === 'number' && !this._group.isSticky(options.index)) {
|
||||
// Special case: we are to open an editor sticky but at an index that is not sticky
|
||||
// In that case we prefer to open the editor at the index but not sticky. This enables
|
||||
// to drag a sticky editor to an index that is not sticky to unstick it.
|
||||
openEditorOptions.sticky = false;
|
||||
}
|
||||
|
||||
if (!openEditorOptions.active && !openEditorOptions.pinned && this._group.activeEditor && !this._group.isPinned(this._group.activeEditor)) {
|
||||
// Special case: we are to open an editor inactive and not pinned, but the current active
|
||||
// editor is also not pinned, which means it will get replaced with this one. As such,
|
||||
// the editor can only be active.
|
||||
@@ -1095,8 +1149,11 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
// When moving an editor, try to preserve as much view state as possible by checking
|
||||
// for the editor to be a text editor and creating the options accordingly if so
|
||||
const options = getActiveTextEditorOptions(this, editor, EditorOptions.create(moveOptions));
|
||||
options.pinned = true; // always pin moved editor
|
||||
const options = getActiveTextEditorOptions(this, editor, EditorOptions.create({
|
||||
...moveOptions,
|
||||
pinned: true, // always pin moved editor
|
||||
sticky: this._group.isSticky(editor) // preserve sticky state
|
||||
}));
|
||||
|
||||
// A move to another group is an open first...
|
||||
target.openEditor(editor, options);
|
||||
@@ -1377,7 +1434,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
return;
|
||||
}
|
||||
|
||||
const editors = this.getEditorsToClose(args);
|
||||
const editors = this.doGetEditorsToClose(args);
|
||||
|
||||
// Check for dirty and veto
|
||||
const veto = await this.handleDirtyClosing(editors.slice(0));
|
||||
@@ -1389,31 +1446,31 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
this.doCloseEditors(editors, options);
|
||||
}
|
||||
|
||||
private getEditorsToClose(editors: EditorInput[] | ICloseEditorsFilter): EditorInput[] {
|
||||
if (Array.isArray(editors)) {
|
||||
return editors;
|
||||
private doGetEditorsToClose(args: EditorInput[] | ICloseEditorsFilter): EditorInput[] {
|
||||
if (Array.isArray(args)) {
|
||||
return args;
|
||||
}
|
||||
|
||||
const filter = editors;
|
||||
const filter = args;
|
||||
const hasDirection = typeof filter.direction === 'number';
|
||||
|
||||
let editorsToClose = this._group.getEditors(hasDirection ? EditorsOrder.SEQUENTIAL : EditorsOrder.MOST_RECENTLY_ACTIVE); // in MRU order only if direction is not specified
|
||||
let editorsToClose = this._group.getEditors(hasDirection ? EditorsOrder.SEQUENTIAL : EditorsOrder.MOST_RECENTLY_ACTIVE, filter); // in MRU order only if direction is not specified
|
||||
|
||||
// Filter: saved or saving only
|
||||
if (filter.savedOnly) {
|
||||
editorsToClose = editorsToClose.filter(e => !e.isDirty() || e.isSaving());
|
||||
editorsToClose = editorsToClose.filter(editor => !editor.isDirty() || editor.isSaving());
|
||||
}
|
||||
|
||||
// Filter: direction (left / right)
|
||||
else if (hasDirection && filter.except) {
|
||||
editorsToClose = (filter.direction === CloseDirection.LEFT) ?
|
||||
editorsToClose.slice(0, this._group.indexOf(filter.except)) :
|
||||
editorsToClose.slice(this._group.indexOf(filter.except) + 1);
|
||||
editorsToClose.slice(0, this._group.indexOf(filter.except, editorsToClose)) :
|
||||
editorsToClose.slice(this._group.indexOf(filter.except, editorsToClose) + 1);
|
||||
}
|
||||
|
||||
// Filter: except
|
||||
else if (filter.except) {
|
||||
editorsToClose = editorsToClose.filter(e => !e.matches(filter.except));
|
||||
editorsToClose = editorsToClose.filter(editor => !editor.matches(filter.except));
|
||||
}
|
||||
|
||||
return editorsToClose;
|
||||
@@ -1444,7 +1501,7 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
|
||||
//#region closeAllEditors()
|
||||
|
||||
async closeAllEditors(): Promise<void> {
|
||||
async closeAllEditors(options?: ICloseAllEditorsOptions): Promise<void> {
|
||||
if (this.isEmpty) {
|
||||
|
||||
// If the group is empty and the request is to close all editors, we still close
|
||||
@@ -1458,30 +1515,34 @@ export class EditorGroupView extends Themable implements IEditorGroupView {
|
||||
}
|
||||
|
||||
// Check for dirty and veto
|
||||
const editors = this._group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE);
|
||||
const veto = await this.handleDirtyClosing(editors.slice(0));
|
||||
const veto = await this.handleDirtyClosing(this._group.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, options));
|
||||
if (veto) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Do close
|
||||
this.doCloseAllEditors();
|
||||
this.doCloseAllEditors(options);
|
||||
}
|
||||
|
||||
private doCloseAllEditors(): void {
|
||||
private doCloseAllEditors(options?: ICloseAllEditorsOptions): void {
|
||||
|
||||
// Close all inactive editors first
|
||||
this.editors.forEach(editor => {
|
||||
const editorsToClose: EditorInput[] = [];
|
||||
this._group.getEditors(EditorsOrder.SEQUENTIAL, options).forEach(editor => {
|
||||
if (!this.isActive(editor)) {
|
||||
this.doCloseInactiveEditor(editor);
|
||||
}
|
||||
|
||||
editorsToClose.push(editor);
|
||||
});
|
||||
|
||||
// Close active editor last
|
||||
// Close active editor last (unless we skip it, e.g. because it is sticky)
|
||||
if (this.activeEditor && editorsToClose.includes(this.activeEditor)) {
|
||||
this.doCloseActiveEditor();
|
||||
}
|
||||
|
||||
// Forward to title control
|
||||
this.titleAreaControl.closeAllEditors();
|
||||
this.titleAreaControl.closeEditors(editorsToClose);
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -48,7 +48,7 @@ export class EditorsObserver extends Disposable {
|
||||
}
|
||||
|
||||
get editors(): IEditorIdentifier[] {
|
||||
return [...this.mostRecentEditorsMap.values()];
|
||||
return this.mostRecentEditorsMap.values();
|
||||
}
|
||||
|
||||
hasEditor(resource: URI): boolean {
|
||||
@@ -283,7 +283,7 @@ export class EditorsObserver extends Disposable {
|
||||
|
||||
// Across all editor groups
|
||||
else {
|
||||
await this.doEnsureOpenedEditorsLimit(limit, [...this.mostRecentEditorsMap.values()], exclude);
|
||||
await this.doEnsureOpenedEditorsLimit(limit, this.mostRecentEditorsMap.values(), exclude);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +302,10 @@ export class EditorsObserver extends Disposable {
|
||||
return false; // never the editor that should be excluded
|
||||
}
|
||||
|
||||
if (this.editorGroupsService.getGroup(groupId)?.isSticky(editor)) {
|
||||
return false; // never sticky editors
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
@@ -342,7 +346,7 @@ export class EditorsObserver extends Disposable {
|
||||
private serialize(): ISerializedEditorsList {
|
||||
const registry = Registry.as<IEditorInputFactoryRegistry>(Extensions.EditorInputFactories);
|
||||
|
||||
const entries = [...this.mostRecentEditorsMap.values()];
|
||||
const entries = this.mostRecentEditorsMap.values();
|
||||
const mapGroupToSerializableEditorsOfGroup = new Map<IEditorGroup, IEditorInput[]>();
|
||||
|
||||
return {
|
||||
|
||||
@@ -63,8 +63,8 @@
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-right,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off {
|
||||
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.has-icon-theme.close-button-off:not(.sticky) {
|
||||
padding-left: 5px; /* reduce padding when we show icons and are in shrinking mode and tab close button is not left (unless sticky) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit {
|
||||
@@ -82,6 +82,30 @@
|
||||
max-width: -moz-fit-content;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit.sticky,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.sticky {
|
||||
|
||||
/** Sticky tabs do not scroll in case of overflow and are always above unsticky tabs which scroll under */
|
||||
position: sticky;
|
||||
z-index: 1;
|
||||
|
||||
/** Sticky tabs are even and never grow */
|
||||
flex-basis: 0;
|
||||
flex-grow: 0;
|
||||
|
||||
/** Sticky tabs have a fixed width of 38px */
|
||||
width: 38px;
|
||||
min-width: 38px;
|
||||
max-width: 38px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-fit.sticky,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container.disable-sticky-tabs > .tab.sizing-shrink.sticky {
|
||||
|
||||
/** Disable sticky positions for sticky tabs if the available space is too little */
|
||||
position: static;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-left .action-label {
|
||||
margin-right: 4px !important;
|
||||
}
|
||||
@@ -174,6 +198,10 @@
|
||||
opacity: 0; /* when tab has the focus this shade breaks the tab border (fixes https://github.com/Microsoft/vscode/issues/57819) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sticky:not(.has-icon-theme) .monaco-icon-label {
|
||||
text-align: center; /* ensure that sticky tabs without icon have label centered */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-fit .monaco-icon-label > .monaco-icon-label-container {
|
||||
overflow: visible; /* fixes https://github.com/Microsoft/vscode/issues/20182 */
|
||||
@@ -210,8 +238,9 @@
|
||||
overflow: visible; /* ...but still show the close button on hover, focus and when dirty */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close {
|
||||
display: none; /* hide the close action bar when we are configured to hide it */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off:not(.dirty) > .tab-close,
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.sticky > .tab-close {
|
||||
display: none; /* hide the close action bar when we are configured to hide it (unless dirty, but always when sticky) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container.active > .title .tabs-container > .tab.active > .tab-close .action-label, /* always show it for active tab */
|
||||
@@ -257,8 +286,8 @@
|
||||
padding-right: 10px; /* give a little bit more room if close button is off */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off {
|
||||
padding-right: 5px; /* we need less room when sizing is shrink */
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.sizing-shrink.close-button-off:not(.sticky) {
|
||||
padding-right: 5px; /* we need less room when sizing is shrink (unless tab is sticky) */
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .editor-group-container > .title .tabs-container > .tab.close-button-off.dirty-border-top > .tab-close,
|
||||
|
||||
@@ -136,10 +136,6 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
this.ifActiveEditorChanged(() => this.redraw());
|
||||
}
|
||||
|
||||
closeAllEditors(): void {
|
||||
this.redraw();
|
||||
}
|
||||
|
||||
moveEditor(editor: IEditorInput, fromIndex: number, targetIndex: number): void {
|
||||
this.ifActiveEditorChanged(() => this.redraw());
|
||||
}
|
||||
@@ -148,6 +144,14 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
this.ifEditorIsActive(editor, () => this.redraw());
|
||||
}
|
||||
|
||||
stickEditor(editor: IEditorInput): void {
|
||||
// Sticky editors are not presented any different with tabs disabled
|
||||
}
|
||||
|
||||
unstickEditor(editor: IEditorInput): void {
|
||||
// Sticky editors are not presented any different with tabs disabled
|
||||
}
|
||||
|
||||
setActive(isActive: boolean): void {
|
||||
this.redraw();
|
||||
}
|
||||
@@ -219,7 +223,6 @@ export class NoTabsTitleControl extends TitleControl {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private ifEditorIsActive(editor: IEditorInput, fn: () => void): void {
|
||||
if (this.group.isActive(editor)) {
|
||||
fn(); // only run if editor is current active
|
||||
|
||||
@@ -27,7 +27,7 @@ import { getOrSet } from 'vs/base/common/map';
|
||||
import { IThemeService, registerThemingParticipant, IColorTheme, ICssStyleCollector, HIGH_CONTRAST } from 'vs/platform/theme/common/themeService';
|
||||
import { TAB_INACTIVE_BACKGROUND, TAB_ACTIVE_BACKGROUND, TAB_ACTIVE_FOREGROUND, TAB_INACTIVE_FOREGROUND, TAB_BORDER, EDITOR_DRAG_AND_DROP_BACKGROUND, TAB_UNFOCUSED_ACTIVE_FOREGROUND, TAB_UNFOCUSED_INACTIVE_FOREGROUND, TAB_UNFOCUSED_ACTIVE_BACKGROUND, TAB_UNFOCUSED_ACTIVE_BORDER, TAB_ACTIVE_BORDER, TAB_HOVER_BACKGROUND, TAB_HOVER_BORDER, TAB_UNFOCUSED_HOVER_BACKGROUND, TAB_UNFOCUSED_HOVER_BORDER, EDITOR_GROUP_HEADER_TABS_BACKGROUND, WORKBENCH_BACKGROUND, TAB_ACTIVE_BORDER_TOP, TAB_UNFOCUSED_ACTIVE_BORDER_TOP, TAB_ACTIVE_MODIFIED_BORDER, TAB_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_ACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_MODIFIED_BORDER, TAB_UNFOCUSED_INACTIVE_BACKGROUND, TAB_HOVER_FOREGROUND, TAB_UNFOCUSED_HOVER_FOREGROUND, EDITOR_GROUP_HEADER_TABS_BORDER } from 'vs/workbench/common/theme';
|
||||
import { activeContrastBorder, contrastBorder, editorBackground, breadcrumbsBackground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ResourcesDropHandler, fillResourceDataTransfers, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
import { ResourcesDropHandler, DraggedEditorIdentifier, DraggedEditorGroupIdentifier, DragAndDropObserver } from 'vs/workbench/browser/dnd';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
@@ -67,6 +67,11 @@ export class TabsTitleControl extends TitleControl {
|
||||
large: 10
|
||||
};
|
||||
|
||||
private static readonly TAB_SIZES = {
|
||||
sticky: 38,
|
||||
fit: 120
|
||||
};
|
||||
|
||||
private titleContainer: HTMLElement | undefined;
|
||||
private tabsAndActionsContainer: HTMLElement | undefined;
|
||||
private tabsContainer: HTMLElement | undefined;
|
||||
@@ -392,10 +397,6 @@ export class TabsTitleControl extends TitleControl {
|
||||
this.handleClosedEditors();
|
||||
}
|
||||
|
||||
closeAllEditors(): void {
|
||||
this.handleClosedEditors();
|
||||
}
|
||||
|
||||
private handleClosedEditors(): void {
|
||||
|
||||
// There are tabs to show
|
||||
@@ -453,7 +454,24 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
pinEditor(editor: IEditorInput): void {
|
||||
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel));
|
||||
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel));
|
||||
}
|
||||
|
||||
stickEditor(editor: IEditorInput): void {
|
||||
this.doHandleStickyEditorChange(editor);
|
||||
}
|
||||
|
||||
unstickEditor(editor: IEditorInput): void {
|
||||
this.doHandleStickyEditorChange(editor);
|
||||
}
|
||||
|
||||
private doHandleStickyEditorChange(editor: IEditorInput): void {
|
||||
|
||||
// Update tab
|
||||
this.withTab(editor, (editor, index, tabContainer, tabLabelWidget, tabLabel) => this.redrawTab(editor, index, tabContainer, tabLabelWidget, tabLabel));
|
||||
|
||||
// A change to the sticky state requires a layout to keep the active editor visible
|
||||
this.layout(this.dimension);
|
||||
}
|
||||
|
||||
setActive(isGroupActive: boolean): void {
|
||||
@@ -487,7 +505,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// As such we need to redraw each label
|
||||
this.forEachTab((editor, index, tabContainer, tabLabelWidget, tabLabel) => {
|
||||
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
|
||||
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
|
||||
});
|
||||
|
||||
// A change to a label requires a layout to keep the active editor visible
|
||||
@@ -745,10 +763,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
// Apply some datatransfer types to allow for dragging the element outside of the application
|
||||
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
if (resource) {
|
||||
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], e);
|
||||
}
|
||||
this.doFillResourceDataTransfers(editor, e);
|
||||
|
||||
// Fixes https://github.com/Microsoft/vscode/issues/18733
|
||||
addClass(tab, 'dragged');
|
||||
@@ -1010,7 +1025,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
private redrawTab(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
|
||||
// Label
|
||||
this.redrawLabel(editor, tabContainer, tabLabelWidget, tabLabel);
|
||||
this.redrawLabel(editor, index, tabContainer, tabLabelWidget, tabLabel);
|
||||
|
||||
// Borders / Outline
|
||||
const borderRightColor = (this.getColor(TAB_BORDER) || this.getColor(contrastBorder));
|
||||
@@ -1018,10 +1033,12 @@ export class TabsTitleControl extends TitleControl {
|
||||
tabContainer.style.outlineColor = this.getColor(activeContrastBorder) || '';
|
||||
|
||||
// Settings
|
||||
const isTabSticky = this.group.isSticky(index);
|
||||
const options = this.accessor.partOptions;
|
||||
|
||||
const tabCloseButton = isTabSticky ? 'off' /* treat sticky tabs as tabCloseButton: 'off' */ : options.tabCloseButton;
|
||||
['off', 'left', 'right'].forEach(option => {
|
||||
const domAction = options.tabCloseButton === option ? addClass : removeClass;
|
||||
const domAction = tabCloseButton === option ? addClass : removeClass;
|
||||
domAction(tabContainer, `close-button-${option}`);
|
||||
});
|
||||
|
||||
@@ -1036,13 +1053,37 @@ export class TabsTitleControl extends TitleControl {
|
||||
removeClass(tabContainer, 'has-icon-theme');
|
||||
}
|
||||
|
||||
// Sticky Tabs need a position to remain at their location
|
||||
// when scrolling to stay in view (requirement for position: sticky)
|
||||
if (isTabSticky) {
|
||||
addClass(tabContainer, 'sticky');
|
||||
tabContainer.style.left = `${index * TabsTitleControl.TAB_SIZES.sticky}px`;
|
||||
} else {
|
||||
removeClass(tabContainer, 'sticky');
|
||||
tabContainer.style.left = 'auto';
|
||||
}
|
||||
|
||||
// Active / dirty state
|
||||
this.redrawEditorActiveAndDirty(this.accessor.activeGroup === this.group, editor, tabContainer, tabLabelWidget);
|
||||
}
|
||||
|
||||
private redrawLabel(editor: IEditorInput, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
const name = tabLabel.name;
|
||||
const description = tabLabel.description || '';
|
||||
private redrawLabel(editor: IEditorInput, index: number, tabContainer: HTMLElement, tabLabelWidget: IResourceLabel, tabLabel: IEditorInputLabel): void {
|
||||
const isTabSticky = this.group.isSticky(index);
|
||||
|
||||
// Unless tabs are sticky, show the full label and description
|
||||
// Sticky tabs will only show an icon if icons are enabled
|
||||
// or their first character of the name otherwise
|
||||
let name: string | undefined;
|
||||
let description: string;
|
||||
if (isTabSticky) {
|
||||
const isShowingIcons = this.accessor.partOptions.showIcons && !!this.accessor.partOptions.iconTheme;
|
||||
name = isShowingIcons ? '' : tabLabel.name?.charAt(0).toUpperCase();
|
||||
description = '';
|
||||
} else {
|
||||
name = tabLabel.name;
|
||||
description = tabLabel.description || '';
|
||||
}
|
||||
|
||||
const title = tabLabel.title || '';
|
||||
|
||||
if (tabLabel.ariaLabel) {
|
||||
@@ -1056,7 +1097,7 @@ export class TabsTitleControl extends TitleControl {
|
||||
// Label
|
||||
tabLabelWidget.setResource(
|
||||
{ name, description, resource: toResource(editor, { supportSideBySide: SideBySideEditor.BOTH }) },
|
||||
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor) }
|
||||
{ title, extraClasses: ['tab-label'], italic: !this.group.isPinned(editor), forceLabel: isTabSticky }
|
||||
);
|
||||
|
||||
this.setEditorTabColor(editor, tabContainer, this.group.isActive(editor)); // {{SQL CARBON EDIT}} -- Display the editor's tab color
|
||||
@@ -1173,8 +1214,8 @@ export class TabsTitleControl extends TitleControl {
|
||||
layout(dimension: Dimension | undefined): void {
|
||||
this.dimension = dimension;
|
||||
|
||||
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
|
||||
if (!activeTab || !this.dimension) {
|
||||
const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined;
|
||||
if (!activeTabAndIndex || !this.dimension) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1192,20 +1233,66 @@ export class TabsTitleControl extends TitleControl {
|
||||
}
|
||||
|
||||
private doLayout(dimension: Dimension): void {
|
||||
const activeTab = this.group.activeEditor ? this.getTab(this.group.activeEditor) : undefined;
|
||||
if (!activeTab) {
|
||||
return;
|
||||
const activeTabAndIndex = this.group.activeEditor ? this.getTabAndIndex(this.group.activeEditor) : undefined;
|
||||
if (!activeTabAndIndex) {
|
||||
return; // nothing to do if not editor opened
|
||||
}
|
||||
|
||||
const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar);
|
||||
// Breadcrumbs
|
||||
this.doLayoutBreadcrumbs(dimension);
|
||||
|
||||
// Tabs
|
||||
const [activeTab, activeIndex] = activeTabAndIndex;
|
||||
this.doLayoutTabs(activeTab, activeIndex);
|
||||
}
|
||||
|
||||
private doLayoutBreadcrumbs(dimension: Dimension): void {
|
||||
if (this.breadcrumbsControl && !this.breadcrumbsControl.isHidden()) {
|
||||
const tabsScrollbar = assertIsDefined(this.tabsScrollbar);
|
||||
|
||||
this.breadcrumbsControl.layout({ width: dimension.width, height: BreadcrumbsControl.HEIGHT });
|
||||
tabsScrollbar.getDomNode().style.height = `${dimension.height - BreadcrumbsControl.HEIGHT}px`;
|
||||
}
|
||||
}
|
||||
|
||||
const visibleContainerWidth = tabsContainer.offsetWidth;
|
||||
const totalContainerWidth = tabsContainer.scrollWidth;
|
||||
private doLayoutTabs(activeTab: HTMLElement, activeIndex: number): void {
|
||||
const [tabsContainer, tabsScrollbar] = assertAllDefined(this.tabsContainer, this.tabsScrollbar);
|
||||
|
||||
//
|
||||
// Synopsis
|
||||
// - allTabsWidth: sum of all tab widths
|
||||
// - stickyTabsWidth: sum of all sticky tab widths
|
||||
// - visibleContainerWidth: size of tab container
|
||||
// - availableContainerWidth: size of tab container minus size of sticky tabs
|
||||
//
|
||||
// [------------------------------ All tabs width ---------------------------------------]
|
||||
// [------------------- Visible container width -------------------]
|
||||
// [------ Available container width ------]
|
||||
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
|
||||
// Active Tab Width [-------]
|
||||
// [------- Active Tab Pos X -------]
|
||||
// [-- Sticky Tabs Width --]
|
||||
//
|
||||
|
||||
const visibleTabsContainerWidth = tabsContainer.offsetWidth;
|
||||
const allTabsWidth = tabsContainer.scrollWidth;
|
||||
|
||||
let stickyTabsWidth = this.group.stickyCount * TabsTitleControl.TAB_SIZES.sticky;
|
||||
let activeTabSticky = this.group.isSticky(activeIndex);
|
||||
let availableTabsContainerWidth = visibleTabsContainerWidth - stickyTabsWidth;
|
||||
|
||||
// Special case: we have sticky tabs but the available space for showing tabs
|
||||
// is little enough that we need to disable sticky tabs sticky positioning
|
||||
// so that tabs can be scrolled at naturally.
|
||||
if (this.group.stickyCount > 0 && availableTabsContainerWidth < TabsTitleControl.TAB_SIZES.fit) {
|
||||
addClass(tabsContainer, 'disable-sticky-tabs');
|
||||
|
||||
availableTabsContainerWidth = visibleTabsContainerWidth;
|
||||
stickyTabsWidth = 0;
|
||||
activeTabSticky = false;
|
||||
} else {
|
||||
removeClass(tabsContainer, 'disable-sticky-tabs');
|
||||
}
|
||||
|
||||
let activeTabPosX: number | undefined;
|
||||
let activeTabWidth: number | undefined;
|
||||
@@ -1217,42 +1304,78 @@ export class TabsTitleControl extends TitleControl {
|
||||
|
||||
// Update scrollbar
|
||||
tabsScrollbar.setScrollDimensions({
|
||||
width: visibleContainerWidth,
|
||||
scrollWidth: totalContainerWidth
|
||||
width: visibleTabsContainerWidth,
|
||||
scrollWidth: allTabsWidth
|
||||
});
|
||||
|
||||
// Return now if we are blocked to reveal the active tab and clear flag
|
||||
if (this.blockRevealActiveTab || typeof activeTabPosX !== 'number' || typeof activeTabWidth !== 'number') {
|
||||
// We also return if the active tab is sticky because this means it is
|
||||
// always visible anyway.
|
||||
if (this.blockRevealActiveTab || typeof activeTabPosX !== 'number' || typeof activeTabWidth !== 'number' || activeTabSticky) {
|
||||
this.blockRevealActiveTab = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Reveal the active one
|
||||
const containerScrollPosX = tabsScrollbar.getScrollPosition().scrollLeft;
|
||||
const activeTabFits = activeTabWidth <= visibleContainerWidth;
|
||||
const tabsContainerScrollPosX = tabsScrollbar.getScrollPosition().scrollLeft;
|
||||
const activeTabFits = activeTabWidth <= availableTabsContainerWidth;
|
||||
const adjustedActiveTabPosX = activeTabPosX - stickyTabsWidth;
|
||||
|
||||
//
|
||||
// Synopsis
|
||||
// - adjustedActiveTabPosX: the adjusted tabPosX takes the width of sticky tabs into account
|
||||
// conceptually the scrolling only begins after sticky tabs so in order to reveal a tab fully
|
||||
// the actual position needs to be adjusted for sticky tabs.
|
||||
//
|
||||
// Tab is overflowing to the right: Scroll minimally until the element is fully visible to the right
|
||||
// Note: only try to do this if we actually have enough width to give to show the tab fully!
|
||||
if (activeTabFits && containerScrollPosX + visibleContainerWidth < activeTabPosX + activeTabWidth) {
|
||||
//
|
||||
// Example: Tab G should be made active and needs to be fully revealed as such.
|
||||
//
|
||||
// [-------------------------------- All tabs width -----------------------------------------]
|
||||
// [-------------------- Visible container width --------------------]
|
||||
// [----- Available container width -------]
|
||||
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
|
||||
// Active Tab Width [-------]
|
||||
// [------- Active Tab Pos X -------]
|
||||
// [-------- Adjusted Tab Pos X -------]
|
||||
// [-- Sticky Tabs Width --]
|
||||
//
|
||||
//
|
||||
if (activeTabFits && tabsContainerScrollPosX + availableTabsContainerWidth < adjustedActiveTabPosX + activeTabWidth) {
|
||||
tabsScrollbar.setScrollPosition({
|
||||
scrollLeft: containerScrollPosX + ((activeTabPosX + activeTabWidth) /* right corner of tab */ - (containerScrollPosX + visibleContainerWidth) /* right corner of view port */)
|
||||
scrollLeft: tabsContainerScrollPosX + ((adjustedActiveTabPosX + activeTabWidth) /* right corner of tab */ - (tabsContainerScrollPosX + availableTabsContainerWidth) /* right corner of view port */)
|
||||
});
|
||||
}
|
||||
|
||||
// Tab is overlflowng to the left or does not fit: Scroll it into view to the left
|
||||
else if (containerScrollPosX > activeTabPosX || !activeTabFits) {
|
||||
//
|
||||
// Tab is overlflowing to the left or does not fit: Scroll it into view to the left
|
||||
//
|
||||
// Example: Tab C should be made active and needs to be fully revealed as such.
|
||||
//
|
||||
// [----------------------------- All tabs width ----------------------------------------]
|
||||
// [------------------ Visible container width ------------------]
|
||||
// [----- Available container width -------]
|
||||
// [ Sticky A ][ Sticky B ][ Tab C ][ Tab D ][ Tab E ][ Tab F ][ Tab G ][ Tab H ][ Tab I ]
|
||||
// Active Tab Width [-------]
|
||||
// [------- Active Tab Pos X -------]
|
||||
// Adjusted Tab Pos X []
|
||||
// [-- Sticky Tabs Width --]
|
||||
//
|
||||
//
|
||||
else if (tabsContainerScrollPosX > adjustedActiveTabPosX || !activeTabFits) {
|
||||
tabsScrollbar.setScrollPosition({
|
||||
scrollLeft: activeTabPosX
|
||||
scrollLeft: adjustedActiveTabPosX
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private getTab(editor: IEditorInput): HTMLElement | undefined {
|
||||
private getTabAndIndex(editor: IEditorInput): [HTMLElement, number /* index */] | undefined {
|
||||
const editorIndex = this.group.getIndexOfEditor(editor);
|
||||
if (editorIndex >= 0) {
|
||||
const tabsContainer = assertIsDefined(this.tabsContainer);
|
||||
|
||||
return tabsContainer.children[editorIndex] as HTMLElement;
|
||||
return [tabsContainer.children[editorIndex] as HTMLElement, editorIndex];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
@@ -1494,11 +1617,11 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
|
||||
// Adjust gradient for focused and unfocused hover background
|
||||
const makeTabHoverBackgroundRule = (color: Color, colorDrag: Color, hasFocus = false) => `
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${color}, transparent) !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):hover > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${hasFocus ? '.active' : ''} > .title .tabs-container > .tab.sizing-shrink:not(.dragged):not(.sticky):hover > .tab-label::after {
|
||||
background: linear-gradient(to left, ${colorDrag}, transparent) !important;
|
||||
}
|
||||
`;
|
||||
@@ -1521,19 +1644,19 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
if (editorDragAndDropBackground && adjustedTabDragBackground) {
|
||||
const adjustedColorDrag = editorDragAndDropBackground.flatten(adjustedTabDragBackground);
|
||||
collector.addRule(`
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged) > .tab-label::after,
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container.active > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.active):not(.dragged):not(.sticky) > .tab-label::after,
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container:not(.active) > .title .tabs-container > .tab.sizing-shrink.dragged-over:not(.dragged):not(.sticky) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${adjustedColorDrag}, transparent) !important;
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
const makeTabBackgroundRule = (color: Color, colorDrag: Color, focused: boolean, active: boolean) => `
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content:not(.dragged-over) .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${color}, transparent);
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged) > .tab-label::after {
|
||||
.monaco-workbench .part.editor > .content.dragged-over .editor-group-container${focused ? '.active' : ':not(.active)'} > .title .tabs-container > .tab.sizing-shrink${active ? '.active' : ''}:not(.dragged):not(.sticky) > .tab-label::after {
|
||||
background: linear-gradient(to left, ${colorDrag}, transparent);
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -181,7 +181,12 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan
|
||||
// because we are triggering another openEditor() call
|
||||
// and do not control the initial intent that resulted
|
||||
// in us now opening as binary.
|
||||
const preservingOptions: IEditorOptions = { activation: EditorActivation.PRESERVE, pinned: this.group?.isPinned(input) };
|
||||
const preservingOptions: IEditorOptions = {
|
||||
activation: EditorActivation.PRESERVE,
|
||||
pinned: this.group?.isPinned(input),
|
||||
sticky: this.group?.isSticky(input)
|
||||
};
|
||||
|
||||
if (options) {
|
||||
options.overwrite(preservingOptions);
|
||||
} else {
|
||||
@@ -237,7 +242,7 @@ export class TextDiffEditor extends BaseTextEditor implements ITextDiffEditorPan
|
||||
if (isArray(error)) {
|
||||
const errors = <Error[]>error;
|
||||
|
||||
return errors.some(e => this.isFileBinaryError(e));
|
||||
return errors.some(error => this.isFileBinaryError(error));
|
||||
}
|
||||
|
||||
return (<TextFileOperationError>error).textFileOperationResult === TextFileOperationResult.FILE_IS_BINARY;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/titlecontrol';
|
||||
import { applyDragImage, DataTransfers } from 'vs/base/browser/dnd';
|
||||
import { addDisposableListener, Dimension, EventType } from 'vs/base/browser/dom';
|
||||
import { StandardMouseEvent } from 'vs/base/browser/mouseEvent';
|
||||
@@ -12,8 +13,7 @@ import { IAction, IRunEvent, WorkbenchActionExecutedEvent, WorkbenchActionExecut
|
||||
import * as arrays from 'vs/base/common/arrays';
|
||||
import { ResolvedKeybinding } from 'vs/base/common/keyCodes';
|
||||
import { dispose, DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import 'vs/css!./media/titlecontrol';
|
||||
import { getCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { getCodeEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { localize } from 'vs/nls';
|
||||
import { createActionViewItem, createAndFillInActionBarActions, createAndFillInContextMenuActions } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { ExecuteCommandAction, IMenu, IMenuService, MenuId } from 'vs/platform/actions/common/actions';
|
||||
@@ -32,13 +32,14 @@ import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
|
||||
import { BreadcrumbsConfig } from 'vs/workbench/browser/parts/editor/breadcrumbs';
|
||||
import { BreadcrumbsControl, IBreadcrumbsControlOptions } from 'vs/workbench/browser/parts/editor/breadcrumbsControl';
|
||||
import { EDITOR_TITLE_HEIGHT, IEditorGroupsAccessor, IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext } from 'vs/workbench/common/editor';
|
||||
import { EditorCommandsContextActionRunner, IEditorCommandsContext, IEditorInput, toResource, IEditorPartOptions, SideBySideEditor, EditorPinnedContext, EditorStickyContext } from 'vs/workbench/common/editor';
|
||||
import { ResourceContextKey } from 'vs/workbench/common/resources';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { AnchorAlignment } from 'vs/base/browser/ui/contextview/contextview';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { withNullAsUndefined, withUndefinedAsNull, assertIsDefined } from 'vs/base/common/types';
|
||||
import { isFirefox } from 'vs/base/browser/browser';
|
||||
import { ITextEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
|
||||
export interface IToolbarActions {
|
||||
primary: IAction[];
|
||||
@@ -59,6 +60,7 @@ export abstract class TitleControl extends Themable {
|
||||
|
||||
private resourceContext: ResourceContextKey;
|
||||
private editorPinnedContext: IContextKey<boolean>;
|
||||
private editorStickyContext: IContextKey<boolean>;
|
||||
|
||||
private readonly editorToolBarMenuDisposables = this._register(new DisposableStore());
|
||||
|
||||
@@ -86,6 +88,7 @@ export abstract class TitleControl extends Themable {
|
||||
|
||||
this.resourceContext = this._register(instantiationService.createInstance(ResourceContextKey));
|
||||
this.editorPinnedContext = EditorPinnedContext.bindTo(contextKeyService);
|
||||
this.editorStickyContext = EditorStickyContext.bindTo(contextKeyService);
|
||||
|
||||
this.contextMenu = this._register(this.menuService.createMenu(MenuId.EditorTitleContext, this.contextKeyService));
|
||||
|
||||
@@ -222,6 +225,7 @@ export abstract class TitleControl extends Themable {
|
||||
// Update contexts
|
||||
this.resourceContext.set(this.group.activeEditor ? withUndefinedAsNull(toResource(this.group.activeEditor, { supportSideBySide: SideBySideEditor.MASTER })) : null);
|
||||
this.editorPinnedContext.set(this.group.activeEditor ? this.group.isPinned(this.group.activeEditor) : false);
|
||||
this.editorStickyContext.set(this.group.activeEditor ? this.group.isSticky(this.group.activeEditor) : false);
|
||||
|
||||
// Editor actions require the editor control to be there, so we retrieve it via service
|
||||
const activeEditorPane = this.group.activeEditorPane;
|
||||
@@ -266,10 +270,8 @@ export abstract class TitleControl extends Themable {
|
||||
// If tabs are disabled, treat dragging as if an editor tab was dragged
|
||||
let hasDataTransfer = false;
|
||||
if (!this.accessor.partOptions.showTabs) {
|
||||
const resource = this.group.activeEditor ? toResource(this.group.activeEditor, { supportSideBySide: SideBySideEditor.MASTER }) : null;
|
||||
if (resource) {
|
||||
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], e);
|
||||
hasDataTransfer = true;
|
||||
if (this.group.activeEditor) {
|
||||
hasDataTransfer = this.doFillResourceDataTransfers(this.group.activeEditor, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,6 +297,31 @@ export abstract class TitleControl extends Themable {
|
||||
}));
|
||||
}
|
||||
|
||||
protected doFillResourceDataTransfers(editor: IEditorInput, e: DragEvent): boolean {
|
||||
const resource = toResource(editor, { supportSideBySide: SideBySideEditor.MASTER });
|
||||
if (!resource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const editorOptions: ITextEditorOptions = {
|
||||
viewState: (() => {
|
||||
if (this.group.activeEditor === editor) {
|
||||
const activeControl = this.group.activeEditorPane?.getControl();
|
||||
if (isCodeEditor(activeControl)) {
|
||||
return withNullAsUndefined(activeControl.saveViewState());
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
})(),
|
||||
sticky: this.group.isSticky(editor)
|
||||
};
|
||||
|
||||
this.instantiationService.invokeFunction(fillResourceDataTransfers, [resource], () => editorOptions, e);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected onContextMenu(editor: IEditorInput, e: Event, node: HTMLElement): void {
|
||||
|
||||
// Update contexts based on editor picked and remember previous to restore
|
||||
@@ -302,6 +329,8 @@ export abstract class TitleControl extends Themable {
|
||||
this.resourceContext.set(withUndefinedAsNull(toResource(editor, { supportSideBySide: SideBySideEditor.MASTER })));
|
||||
const currentPinnedContext = !!this.editorPinnedContext.get();
|
||||
this.editorPinnedContext.set(this.group.isPinned(editor));
|
||||
const currentStickyContext = !!this.editorStickyContext.get();
|
||||
this.editorStickyContext.set(this.group.isSticky(editor));
|
||||
|
||||
// Find target anchor
|
||||
let anchor: HTMLElement | { x: number, y: number } = node;
|
||||
@@ -325,6 +354,7 @@ export abstract class TitleControl extends Themable {
|
||||
// restore previous contexts
|
||||
this.resourceContext.set(currentResourceContext || null);
|
||||
this.editorPinnedContext.set(currentPinnedContext);
|
||||
this.editorStickyContext.set(currentStickyContext);
|
||||
|
||||
// restore focus to active group
|
||||
this.accessor.activeGroup.focus();
|
||||
@@ -351,12 +381,14 @@ export abstract class TitleControl extends Themable {
|
||||
|
||||
abstract closeEditors(editors: IEditorInput[]): void;
|
||||
|
||||
abstract closeAllEditors(): void;
|
||||
|
||||
abstract moveEditor(editor: IEditorInput, fromIndex: number, targetIndex: number): void;
|
||||
|
||||
abstract pinEditor(editor: IEditorInput): void;
|
||||
|
||||
abstract stickEditor(editor: IEditorInput): void;
|
||||
|
||||
abstract unstickEditor(editor: IEditorInput): void;
|
||||
|
||||
abstract setActive(isActive: boolean): void;
|
||||
|
||||
abstract updateEditorLabel(editor: IEditorInput): void;
|
||||
|
||||
@@ -207,7 +207,8 @@ export class PanelPart extends CompositePart<Panel> implements IPanelService {
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
if (!activePanel) {
|
||||
// Only try to open the panel if it has been created and visible
|
||||
if (!activePanel && this.element && this.layoutService.isVisible(Parts.PANEL_PART)) {
|
||||
this.doOpenPanel(panel.id);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/
|
||||
import { contrastBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { isThemeColor } from 'vs/editor/common/editorCommon';
|
||||
import { Color } from 'vs/base/common/color';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, removeClass, EventType, hide, show, removeClasses } from 'vs/base/browser/dom';
|
||||
import { addClass, EventHelper, createStyleSheet, addDisposableListener, addClasses, removeClass, EventType, hide, show, removeClasses, isAncestor } from 'vs/base/browser/dom';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
|
||||
import { Parts, IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
|
||||
@@ -35,6 +35,11 @@ import { assertIsDefined } from 'vs/base/common/types';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Command } from 'vs/editor/common/modes';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
|
||||
import { KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { ServicesAccessor } from 'vs/editor/browser/editorExtensions';
|
||||
import { RawContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
|
||||
interface IPendingStatusbarEntry {
|
||||
id: string;
|
||||
@@ -51,8 +56,11 @@ interface IStatusbarViewModelEntry {
|
||||
alignment: StatusbarAlignment;
|
||||
priority: number;
|
||||
container: HTMLElement;
|
||||
labelContainer: HTMLElement;
|
||||
}
|
||||
|
||||
const CONTEXT_STATUS_BAR_FOCUSED = new RawContextKey<boolean>('statusBarFocused', false);
|
||||
|
||||
class StatusbarViewModel extends Disposable {
|
||||
|
||||
static readonly HIDDEN_ENTRIES_KEY = 'workbench.statusbar.hidden';
|
||||
@@ -188,6 +196,40 @@ class StatusbarViewModel extends Disposable {
|
||||
return this._entries.filter(entry => entry.alignment === alignment);
|
||||
}
|
||||
|
||||
focusNextEntry(): void {
|
||||
this.focusEntry(+1, 0);
|
||||
}
|
||||
|
||||
focusPreviousEntry(): void {
|
||||
this.focusEntry(-1, this.entries.length - 1);
|
||||
}
|
||||
|
||||
private focusEntry(delta: number, restartPosition: number): void {
|
||||
const getVisibleEntry = (start: number) => {
|
||||
let indexToFocus = start;
|
||||
let entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
|
||||
while (entry && this.isHidden(entry.id)) {
|
||||
indexToFocus += delta;
|
||||
entry = (indexToFocus >= 0 && indexToFocus < this._entries.length) ? this._entries[indexToFocus] : undefined;
|
||||
}
|
||||
return entry;
|
||||
};
|
||||
|
||||
const focused = this._entries.find(entry => isAncestor(document.activeElement, entry.container));
|
||||
if (focused) {
|
||||
const entry = getVisibleEntry(this._entries.indexOf(focused) + delta);
|
||||
if (entry) {
|
||||
entry.labelContainer.focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const entry = getVisibleEntry(restartPosition);
|
||||
if (entry) {
|
||||
entry.labelContainer.focus();
|
||||
}
|
||||
}
|
||||
|
||||
private updateVisibility(id: string, trigger: boolean): void;
|
||||
private updateVisibility(entry: IStatusbarViewModelEntry, trigger: boolean): void;
|
||||
private updateVisibility(arg1: string | IStatusbarViewModelEntry, trigger: boolean): void {
|
||||
@@ -355,6 +397,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
|
||||
@IContextMenuService private contextMenuService: IContextMenuService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
|
||||
) {
|
||||
super(Parts.STATUSBAR_PART, { hasTitle: false }, themeService, storageService, layoutService);
|
||||
@@ -415,7 +458,7 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
this.appendOneStatusbarEntry(itemContainer, alignment, priority);
|
||||
|
||||
// Add to view model
|
||||
const viewModelEntry: IStatusbarViewModelEntry = { id, name, alignment, priority, container: itemContainer };
|
||||
const viewModelEntry: IStatusbarViewModelEntry = { id, name, alignment, priority, container: itemContainer, labelContainer: item.labelContainer };
|
||||
const viewModelEntryDispose = this.viewModel.add(viewModelEntry);
|
||||
|
||||
return {
|
||||
@@ -442,9 +485,21 @@ export class StatusbarPart extends Part implements IStatusbarService {
|
||||
}
|
||||
}
|
||||
|
||||
focusNextEntry(): void {
|
||||
this.viewModel.focusNextEntry();
|
||||
}
|
||||
|
||||
focusPreviousEntry(): void {
|
||||
this.viewModel.focusPreviousEntry();
|
||||
}
|
||||
|
||||
createContentArea(parent: HTMLElement): HTMLElement {
|
||||
this.element = parent;
|
||||
|
||||
// Track focus within container
|
||||
const scopedContextKeyService = this.contextKeyService.createScoped(this.element);
|
||||
CONTEXT_STATUS_BAR_FOCUSED.bindTo(scopedContextKeyService).set(true);
|
||||
|
||||
// Left items container
|
||||
this.leftItemsContainer = document.createElement('div');
|
||||
addClasses(this.leftItemsContainer, 'left-items', 'items-container');
|
||||
@@ -645,13 +700,14 @@ class StatusbarEntryItem extends Disposable {
|
||||
|
||||
private entry!: IStatusbarEntry;
|
||||
|
||||
private labelContainer!: HTMLElement;
|
||||
labelContainer!: HTMLElement;
|
||||
private label!: CodiconLabel;
|
||||
|
||||
private readonly foregroundListener = this._register(new MutableDisposable());
|
||||
private readonly backgroundListener = this._register(new MutableDisposable());
|
||||
|
||||
private readonly commandListener = this._register(new MutableDisposable());
|
||||
private readonly commandMouseListener = this._register(new MutableDisposable());
|
||||
private readonly commandKeyboardListener = this._register(new MutableDisposable());
|
||||
|
||||
constructor(
|
||||
private container: HTMLElement,
|
||||
@@ -711,11 +767,18 @@ class StatusbarEntryItem extends Disposable {
|
||||
|
||||
// Update: Command
|
||||
if (!this.entry || entry.command !== this.entry.command) {
|
||||
this.commandListener.clear();
|
||||
this.commandMouseListener.clear();
|
||||
this.commandKeyboardListener.clear();
|
||||
|
||||
const command = entry.command;
|
||||
if (command) {
|
||||
this.commandListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command));
|
||||
this.commandMouseListener.value = addDisposableListener(this.labelContainer, EventType.CLICK, () => this.executeCommand(command));
|
||||
this.commandKeyboardListener.value = addDisposableListener(this.labelContainer, EventType.KEY_UP, e => {
|
||||
const event = new StandardKeyboardEvent(e);
|
||||
if (event.equals(KeyCode.Space) || event.equals(KeyCode.Enter)) {
|
||||
this.executeCommand(command);
|
||||
}
|
||||
});
|
||||
|
||||
removeClass(this.labelContainer, 'disabled');
|
||||
} else {
|
||||
@@ -814,7 +877,8 @@ class StatusbarEntryItem extends Disposable {
|
||||
|
||||
dispose(this.foregroundListener);
|
||||
dispose(this.backgroundListener);
|
||||
dispose(this.commandListener);
|
||||
dispose(this.commandMouseListener);
|
||||
dispose(this.commandKeyboardListener);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,6 +886,7 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
const statusBarItemHoverBackground = theme.getColor(STATUS_BAR_ITEM_HOVER_BACKGROUND);
|
||||
if (statusBarItemHoverBackground) {
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:hover { background-color: ${statusBarItemHoverBackground}; }`);
|
||||
collector.addRule(`.monaco-workbench .part.statusbar > .items-container > .statusbar-item a:focus { background-color: ${statusBarItemHoverBackground}; }`);
|
||||
}
|
||||
|
||||
const statusBarItemActiveBackground = theme.getColor(STATUS_BAR_ITEM_ACTIVE_BACKGROUND);
|
||||
@@ -846,3 +911,27 @@ registerThemingParticipant((theme: IColorTheme, collector: ICssStyleCollector) =
|
||||
});
|
||||
|
||||
registerSingleton(IStatusbarService, StatusbarPart);
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.statusBar.focusPrevious',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.LeftArrow,
|
||||
secondary: [KeyCode.UpArrow],
|
||||
when: CONTEXT_STATUS_BAR_FOCUSED,
|
||||
handler: (accessor: ServicesAccessor) => {
|
||||
const statusBarService = accessor.get(IStatusbarService);
|
||||
statusBarService.focusPreviousEntry();
|
||||
}
|
||||
});
|
||||
|
||||
KeybindingsRegistry.registerCommandAndKeybindingRule({
|
||||
id: 'workbench.statusBar.focusNext',
|
||||
weight: KeybindingWeight.WorkbenchContrib,
|
||||
primary: KeyCode.RightArrow,
|
||||
secondary: [KeyCode.DownArrow],
|
||||
when: CONTEXT_STATUS_BAR_FOCUSED,
|
||||
handler: (accessor: ServicesAccessor) => {
|
||||
const statusBarService = accessor.get(IStatusbarService);
|
||||
statusBarService.focusNextEntry();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -934,17 +934,21 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
getContextMenuActions(viewDescriptor?: IViewDescriptor): IAction[] {
|
||||
const result: IAction[] = [];
|
||||
|
||||
let showHide = true;
|
||||
if (!viewDescriptor && this.isViewMergedWithContainer()) {
|
||||
viewDescriptor = this.viewDescriptorService.getViewDescriptorById(this.panes[0].id) || undefined;
|
||||
showHide = false;
|
||||
}
|
||||
|
||||
if (viewDescriptor) {
|
||||
if (showHide) {
|
||||
result.push(<IAction>{
|
||||
id: `${viewDescriptor.id}.removeView`,
|
||||
label: nls.localize('hideView', "Hide"),
|
||||
enabled: viewDescriptor.canToggleVisibility,
|
||||
run: () => this.toggleViewVisibility(viewDescriptor!.id)
|
||||
});
|
||||
}
|
||||
const view = this.getView(viewDescriptor.id);
|
||||
if (view) {
|
||||
result.push(...view.getContextMenuActions());
|
||||
@@ -955,7 +959,7 @@ export class ViewPaneContainer extends Component implements IViewPaneContainer {
|
||||
id: `${viewDescriptor.id}.toggleVisibility`,
|
||||
label: viewDescriptor.name,
|
||||
checked: this.viewContainerModel.isVisible(viewDescriptor.id),
|
||||
enabled: viewDescriptor.canToggleVisibility,
|
||||
enabled: viewDescriptor.canToggleVisibility && (!this.viewContainerModel.isVisible(viewDescriptor.id) || this.viewContainerModel.visibleViewDescriptors.length > 1),
|
||||
run: () => this.toggleViewVisibility(viewDescriptor.id)
|
||||
}));
|
||||
|
||||
|
||||
@@ -127,15 +127,10 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
this.deregisterViewletOrPanel(container, location);
|
||||
}
|
||||
for (const { container, location } of added) {
|
||||
this.registerViewletOrPanel(container, location);
|
||||
this.onDidRegisterViewContainer(container, location);
|
||||
}
|
||||
}
|
||||
|
||||
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
|
||||
this.deregisterViewletOrPanel(viewContainer, from);
|
||||
this.registerViewletOrPanel(viewContainer, to);
|
||||
}
|
||||
|
||||
private onDidRegisterViewContainer(viewContainer: ViewContainer, viewContainerLocation: ViewContainerLocation): void {
|
||||
this.registerViewletOrPanel(viewContainer, viewContainerLocation);
|
||||
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
|
||||
@@ -146,6 +141,11 @@ export class ViewsService extends Disposable implements IViewsService {
|
||||
}));
|
||||
}
|
||||
|
||||
private onDidChangeContainerLocation(viewContainer: ViewContainer, from: ViewContainerLocation, to: ViewContainerLocation): void {
|
||||
this.deregisterViewletOrPanel(viewContainer, from);
|
||||
this.registerViewletOrPanel(viewContainer, to);
|
||||
}
|
||||
|
||||
private onViewDescriptorsAdded(views: ReadonlyArray<IViewDescriptor>, container: ViewContainer): void {
|
||||
const location = this.viewDescriptorService.getViewContainerLocation(container);
|
||||
if (location === null) {
|
||||
|
||||
@@ -71,7 +71,7 @@ class BrowserMain extends Disposable {
|
||||
services.storageService.store(Settings.WORKSPACE_FIRST_OPEN, !(firstOpen ?? false), StorageScope.WORKSPACE);
|
||||
}
|
||||
|
||||
{ await domContentLoaded(); }
|
||||
await domContentLoaded();
|
||||
mark('willStartWorkbench');
|
||||
|
||||
// Base Theme
|
||||
@@ -272,7 +272,7 @@ class BrowserMain extends Disposable {
|
||||
if (!this.configuration.userDataProvider) {
|
||||
const remoteUserDataUri = this.getRemoteUserDataUri();
|
||||
if (remoteUserDataUri) {
|
||||
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService));
|
||||
this.configuration.userDataProvider = this._register(new FileUserDataProvider(remoteUserDataUri, joinPath(remoteUserDataUri, BACKUPS), remoteFileSystemProvider, environmentService, logService));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,12 +108,12 @@ import { workbenchConfigurationNodeBase } from 'vs/workbench/common/configuratio
|
||||
},
|
||||
'workbench.editor.enablePreview': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enablePreview', "Controls whether opened editors show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing) and show up with an italic font style."),
|
||||
'description': nls.localize('enablePreview', "Controls whether opened editors show as preview. Preview editors are reused until they are explicitly set to be kept open (e.g. via double click or editing) and show up with an italic font style."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.enablePreviewFromQuickOpen': {
|
||||
'type': 'boolean',
|
||||
'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors are reused until they are pinned (e.g. via double click or editing)."),
|
||||
'description': nls.localize('enablePreviewFromQuickOpen', "Controls whether editors opened from Quick Open show as preview. Preview editors are reused until they are explicitly set to be kept open (e.g. via double click or editing)."),
|
||||
'default': true
|
||||
},
|
||||
'workbench.editor.closeOnFileDelete': {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user