Merge remote-tracking branch 'origin/master' into tyriar/r136_windows_remote_links
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "code-oss-dev",
|
||||
"version": "1.36.0",
|
||||
"distro": "5fc996cf23a90ee6ea8d55df47948fcccfd7b613",
|
||||
"distro": "0293a04fc4ec308a7770025ead5660e2fb9667a9",
|
||||
"author": {
|
||||
"name": "Microsoft Corporation"
|
||||
},
|
||||
|
|
|
@ -206,6 +206,11 @@ export interface IFileDialogService {
|
|||
*/
|
||||
pickWorkspaceAndOpen(options: IPickAndOpenOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Shows a save file file dialog and save the file at the chosen file URI.
|
||||
*/
|
||||
pickFileToSave(options: ISaveDialogOptions): Promise<URI | undefined>;
|
||||
|
||||
/**
|
||||
* Shows a save file dialog and returns the chosen file URI.
|
||||
*/
|
||||
|
|
|
@ -54,6 +54,24 @@ export class OpenLocalFileAction extends Action {
|
|||
}
|
||||
}
|
||||
|
||||
export class SaveLocalFileAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.files.saveLocalFile';
|
||||
static LABEL = nls.localize('saveLocalFile', "Save Local File...");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IFileDialogService private readonly dialogService: IFileDialogService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
run(event?: any, data?: ITelemetryData): Promise<any> {
|
||||
return this.dialogService.pickFileToSave({ availableFileSystems: [Schemas.file] });
|
||||
}
|
||||
}
|
||||
|
||||
export class OpenFolderAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.action.files.openFolder';
|
||||
|
|
|
@ -700,8 +700,7 @@ body[data-exploration="icon-exploration"] .extensions-viewlet > .extensions .ext
|
|||
Panels
|
||||
****************/
|
||||
|
||||
body[data-exploration="icon-exploration"] .monaco-workbench .hide-panel-action,
|
||||
.hc-black .monaco-workbench .hide-panel-action {
|
||||
body[data-exploration="icon-exploration"] .monaco-workbench .hide-panel-action {
|
||||
-webkit-mask-image: url("images/panel/close-alt1.svg");
|
||||
}
|
||||
|
||||
|
@ -947,7 +946,7 @@ body[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.operato
|
|||
background-color: var(--blue);
|
||||
}
|
||||
|
||||
ody[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.type-parameter::before {
|
||||
body[data-exploration="icon-exploration"] .monaco-workbench .symbol-icon.type-parameter::before {
|
||||
-webkit-mask-image: url("images/intellisense/parameter-alt1.svg");
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
|
|||
import { DebugEditorModelManager } from 'vs/workbench/contrib/debug/browser/debugEditorModelManager';
|
||||
import { StartAction, AddFunctionBreakpointAction, ConfigureAction, DisableAllBreakpointsAction, EnableAllBreakpointsAction, RemoveAllBreakpointsAction, RunAction, ReapplyBreakpointsAction, SelectAndStartAction } from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { DebugToolBar } from 'vs/workbench/contrib/debug/browser/debugToolBar';
|
||||
import * as service from 'vs/workbench/contrib/debug/electron-browser/debugService';
|
||||
import * as service from 'vs/workbench/contrib/debug/browser/debugService';
|
||||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { registerCommands, ADD_CONFIGURATION_ID, TOGGLE_INLINE_BREAKPOINT_ID, COPY_STACK_TRACE_ID, REVERSE_CONTINUE_ID, STEP_BACK_ID, RESTART_SESSION_ID, TERMINATE_THREAD_ID, STEP_OVER_ID, STEP_INTO_ID, STEP_OUT_ID, PAUSE_ID, DISCONNECT_ID, STOP_ID, RESTART_FRAME_ID, CONTINUE_ID, FOCUS_REPL_ID, JUMP_TO_CURSOR_ID } from 'vs/workbench/contrib/debug/browser/debugCommands';
|
||||
import { IQuickOpenRegistry, Extensions as QuickOpenExtensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
|
||||
|
@ -249,6 +249,11 @@ configurationRegistry.registerConfiguration({
|
|||
description: nls.localize('debug.console.lineHeight', "Controls the line height in pixels in the debug console. Use 0 to compute the line height from the font size."),
|
||||
default: 0
|
||||
},
|
||||
'debug.console.wordWrap': {
|
||||
type: 'boolean',
|
||||
description: nls.localize('debug.console.wordWrap', "Controls if the lines should wrap in the debug console."),
|
||||
default: true
|
||||
},
|
||||
'launch': {
|
||||
type: 'object',
|
||||
description: nls.localize({ comment: ['This is the description for a setting'], key: 'launch' }, "Global debug launch configuration. Should be used as an alternative to 'launch.json' that is shared across workspaces."),
|
|
@ -21,13 +21,12 @@ import { IFileService } from 'vs/platform/files/common/files';
|
|||
import { IWorkspaceContextService, IWorkspaceFolder, WorkbenchState } from 'vs/platform/workspace/common/workspace';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IDebugService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/node/debugger';
|
||||
import { IDebugConfigurationProvider, ICompound, IDebugConfiguration, IConfig, IGlobalConfig, IConfigurationManager, ILaunch, IDebugAdapterDescriptorFactory, IDebugAdapter, ITerminalSettings, ITerminalLauncher, IDebugSession, IAdapterDescriptor, CONTEXT_DEBUG_CONFIGURATION_TYPE, IDebugAdapterFactory, IDebugService, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
|
||||
import { IEditorService, ACTIVE_GROUP, SIDE_GROUP } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { isCodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
import { launchSchemaId } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { TerminalLauncher } from 'vs/workbench/contrib/debug/electron-browser/terminalSupport';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { launchSchema, debuggersExtPoint, breakpointsExtPoint } from 'vs/workbench/contrib/debug/common/debugSchemas';
|
||||
|
@ -67,7 +66,8 @@ export class ConfigurationManager implements IConfigurationManager {
|
|||
@IStorageService private readonly storageService: IStorageService,
|
||||
@ILifecycleService lifecycleService: ILifecycleService,
|
||||
@IExtensionService private readonly extensionService: IExtensionService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IDebugHelperService private readonly debugHelperService: IDebugHelperService
|
||||
) {
|
||||
this.configProviders = [];
|
||||
this.adapterDescriptorFactories = [];
|
||||
|
@ -114,7 +114,7 @@ export class ConfigurationManager implements IConfigurationManager {
|
|||
let tl: ITerminalLauncher | undefined = this.debugAdapterFactories.get(debugType);
|
||||
if (!tl) {
|
||||
if (!this.terminalLauncher) {
|
||||
this.terminalLauncher = this.instantiationService.createInstance(TerminalLauncher);
|
||||
this.terminalLauncher = this.debugHelperService.createTerminalLauncher(this.instantiationService);
|
||||
}
|
||||
tl = this.terminalLauncher;
|
||||
}
|
29
src/vs/workbench/contrib/debug/browser/debugHelperService.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { ServiceIdentifier, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ITerminalLauncher, IDebugHelperService, ILaunchVSCodeArguments } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
|
||||
export class BrowserDebugHelperService implements IDebugHelperService {
|
||||
|
||||
_serviceBrand: ServiceIdentifier<IDebugHelperService>;
|
||||
|
||||
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher {
|
||||
throw new Error('Method createTerminalLauncher not implemented.');
|
||||
}
|
||||
|
||||
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
|
||||
throw new Error('Method launchVsCode not implemented.');
|
||||
}
|
||||
|
||||
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IDebugHelperService, BrowserDebugHelperService);
|
|
@ -21,7 +21,7 @@ import { IStorageService, StorageScope } from 'vs/platform/storage/common/storag
|
|||
import { DebugModel, ExceptionBreakpoint, FunctionBreakpoint, Breakpoint, Expression } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { ViewModel } from 'vs/workbench/contrib/debug/common/debugViewModel';
|
||||
import * as debugactions from 'vs/workbench/contrib/debug/browser/debugActions';
|
||||
import { ConfigurationManager } from 'vs/workbench/contrib/debug/electron-browser/debugConfigurationManager';
|
||||
import { ConfigurationManager } from 'vs/workbench/contrib/debug/browser/debugConfigurationManager';
|
||||
import Constants from 'vs/workbench/contrib/markers/browser/constants';
|
||||
import { ITaskService, ITaskSummary } from 'vs/workbench/contrib/tasks/common/taskService';
|
||||
import { TaskError } from 'vs/workbench/contrib/tasks/common/taskSystem';
|
||||
|
@ -39,7 +39,7 @@ import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
|||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IAction, Action } from 'vs/base/common/actions';
|
||||
import { deepClone, equals } from 'vs/base/common/objects';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/electron-browser/debugSession';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
|
||||
import { dispose, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IDebugService, State, IDebugSession, CONTEXT_DEBUG_TYPE, CONTEXT_DEBUG_STATE, CONTEXT_IN_DEBUG_MODE, IThread, IDebugConfiguration, VIEWLET_ID, REPL_ID, IConfig, ILaunch, IViewModel, IConfigurationManager, IDebugModel, IEnablement, IBreakpoint, IBreakpointData, ICompound, IGlobalConfig, IStackFrame, AdapterEndEvent, getStateLabel } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { isExtensionHostDebugging } from 'vs/workbench/contrib/debug/common/debugUtils';
|
|
@ -12,12 +12,12 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||
import { CompletionItem, completionKindFromString } from 'vs/editor/common/modes';
|
||||
import { Position } from 'vs/editor/common/core/position';
|
||||
import * as aria from 'vs/base/browser/ui/aria/aria';
|
||||
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IDebugSession, IConfig, IThread, IRawModelUpdate, IDebugService, IRawStoppedDetails, State, LoadedSourceEvent, IFunctionBreakpoint, IExceptionBreakpoint, IBreakpoint, IExceptionInfo, AdapterEndEvent, IDebugger, VIEWLET_ID, IDebugConfiguration, IReplElement, IStackFrame, IExpression, IReplElementSource, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { mixin } from 'vs/base/common/objects';
|
||||
import { Thread, ExpressionContainer, DebugModel } from 'vs/workbench/contrib/debug/common/debugModel';
|
||||
import { RawDebugSession } from 'vs/workbench/contrib/debug/electron-browser/rawDebugSession';
|
||||
import product from 'vs/platform/product/node/product';
|
||||
import { RawDebugSession } from 'vs/workbench/contrib/debug/browser/rawDebugSession';
|
||||
import { IProductService } from 'vs/platform/product/common/product';
|
||||
import { IWorkspaceFolder, IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
||||
import { RunOnceScheduler } from 'vs/base/common/async';
|
||||
|
@ -30,7 +30,6 @@ import { IConfigurationService } from 'vs/platform/configuration/common/configur
|
|||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
|
||||
|
@ -66,9 +65,10 @@ export class DebugSession implements IDebugSession {
|
|||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@ISignService private readonly signService: ISignService
|
||||
@ISignService private readonly signService: ISignService,
|
||||
@IProductService private readonly productService: IProductService,
|
||||
@IDebugHelperService private readonly debugUIService: IDebugHelperService
|
||||
) {
|
||||
this.id = generateUuid();
|
||||
this.repl = new ReplModel(this);
|
||||
|
@ -169,7 +169,7 @@ export class DebugSession implements IDebugSession {
|
|||
|
||||
return dbgr.createDebugAdapter(this).then(debugAdapter => {
|
||||
|
||||
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.environmentService, this.signService);
|
||||
this.raw = new RawDebugSession(debugAdapter, dbgr, this.telemetryService, customTelemetryService, this.signService, this.debugUIService);
|
||||
|
||||
return this.raw!.start().then(() => {
|
||||
|
||||
|
@ -177,7 +177,7 @@ export class DebugSession implements IDebugSession {
|
|||
|
||||
return this.raw!.initialize({
|
||||
clientID: 'vscode',
|
||||
clientName: product.nameLong,
|
||||
clientName: this.productService.nameLong,
|
||||
adapterID: this.configuration.type,
|
||||
pathFormat: 'path',
|
||||
linesStartAt1: true,
|
Before Width: | Height: | Size: 339 B After Width: | Height: | Size: 339 B |
Before Width: | Height: | Size: 363 B After Width: | Height: | Size: 363 B |
Before Width: | Height: | Size: 217 B After Width: | Height: | Size: 217 B |
Before Width: | Height: | Size: 701 B After Width: | Height: | Size: 701 B |
Before Width: | Height: | Size: 418 B After Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 411 B After Width: | Height: | Size: 411 B |
Before Width: | Height: | Size: 548 B After Width: | Height: | Size: 548 B |
Before Width: | Height: | Size: 197 B After Width: | Height: | Size: 197 B |
|
@ -9,28 +9,11 @@ import * as objects from 'vs/base/common/objects';
|
|||
import { Action } from 'vs/base/common/actions';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { formatPII, isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { formatPII } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import { IDebugAdapter, IConfig, AdapterEndEvent, IDebugger, IDebugHelperService, ILaunchVSCodeArguments } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
|
||||
import * as cp from 'child_process';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { ISignService } from 'vs/platform/sign/common/sign';
|
||||
|
||||
/**
|
||||
* This interface represents a single command line argument split into a "prefix" and a "path" half.
|
||||
* The optional "prefix" contains arbitrary text and the optional "path" contains a file system path.
|
||||
* Concatenating both results in the original command line argument.
|
||||
*/
|
||||
export interface ILaunchVSCodeArgument {
|
||||
prefix?: string;
|
||||
path?: string;
|
||||
}
|
||||
|
||||
export interface ILaunchVSCodeArguments {
|
||||
args: ILaunchVSCodeArgument[];
|
||||
env?: { [key: string]: string | null; };
|
||||
}
|
||||
|
||||
/**
|
||||
* Encapsulates the DebugAdapter lifecycle and some idiosyncrasies of the Debug Adapter Protocol.
|
||||
*/
|
||||
|
@ -72,8 +55,8 @@ export class RawDebugSession {
|
|||
dbgr: IDebugger,
|
||||
private readonly telemetryService: ITelemetryService,
|
||||
public readonly customTelemetryService: ITelemetryService | undefined,
|
||||
private readonly environmentService: IEnvironmentService,
|
||||
private readonly signService: ISignService
|
||||
private readonly signService: ISignService,
|
||||
private readonly debugUIService: IDebugHelperService
|
||||
) {
|
||||
this.debugAdapter = debugAdapter;
|
||||
this._capabilities = Object.create(null);
|
||||
|
@ -520,7 +503,7 @@ export class RawDebugSession {
|
|||
|
||||
switch (request.command) {
|
||||
case 'launchVSCode':
|
||||
this.launchVsCode(<ILaunchVSCodeArguments>request.arguments).then(pid => {
|
||||
this.debugUIService.launchVsCode(<ILaunchVSCodeArguments>request.arguments).then(pid => {
|
||||
response.body = {
|
||||
processId: pid
|
||||
};
|
||||
|
@ -566,82 +549,6 @@ export class RawDebugSession {
|
|||
}
|
||||
}
|
||||
|
||||
private launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
|
||||
|
||||
const spawnOpts: cp.SpawnOptions = {
|
||||
detached: false // https://github.com/Microsoft/vscode/issues/57018
|
||||
};
|
||||
|
||||
if (vscodeArgs.env) {
|
||||
// merge environment variables into a copy of the process.env
|
||||
const envArgs = objects.mixin(objects.mixin({}, process.env), vscodeArgs.env);
|
||||
// and delete some if necessary
|
||||
Object.keys(envArgs).filter(k => envArgs[k] === null).forEach(key => delete envArgs[key]);
|
||||
spawnOpts.env = envArgs;
|
||||
}
|
||||
|
||||
let spawnArgs = vscodeArgs.args.map(a => {
|
||||
if ((a.prefix === '--file-uri=' || a.prefix === '--folder-uri=') && !isUri(a.path)) {
|
||||
return (a.path || '');
|
||||
}
|
||||
return (a.prefix || '') + (a.path || '');
|
||||
});
|
||||
|
||||
let runtimeExecutable = this.environmentService['execPath'];
|
||||
if (!runtimeExecutable) {
|
||||
return Promise.reject(new Error(`VS Code executable unknown`));
|
||||
}
|
||||
|
||||
// if VS Code runs out of sources, add the VS Code workspace path as the first argument so that Electron turns into VS Code
|
||||
const electronIdx = runtimeExecutable.indexOf(process.platform === 'win32' ? '\\.build\\electron\\' : '/.build/electron/');
|
||||
if (electronIdx > 0) {
|
||||
// guess the VS Code workspace path from the executable
|
||||
const vscodeWorkspacePath = runtimeExecutable.substr(0, electronIdx);
|
||||
|
||||
// only add VS Code workspace path if user hasn't already added that path as a (folder) argument
|
||||
const x = spawnArgs.filter(a => a.indexOf(vscodeWorkspacePath) === 0);
|
||||
if (x.length === 0) {
|
||||
spawnArgs.unshift(vscodeWorkspacePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for bug Microsoft/vscode#45832
|
||||
if (process.platform === 'win32' && runtimeExecutable.indexOf(' ') > 0) {
|
||||
let foundArgWithSpace = false;
|
||||
|
||||
// check whether there is one arg with a space
|
||||
const args: string[] = [];
|
||||
for (const a of spawnArgs) {
|
||||
if (a.indexOf(' ') > 0) {
|
||||
args.push(`"${a}"`);
|
||||
foundArgWithSpace = true;
|
||||
} else {
|
||||
args.push(a);
|
||||
}
|
||||
}
|
||||
|
||||
if (foundArgWithSpace) {
|
||||
spawnArgs = args;
|
||||
runtimeExecutable = `"${runtimeExecutable}"`;
|
||||
spawnOpts.shell = true;
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const process = cp.spawn(runtimeExecutable, spawnArgs, spawnOpts);
|
||||
process.on('error', error => {
|
||||
reject(error);
|
||||
});
|
||||
process.on('exit', code => {
|
||||
if (code === 0) {
|
||||
resolve(process.pid);
|
||||
} else {
|
||||
reject(new Error(`VS Code exited with ${code}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private send<R extends DebugProtocol.Response>(command: string, args: any, timeout?: number): Promise<R> {
|
||||
return new Promise<R>((completeDispatch, errorDispatch) => {
|
||||
if (!this.debugAdapter) {
|
|
@ -375,6 +375,7 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
|
|||
this.createReplInput(this.container);
|
||||
|
||||
this.replDelegate = new ReplDelegate(this.configurationService);
|
||||
const wordWrap = this.configurationService.getValue<IDebugConfiguration>('debug').console.wordWrap;
|
||||
this.tree = this.instantiationService.createInstance(WorkbenchAsyncDataTree, treeContainer, this.replDelegate, [
|
||||
this.instantiationService.createInstance(VariablesRenderer),
|
||||
this.instantiationService.createInstance(ReplSimpleElementsRenderer),
|
||||
|
@ -386,11 +387,10 @@ export class Repl extends Panel implements IPrivateReplService, IHistoryNavigati
|
|||
identityProvider: { getId: (element: IReplElement) => element.getId() },
|
||||
mouseSupport: false,
|
||||
keyboardNavigationLabelProvider: { getKeyboardNavigationLabel: (e: IReplElement) => e },
|
||||
horizontalScrolling: false,
|
||||
horizontalScrolling: !wordWrap,
|
||||
setRowLineHeight: false,
|
||||
supportDynamicHeights: true
|
||||
supportDynamicHeights: wordWrap
|
||||
}) as WorkbenchAsyncDataTree<IDebugSession, IReplElement, FuzzyScore>;
|
||||
|
||||
this._register(this.tree.onContextMenu(e => this.onContextMenu(e)));
|
||||
let lastSelectedString: string;
|
||||
this._register(this.tree.onMouseClick(() => {
|
||||
|
@ -742,8 +742,13 @@ class ReplDelegate implements IListVirtualDelegate<IReplElement> {
|
|||
const countNumberOfLines = (str: string) => Math.max(1, (str.match(/\r\n|\n/g) || []).length);
|
||||
|
||||
// Give approximate heights. Repl has dynamic height so the tree will measure the actual height on its own.
|
||||
const fontSize = this.configurationService.getValue<IDebugConfiguration>('debug').console.fontSize;
|
||||
const config = this.configurationService.getValue<IDebugConfiguration>('debug');
|
||||
const fontSize = config.console.fontSize;
|
||||
const rowHeight = Math.ceil(1.4 * fontSize);
|
||||
const wordWrap = config.console.wordWrap;
|
||||
if (!wordWrap) {
|
||||
return element instanceof Expression ? 2 * rowHeight : rowHeight;
|
||||
}
|
||||
|
||||
// In order to keep scroll position we need to give a good approximation to the tree
|
||||
// For every 150 characters increase the number of lines needed
|
||||
|
|
|
@ -8,7 +8,7 @@ import { URI as uri } from 'vs/base/common/uri';
|
|||
import severity from 'vs/base/common/severity';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { createDecorator, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IEditorContribution } from 'vs/editor/common/editorCommon';
|
||||
import { ITextModel as EditorIModel } from 'vs/editor/common/model';
|
||||
import { IEditor, ITextEditor } from 'vs/workbench/common/editor';
|
||||
|
@ -25,6 +25,7 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { TaskIdentifier } from 'vs/workbench/contrib/tasks/common/tasks';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { ITerminalConfiguration } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
|
||||
export const VIEWLET_ID = 'workbench.view.debug';
|
||||
export const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewContainerExtensions.ViewContainersRegistry).registerViewContainer(VIEWLET_ID);
|
||||
|
@ -437,6 +438,7 @@ export interface IDebugConfiguration {
|
|||
fontSize: number;
|
||||
fontFamily: string;
|
||||
lineHeight: number;
|
||||
wordWrap: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -834,3 +836,33 @@ export interface IDebugEditorContribution extends IEditorContribution {
|
|||
closeBreakpointWidget(): void;
|
||||
addLaunchConfiguration(): Promise<any>;
|
||||
}
|
||||
|
||||
// temporary debug helper service
|
||||
|
||||
export const DEBUG_HELPER_SERVICE_ID = 'debugHelperService';
|
||||
export const IDebugHelperService = createDecorator<IDebugHelperService>(DEBUG_HELPER_SERVICE_ID);
|
||||
|
||||
/**
|
||||
* This interface represents a single command line argument split into a "prefix" and a "path" half.
|
||||
* The optional "prefix" contains arbitrary text and the optional "path" contains a file system path.
|
||||
* Concatenating both results in the original command line argument.
|
||||
*/
|
||||
export interface ILaunchVSCodeArgument {
|
||||
prefix?: string;
|
||||
path?: string;
|
||||
}
|
||||
|
||||
export interface ILaunchVSCodeArguments {
|
||||
args: ILaunchVSCodeArgument[];
|
||||
env?: { [key: string]: string | null; };
|
||||
}
|
||||
|
||||
export interface IDebugHelperService {
|
||||
_serviceBrand: any;
|
||||
|
||||
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher;
|
||||
|
||||
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number>;
|
||||
|
||||
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,12 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vs/nls';
|
||||
import { Client as TelemetryClient } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import * as strings from 'vs/base/common/strings';
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { isObject } from 'vs/base/common/types';
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
|
||||
import { IJSONSchema, IJSONSchemaSnippet } from 'vs/base/common/jsonSchema';
|
||||
import { IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IConfig, IDebuggerContribution, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IConfig, IDebuggerContribution, INTERNAL_CONSOLE_OPTIONS_SCHEMA, IConfigurationManager, IDebugAdapter, ITerminalSettings, IDebugger, IDebugSession, IDebugHelperService } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IConfigurationResolverService } from 'vs/workbench/services/configurationResolver/common/configurationResolver';
|
||||
import * as ConfigurationResolverUtils from 'vs/workbench/services/configurationResolver/common/configurationResolverUtils';
|
||||
|
@ -19,7 +17,6 @@ import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'
|
|||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { TaskDefinitionRegistry } from 'vs/workbench/contrib/tasks/common/taskDefinitionRegistry';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { ITextResourcePropertiesService } from 'vs/editor/common/services/resourceConfiguration';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
|
@ -37,6 +34,7 @@ export class Debugger implements IDebugger {
|
|||
@ITextResourcePropertiesService private readonly resourcePropertiesService: ITextResourcePropertiesService,
|
||||
@IConfigurationResolverService private readonly configurationResolverService: IConfigurationResolverService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IDebugHelperService private readonly debugHelperService: IDebugHelperService
|
||||
) {
|
||||
this.debuggerContribution = { type: dbgContribution.type };
|
||||
this.merge(dbgContribution, extensionDescription);
|
||||
|
@ -193,24 +191,8 @@ export class Debugger implements IDebugger {
|
|||
telemetryInfo['common.vscodesessionid'] = info.sessionId;
|
||||
return telemetryInfo;
|
||||
}).then(data => {
|
||||
const client = new TelemetryClient(
|
||||
getPathFromAmdModule(require, 'bootstrap-fork'),
|
||||
{
|
||||
serverName: 'Debug Telemetry',
|
||||
timeout: 1000 * 60 * 5,
|
||||
args: [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey],
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: 1,
|
||||
PIPE_LOGGING: 'true',
|
||||
AMD_ENTRYPOINT: 'vs/workbench/contrib/debug/node/telemetryApp'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const channel = client.getChannel('telemetryAppender');
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
|
||||
return new TelemetryService({ appender }, this.configurationService);
|
||||
const args = [`${this.getMainExtensionDescriptor().publisher}.${this.type}`, JSON.stringify(data), aiKey];
|
||||
return this.debugHelperService.createTelemetryService(this.configurationService, args);
|
||||
});
|
||||
}
|
||||
|
131
src/vs/workbench/contrib/debug/node/debugHelperService.ts
Normal file
|
@ -0,0 +1,131 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as objects from 'vs/base/common/objects';
|
||||
import { isUri } from 'vs/workbench/contrib/debug/common/debugUtils';
|
||||
import * as cp from 'child_process';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TerminalLauncher } from 'vs/workbench/contrib/debug/node/terminalSupport';
|
||||
import { ITerminalLauncher, IDebugHelperService, ILaunchVSCodeArguments } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Client as TelemetryClient } from 'vs/base/parts/ipc/node/ipc.cp';
|
||||
import { TelemetryAppenderClient } from 'vs/platform/telemetry/node/telemetryIpc';
|
||||
import { getPathFromAmdModule } from 'vs/base/common/amd';
|
||||
import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
|
||||
export class NodeDebugHelperService implements IDebugHelperService {
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService private readonly environmentService: IEnvironmentService
|
||||
) {
|
||||
}
|
||||
|
||||
createTerminalLauncher(instantiationService: IInstantiationService): ITerminalLauncher {
|
||||
return instantiationService.createInstance(TerminalLauncher);
|
||||
}
|
||||
|
||||
launchVsCode(vscodeArgs: ILaunchVSCodeArguments): Promise<number> {
|
||||
|
||||
const spawnOpts: cp.SpawnOptions = {
|
||||
detached: false // https://github.com/Microsoft/vscode/issues/57018
|
||||
};
|
||||
|
||||
if (vscodeArgs.env) {
|
||||
// merge environment variables into a copy of the process.env
|
||||
const envArgs = objects.mixin(objects.mixin({}, process.env), vscodeArgs.env);
|
||||
// and delete some if necessary
|
||||
Object.keys(envArgs).filter(k => envArgs[k] === null).forEach(key => delete envArgs[key]);
|
||||
spawnOpts.env = envArgs;
|
||||
}
|
||||
|
||||
let spawnArgs = vscodeArgs.args.map(a => {
|
||||
if ((a.prefix === '--file-uri=' || a.prefix === '--folder-uri=') && !isUri(a.path)) {
|
||||
return (a.path || '');
|
||||
}
|
||||
return (a.prefix || '') + (a.path || '');
|
||||
});
|
||||
|
||||
let runtimeExecutable = this.environmentService['execPath'];
|
||||
if (!runtimeExecutable) {
|
||||
return Promise.reject(new Error(`VS Code executable unknown`));
|
||||
}
|
||||
|
||||
// if VS Code runs out of sources, add the VS Code workspace path as the first argument so that Electron turns into VS Code
|
||||
const electronIdx = runtimeExecutable.indexOf(process.platform === 'win32' ? '\\.build\\electron\\' : '/.build/electron/');
|
||||
if (electronIdx > 0) {
|
||||
// guess the VS Code workspace path from the executable
|
||||
const vscodeWorkspacePath = runtimeExecutable.substr(0, electronIdx);
|
||||
|
||||
// only add VS Code workspace path if user hasn't already added that path as a (folder) argument
|
||||
const x = spawnArgs.filter(a => a.indexOf(vscodeWorkspacePath) === 0);
|
||||
if (x.length === 0) {
|
||||
spawnArgs.unshift(vscodeWorkspacePath);
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for bug Microsoft/vscode#45832
|
||||
if (process.platform === 'win32' && runtimeExecutable.indexOf(' ') > 0) {
|
||||
let foundArgWithSpace = false;
|
||||
|
||||
// check whether there is one arg with a space
|
||||
const args: string[] = [];
|
||||
for (const a of spawnArgs) {
|
||||
if (a.indexOf(' ') > 0) {
|
||||
args.push(`"${a}"`);
|
||||
foundArgWithSpace = true;
|
||||
} else {
|
||||
args.push(a);
|
||||
}
|
||||
}
|
||||
|
||||
if (foundArgWithSpace) {
|
||||
spawnArgs = args;
|
||||
runtimeExecutable = `"${runtimeExecutable}"`;
|
||||
spawnOpts.shell = true;
|
||||
}
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const process = cp.spawn(runtimeExecutable, spawnArgs, spawnOpts);
|
||||
process.on('error', error => {
|
||||
reject(error);
|
||||
});
|
||||
process.on('exit', code => {
|
||||
if (code === 0) {
|
||||
resolve(process.pid);
|
||||
} else {
|
||||
reject(new Error(`VS Code exited with ${code}`));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
createTelemetryService(configurationService: IConfigurationService, args: string[]): TelemetryService | undefined {
|
||||
|
||||
const client = new TelemetryClient(
|
||||
getPathFromAmdModule(require, 'bootstrap-fork'),
|
||||
{
|
||||
serverName: 'Debug Telemetry',
|
||||
timeout: 1000 * 60 * 5,
|
||||
args: args,
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: 1,
|
||||
PIPE_LOGGING: 'true',
|
||||
AMD_ENTRYPOINT: 'vs/workbench/contrib/debug/node/telemetryApp'
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
const channel = client.getChannel('telemetryAppender');
|
||||
const appender = new TelemetryAppenderClient(channel);
|
||||
|
||||
return new TelemetryService({ appender }, configurationService);
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IDebugHelperService, NodeDebugHelperService);
|
|
@ -10,12 +10,12 @@ import { SimpleReplElement, DebugModel, Expression, RawObjectReplElement, StackF
|
|||
import * as sinon from 'sinon';
|
||||
import { MockRawSession } from 'vs/workbench/contrib/debug/test/common/mockDebug';
|
||||
import { Source } from 'vs/workbench/contrib/debug/common/debugSource';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/electron-browser/debugSession';
|
||||
import { DebugSession } from 'vs/workbench/contrib/debug/browser/debugSession';
|
||||
import { ReplModel } from 'vs/workbench/contrib/debug/common/replModel';
|
||||
import { IBreakpointUpdateData } from 'vs/workbench/contrib/debug/common/debug';
|
||||
|
||||
function createMockSession(model: DebugModel, name = 'mockSession', parentSession?: DebugSession | undefined): DebugSession {
|
||||
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
return new DebugSession({ resolved: { name, type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, parentSession, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
}
|
||||
|
||||
suite('Debug - Model', () => {
|
||||
|
@ -437,7 +437,7 @@ suite('Debug - Model', () => {
|
|||
// Repl output
|
||||
|
||||
test('repl output', () => {
|
||||
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
const session = new DebugSession({ resolved: { name: 'mockSession', type: 'node', request: 'launch' }, unresolved: undefined }, undefined!, model, undefined, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!, undefined!);
|
||||
const repl = new ReplModel(session);
|
||||
repl.appendToRepl('first line\n', severity.Error);
|
||||
repl.appendToRepl('second line ', severity.Error);
|
|
@ -7,7 +7,7 @@ import * as assert from 'assert';
|
|||
import { join, normalize } from 'vs/base/common/path';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { IDebugAdapterExecutable, IConfigurationManager, IConfig, IDebugSession } from 'vs/workbench/contrib/debug/common/debug';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/node/debugger';
|
||||
import { Debugger } from 'vs/workbench/contrib/debug/common/debugger';
|
||||
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ExecutableDebugAdapter } from 'vs/workbench/contrib/debug/node/debugAdapter';
|
||||
|
@ -130,7 +130,7 @@ suite('Debug - Debugger', () => {
|
|||
const testResourcePropertiesService = new TestTextResourcePropertiesService(configurationService);
|
||||
|
||||
setup(() => {
|
||||
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined!, undefined!);
|
||||
_debugger = new Debugger(configurationManager, debuggerContribution, extensionDescriptor0, configurationService, testResourcePropertiesService, undefined!, undefined!, undefined!);
|
||||
});
|
||||
|
||||
teardown(() => {
|
||||
|
|
|
@ -25,6 +25,7 @@ interface IConfiguration extends IWindowsConfiguration {
|
|||
telemetry: { enableCrashReporter: boolean };
|
||||
keyboard: { touchbar: { enabled: boolean } };
|
||||
workbench: { list: { horizontalScrolling: boolean }, useExperimentalGridLayout: boolean };
|
||||
debug: { console: { wordWrap: boolean } };
|
||||
}
|
||||
|
||||
export class SettingsChangeRelauncher extends Disposable implements IWorkbenchContribution {
|
||||
|
@ -38,6 +39,7 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
|
|||
private touchbarEnabled: boolean;
|
||||
private treeHorizontalScrolling: boolean;
|
||||
private useGridLayout: boolean;
|
||||
private debugConsoleWordWrap: boolean;
|
||||
|
||||
constructor(
|
||||
@IWindowsService private readonly windowsService: IWindowsService,
|
||||
|
@ -109,6 +111,12 @@ export class SettingsChangeRelauncher extends Disposable implements IWorkbenchCo
|
|||
changed = true;
|
||||
}
|
||||
|
||||
// Debug console word wrap
|
||||
if (config.debug && typeof config.debug.console.wordWrap === 'boolean' && config.debug.console.wordWrap !== this.debugConsoleWordWrap) {
|
||||
this.debugConsoleWordWrap = config.debug.console.wordWrap;
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// Notify only when changed and we are the focused window (avoids notification spam across windows)
|
||||
if (notify && changed) {
|
||||
this.doConfirm(
|
||||
|
|
|
@ -14,7 +14,7 @@ import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
|
|||
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenTwitterUrlAction, OpenRequestFeatureUrlAction, OpenPrivacyStatementUrlAction, OpenLicenseUrlAction, OpenNewsletterSignupUrlAction } from 'vs/workbench/electron-browser/actions/helpActions';
|
||||
import { ToggleSharedProcessAction, InspectContextKeysAction, ToggleScreencastModeAction, ToggleDevToolsAction } from 'vs/workbench/electron-browser/actions/developerActions';
|
||||
import { ShowAboutDialogAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, OpenRecentAction, ReloadWindowWithExtensionsDisabledAction, NewWindowTabHandler, ReloadWindowAction, ShowPreviousWindowTabHandler, ShowNextWindowTabHandler, MoveWindowTabToNewWindowHandler, MergeWindowTabsHandlerHandler, ToggleWindowTabsBarHandler } from 'vs/workbench/electron-browser/actions/windowActions';
|
||||
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction, OpenLocalFileAction, OpenLocalFolderAction, OpenLocalFileFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, DuplicateWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction, CloseWorkspaceAction, OpenLocalFileAction, OpenLocalFolderAction, OpenLocalFileFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
|
||||
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
|
@ -45,6 +45,7 @@ import product from 'vs/platform/product/node/product';
|
|||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenLocalFolderAction, OpenLocalFolderAction.ID, OpenLocalFolderAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyMod.CtrlCmd | KeyCode.KEY_O) }, RemoteFileDialogContext), 'File: Open Local Folder...', fileCategory);
|
||||
}
|
||||
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(SaveLocalFileAction, SaveLocalFileAction.ID, SaveLocalFileAction.LABEL, { primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_S }, RemoteFileDialogContext), 'File: Save Local File...', fileCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(QuickOpenRecentAction, QuickOpenRecentAction.ID, QuickOpenRecentAction.LABEL), 'File: Quick Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(OpenRecentAction, OpenRecentAction.ID, OpenRecentAction.LABEL, { primary: KeyMod.CtrlCmd | KeyCode.KEY_R, mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_R } }), 'File: Open Recent...', fileCategory);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(CloseWorkspaceAction, CloseWorkspaceAction.ID, CloseWorkspaceAction.LABEL, { primary: KeyChord(KeyMod.CtrlCmd | KeyCode.KEY_K, KeyCode.KEY_F) }), 'File: Close Workspace', fileCategory);
|
||||
|
|
|
@ -187,6 +187,25 @@ export class FileDialogService implements IFileDialogService {
|
|||
return this.windowService.pickWorkspaceAndOpen(this.toNativeOpenDialogOptions(options));
|
||||
}
|
||||
|
||||
async pickFileToSave(options: ISaveDialogOptions): Promise<URI | undefined> {
|
||||
const schema = this.getFileSystemSchema(options);
|
||||
if (this.shouldUseSimplified(schema)) {
|
||||
if (!options.availableFileSystems) {
|
||||
options.availableFileSystems = this.ensureFileSchema(schema); // always allow file as well
|
||||
}
|
||||
|
||||
options.title = nls.localize('saveFileAs.title', 'Save As');
|
||||
return this.saveRemoteResource(options);
|
||||
}
|
||||
|
||||
const result = await this.windowService.showSaveDialog(this.toNativeSaveDialogOptions(options));
|
||||
if (result) {
|
||||
return URI.file(result);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private toNativeSaveDialogOptions(options: ISaveDialogOptions): Electron.SaveDialogOptions {
|
||||
return {
|
||||
defaultPath: options.defaultUri && options.defaultUri.fsPath || options.defaultFileName,
|
||||
|
|
|
@ -23,7 +23,7 @@ import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/
|
|||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
|
||||
import { IContextKeyService, IContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { equalsIgnoreCase, format, startsWithIgnoreCase } from 'vs/base/common/strings';
|
||||
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { OpenLocalFileAction, OpenLocalFileFolderAction, OpenLocalFolderAction, SaveLocalFileAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IRemoteAgentEnvironment } from 'vs/platform/remote/common/remoteAgentEnvironment';
|
||||
import { isValidBasename } from 'vs/base/common/extpath';
|
||||
|
@ -211,7 +211,12 @@ export class RemoteFileDialog {
|
|||
if (this.options && this.options.availableFileSystems && (this.options.availableFileSystems.length > 1)) {
|
||||
this.filePickBox.customButton = true;
|
||||
this.filePickBox.customLabel = nls.localize('remoteFileDialog.local', 'Show Local');
|
||||
const action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderAction : OpenLocalFileAction) : OpenLocalFolderAction;
|
||||
let action;
|
||||
if (isSave) {
|
||||
action = SaveLocalFileAction;
|
||||
} else {
|
||||
action = this.allowFileSelection ? (this.allowFolderSelection ? OpenLocalFileFolderAction : OpenLocalFileAction) : OpenLocalFolderAction;
|
||||
}
|
||||
const keybinding = this.keybindingService.lookupKeybinding(action.ID);
|
||||
if (keybinding) {
|
||||
const label = keybinding.getLabel();
|
||||
|
@ -251,7 +256,10 @@ export class RemoteFileDialog {
|
|||
}
|
||||
this.options.defaultUri = undefined;
|
||||
this.filePickBox.hide();
|
||||
if (this.requiresTrailing) {
|
||||
if (isSave) {
|
||||
// Remove defaultUri and filters to get a consistant experience with the keybinding.
|
||||
this.options.defaultUri = undefined;
|
||||
this.options.filters = undefined;
|
||||
return this.fileDialogService.showSaveDialog(this.options).then(result => {
|
||||
doResolve(this, result);
|
||||
});
|
||||
|
|
|
@ -653,7 +653,7 @@ export abstract class TextFileService extends Disposable implements ITextFileSer
|
|||
// Help user to find a name for the file by opening it first
|
||||
await this.editorService.openEditor({ resource, options: { revealIfOpened: true, preserveFocus: true, } });
|
||||
|
||||
return this.fileDialogService.showSaveDialog(this.getSaveDialogOptions(defaultUri));
|
||||
return this.fileDialogService.pickFileToSave(this.getSaveDialogOptions(defaultUri));
|
||||
}
|
||||
|
||||
private getSaveDialogOptions(defaultUri: URI): ISaveDialogOptions {
|
||||
|
|
|
@ -439,6 +439,9 @@ export class TestFileDialogService implements IFileDialogService {
|
|||
public pickWorkspaceAndOpen(_options: IPickAndOpenOptions): Promise<any> {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
public pickFileToSave(_options: ISaveDialogOptions): Promise<URI | undefined> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
public showSaveDialog(_options: ISaveDialogOptions): Promise<URI | undefined> {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
|
|
@ -230,11 +230,12 @@ import 'vs/workbench/contrib/scm/browser/scm.contribution';
|
|||
import 'vs/workbench/contrib/scm/browser/scmViewlet';
|
||||
|
||||
// Debug
|
||||
import 'vs/workbench/contrib/debug/electron-browser/debug.contribution';
|
||||
import 'vs/workbench/contrib/debug/browser/debug.contribution';
|
||||
import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
|
||||
import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
|
||||
import 'vs/workbench/contrib/debug/browser/repl';
|
||||
import 'vs/workbench/contrib/debug/browser/debugViewlet';
|
||||
import 'vs/workbench/contrib/debug/node/debugHelperService';
|
||||
|
||||
// Markers
|
||||
import 'vs/workbench/contrib/markers/browser/markers.contribution';
|
||||
|
|
|
@ -234,11 +234,13 @@ import 'vs/workbench/contrib/scm/browser/scm.contribution';
|
|||
import 'vs/workbench/contrib/scm/browser/scmViewlet';
|
||||
|
||||
// Debug
|
||||
// import 'vs/workbench/contrib/debug/electron-browser/debug.contribution';
|
||||
// import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
|
||||
// import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
|
||||
// import 'vs/workbench/contrib/debug/browser/repl';
|
||||
// import 'vs/workbench/contrib/debug/browser/debugViewlet';
|
||||
import 'vs/workbench/contrib/debug/browser/debug.contribution';
|
||||
import 'vs/workbench/contrib/debug/browser/debugQuickOpen';
|
||||
import 'vs/workbench/contrib/debug/browser/debugEditorContribution';
|
||||
import 'vs/workbench/contrib/debug/browser/repl';
|
||||
import 'vs/workbench/contrib/debug/browser/debugViewlet';
|
||||
import 'vs/workbench/contrib/debug/browser/debugHelperService';
|
||||
|
||||
|
||||
// Markers
|
||||
import 'vs/workbench/contrib/markers/browser/markers.contribution';
|
||||
|
|