Skip to content

Commit 32184f4

Browse files
author
Benjamin Pasero
committed
untitled - fully support resources with associated filepath
1 parent 57fb54f commit 32184f4

17 files changed

Lines changed: 192 additions & 186 deletions

File tree

src/vs/code/electron-main/window.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,8 +554,7 @@ export class CodeWindow extends Disposable implements ICodeWindow {
554554
const configuration = configurationIn ? configurationIn : objects.mixin({}, this.currentConfig);
555555

556556
// Delete some properties we do not want during reload
557-
delete configuration.filesToOpen;
558-
delete configuration.filesToCreate;
557+
delete configuration.filesToOpenOrCreate;
559558
delete configuration.filesToDiff;
560559
delete configuration.filesToWait;
561560

src/vs/code/electron-main/windows.ts

Lines changed: 49 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,7 @@ interface IPathParseOptions {
9191
}
9292

9393
interface IFileInputs {
94-
filesToOpen: IPath[];
95-
filesToCreate: IPath[];
94+
filesToOpenOrCreate: IPath[];
9695
filesToDiff: IPath[];
9796
filesToWait?: IPathsToWaitFor;
9897
remoteAuthority?: string;
@@ -112,9 +111,6 @@ interface IPathToOpen extends IPath {
112111
// the remote authority for the Code instance to open. Undefined if not remote.
113112
remoteAuthority?: string;
114113

115-
// indicator to create the file path in the Code instance
116-
createFilePath?: boolean;
117-
118114
// optional label for the recent history
119115
label?: string;
120116
}
@@ -397,13 +393,9 @@ export class WindowsManager implements IWindowsMainService {
397393
workspacesToOpen.push(path);
398394
} else if (path.fileUri) {
399395
if (!fileInputs) {
400-
fileInputs = { filesToCreate: [], filesToOpen: [], filesToDiff: [], remoteAuthority: path.remoteAuthority };
401-
}
402-
if (!path.createFilePath) {
403-
fileInputs.filesToOpen.push(path);
404-
} else {
405-
fileInputs.filesToCreate.push(path);
396+
fileInputs = { filesToOpenOrCreate: [], filesToDiff: [], remoteAuthority: path.remoteAuthority };
406397
}
398+
fileInputs.filesToOpenOrCreate.push(path);
407399
} else if (path.backupPath) {
408400
emptyToRestore.push({ backupFolder: basename(path.backupPath), remoteAuthority: path.remoteAuthority });
409401
} else {
@@ -413,15 +405,14 @@ export class WindowsManager implements IWindowsMainService {
413405

414406
// When run with --diff, take the files to open as files to diff
415407
// if there are exactly two files provided.
416-
if (fileInputs && openConfig.diffMode && fileInputs.filesToOpen.length === 2) {
417-
fileInputs.filesToDiff = fileInputs.filesToOpen;
418-
fileInputs.filesToOpen = [];
419-
fileInputs.filesToCreate = []; // diff ignores other files that do not exist
408+
if (fileInputs && openConfig.diffMode && fileInputs.filesToOpenOrCreate.length === 2) {
409+
fileInputs.filesToDiff = fileInputs.filesToOpenOrCreate;
410+
fileInputs.filesToOpenOrCreate = [];
420411
}
421412

422413
// When run with --wait, make sure we keep the paths to wait for
423414
if (fileInputs && openConfig.waitMarkerFileURI) {
424-
fileInputs.filesToWait = { paths: [...fileInputs.filesToDiff, ...fileInputs.filesToOpen, ...fileInputs.filesToCreate], waitMarkerFileUri: openConfig.waitMarkerFileURI };
415+
fileInputs.filesToWait = { paths: [...fileInputs.filesToDiff, ...fileInputs.filesToOpenOrCreate], waitMarkerFileUri: openConfig.waitMarkerFileURI };
425416
}
426417

427418
//
@@ -551,7 +542,7 @@ export class WindowsManager implements IWindowsMainService {
551542
if (potentialWindowsCount === 0 && fileInputs) {
552543

553544
// Find suitable window or folder path to open files in
554-
const fileToCheck = fileInputs.filesToOpen[0] || fileInputs.filesToCreate[0] || fileInputs.filesToDiff[0];
545+
const fileToCheck = fileInputs.filesToOpenOrCreate[0] || fileInputs.filesToDiff[0];
555546
// only look at the windows with correct authority
556547
const windows = WindowsManager.WINDOWS.filter(w => w.remoteAuthority === fileInputs!.remoteAuthority);
557548

@@ -746,10 +737,9 @@ export class WindowsManager implements IWindowsMainService {
746737
private doOpenFilesInExistingWindow(configuration: IOpenConfiguration, window: ICodeWindow, fileInputs?: IFileInputs): ICodeWindow {
747738
window.focus(); // make sure window has focus
748739

749-
const params: { filesToOpen?: IPath[], filesToCreate?: IPath[], filesToDiff?: IPath[], filesToWait?: IPathsToWaitFor, termProgram?: string } = {};
740+
const params: { filesToOpenOrCreate?: IPath[], filesToDiff?: IPath[], filesToWait?: IPathsToWaitFor, termProgram?: string } = {};
750741
if (fileInputs) {
751-
params.filesToOpen = fileInputs.filesToOpen;
752-
params.filesToCreate = fileInputs.filesToCreate;
742+
params.filesToOpenOrCreate = fileInputs.filesToOpenOrCreate;
753743
params.filesToDiff = fileInputs.filesToDiff;
754744
params.filesToWait = fileInputs.filesToWait;
755745
}
@@ -1065,47 +1055,57 @@ export class WindowsManager implements IWindowsMainService {
10651055
anyPath = parsedPath.path;
10661056
}
10671057

1068-
// open remote if either specified in the cli even if it is a local file. TODO: Future idea: resolve in remote host context.
1058+
// open remote if either specified in the cli even if it is a local file. TODO@aeschli: Future idea: resolve in remote host context.
10691059
const remoteAuthority = options.remoteAuthority;
10701060

10711061
const candidate = normalize(anyPath);
10721062
try {
10731063
const candidateStat = fs.statSync(candidate);
1074-
if (candidateStat) {
1075-
if (candidateStat.isFile()) {
1076-
1077-
// Workspace (unless disabled via flag)
1078-
if (!forceOpenWorkspaceAsFile) {
1079-
const workspace = this.workspacesMainService.resolveLocalWorkspaceSync(URI.file(candidate));
1080-
if (workspace) {
1081-
return { workspace: { id: workspace.id, configPath: workspace.configPath }, remoteAuthority: workspace.remoteAuthority };
1082-
}
1064+
if (candidateStat.isFile()) {
1065+
1066+
// Workspace (unless disabled via flag)
1067+
if (!forceOpenWorkspaceAsFile) {
1068+
const workspace = this.workspacesMainService.resolveLocalWorkspaceSync(URI.file(candidate));
1069+
if (workspace) {
1070+
return {
1071+
workspace: { id: workspace.id, configPath: workspace.configPath },
1072+
remoteAuthority: workspace.remoteAuthority,
1073+
exists: true
1074+
};
10831075
}
1084-
1085-
// File
1086-
return {
1087-
fileUri: URI.file(candidate),
1088-
lineNumber,
1089-
columnNumber,
1090-
remoteAuthority
1091-
};
10921076
}
10931077

1094-
// Folder (we check for isDirectory() because e.g. paths like /dev/null
1095-
// are neither file nor folder but some external tools might pass them
1096-
// over to us)
1097-
else if (candidateStat.isDirectory()) {
1098-
return {
1099-
folderUri: URI.file(candidate),
1100-
remoteAuthority
1101-
};
1102-
}
1078+
// File
1079+
return {
1080+
fileUri: URI.file(candidate),
1081+
lineNumber,
1082+
columnNumber,
1083+
remoteAuthority,
1084+
exists: true
1085+
};
1086+
}
1087+
1088+
// Folder (we check for isDirectory() because e.g. paths like /dev/null
1089+
// are neither file nor folder but some external tools might pass them
1090+
// over to us)
1091+
else if (candidateStat.isDirectory()) {
1092+
return {
1093+
folderUri: URI.file(candidate),
1094+
remoteAuthority,
1095+
exists: true
1096+
};
11031097
}
11041098
} catch (error) {
11051099
const fileUri = URI.file(candidate);
11061100
this.historyMainService.removeFromRecentlyOpened([fileUri]); // since file does not seem to exist anymore, remove from recent
1101+
1102+
// assume this is a file that does not yet exist
11071103
if (options && options.ignoreFileNotFound) {
1108-
return { fileUri, createFilePath: true, remoteAuthority }; // assume this is a file that does not yet exist
1104+
return {
1105+
fileUri,
1106+
remoteAuthority,
1107+
exists: false
1108+
};
11091109
}
11101110
}
11111111

@@ -1279,8 +1279,7 @@ export class WindowsManager implements IWindowsMainService {
12791279

12801280
const fileInputs = options.fileInputs;
12811281
if (fileInputs) {
1282-
configuration.filesToOpen = fileInputs.filesToOpen;
1283-
configuration.filesToCreate = fileInputs.filesToCreate;
1282+
configuration.filesToOpenOrCreate = fileInputs.filesToOpenOrCreate;
12841283
configuration.filesToDiff = fileInputs.filesToDiff;
12851284
configuration.filesToWait = fileInputs.filesToWait;
12861285
}

src/vs/platform/editor/common/editor.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ export interface IBaseResourceInput {
4949
* looking at the scheme of the resource(s).
5050
*/
5151
readonly forceFile?: boolean;
52+
53+
/**
54+
* Hint to indicate that this input should be treated as a
55+
* untitled file.
56+
*
57+
* Without this hint, the editor service will make a guess by
58+
* looking at the scheme of the resource(s).
59+
*/
60+
readonly forceUntitled?: boolean;
5261
}
5362

5463
export interface IResourceInput extends IBaseResourceInput {

src/vs/platform/windows/common/windows.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ export const enum ReadyState {
355355

356356
export interface IPath extends IPathData {
357357

358-
// the file path to open within a Code instance
358+
// the file path to open within the instance
359359
fileUri?: URI;
360360
}
361361

@@ -371,19 +371,23 @@ export interface IPathsToWaitForData {
371371

372372
export interface IPathData {
373373

374-
// the file path to open within a Code instance
374+
// the file path to open within the instance
375375
fileUri?: UriComponents;
376376

377377
// the line number in the file path to open
378378
lineNumber?: number;
379379

380380
// the column number in the file path to open
381381
columnNumber?: number;
382+
383+
// a hint that the file exists. if true, the
384+
// file exists, if false it does not. with
385+
// undefined the state is unknown.
386+
exists?: boolean;
382387
}
383388

384389
export interface IOpenFileRequest {
385-
filesToOpen?: IPathData[];
386-
filesToCreate?: IPathData[];
390+
filesToOpenOrCreate?: IPathData[];
387391
filesToDiff?: IPathData[];
388392
filesToWait?: IPathsToWaitForData;
389393
termProgram?: string;
@@ -427,8 +431,7 @@ export interface IWindowConfiguration extends ParsedArgs {
427431
perfWindowLoadTime?: number;
428432
perfEntries: ExportData;
429433

430-
filesToOpen?: IPath[];
431-
filesToCreate?: IPath[];
434+
filesToOpenOrCreate?: IPath[];
432435
filesToDiff?: IPath[];
433436
filesToWait?: IPathsToWaitFor;
434437
termProgram?: string;

src/vs/platform/windows/electron-main/windowsService.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export class WindowsService implements IWindowsService, IURLHandler, IDisposable
176176
async getRecentlyOpened(windowId: number): Promise<IRecentlyOpened> {
177177
this.logService.trace('windowsService#getRecentlyOpened', windowId);
178178

179-
return this.withWindow(windowId, codeWindow => this.historyService.getRecentlyOpened(codeWindow.config.workspace, codeWindow.config.folderUri, codeWindow.config.filesToOpen), () => this.historyService.getRecentlyOpened())!;
179+
return this.withWindow(windowId, codeWindow => this.historyService.getRecentlyOpened(codeWindow.config.workspace, codeWindow.config.folderUri, codeWindow.config.filesToOpenOrCreate), () => this.historyService.getRecentlyOpened())!;
180180
}
181181

182182
async newWindowTab(): Promise<void> {

src/vs/workbench/browser/layout.ts

Lines changed: 22 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ import { onDidChangeFullscreen, isFullscreen, getZoomFactor } from 'vs/base/brow
1010
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
1111
import { Registry } from 'vs/platform/registry/common/platform';
1212
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
13-
import { IResourceInput } from 'vs/platform/editor/common/editor';
14-
import { IUntitledResourceInput, IResourceDiffInput } from 'vs/workbench/common/editor';
13+
import { IUntitledResourceInput, pathsToEditors } from 'vs/workbench/common/editor';
1514
import { SidebarPart } from 'vs/workbench/browser/parts/sidebar/sidebarPart';
1615
import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
1716
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
@@ -24,7 +23,7 @@ import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
2423
import { ITitleService } from 'vs/workbench/services/title/common/titleService';
2524
import { IInstantiationService, ServicesAccessor, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
2625
import { LifecyclePhase, StartupKind, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
27-
import { IWindowService, IPath, MenuBarVisibility, getTitleBarStyle } from 'vs/platform/windows/common/windows';
26+
import { IWindowService, MenuBarVisibility, getTitleBarStyle } from 'vs/platform/windows/common/windows';
2827
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
2928
import { IEditorService, IResourceEditor } from 'vs/workbench/services/editor/common/editorService';
3029
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -34,7 +33,7 @@ import { IDimension } from 'vs/platform/layout/browser/layoutService';
3433
import { Part } from 'vs/workbench/browser/part';
3534
import { IStatusbarService } from 'vs/platform/statusbar/common/statusbar';
3635
import { IActivityBarService } from 'vs/workbench/services/activityBar/browser/activityBarService';
37-
import { coalesce } from 'vs/base/common/arrays';
36+
import { IFileService } from 'vs/platform/files/common/files';
3837

3938
enum Settings {
4039
MENUBAR_VISIBLE = 'window.menuBarVisibility',
@@ -182,7 +181,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
182181
this.registerLayoutListeners();
183182

184183
// State
185-
this.initLayoutState(accessor.get(ILifecycleService));
184+
this.initLayoutState(accessor.get(ILifecycleService), accessor.get(IFileService));
186185
}
187186

188187
private registerLayoutListeners(): void {
@@ -319,7 +318,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
319318
}
320319
}
321320

322-
private initLayoutState(lifecycleService: ILifecycleService): void {
321+
private initLayoutState(lifecycleService: ILifecycleService, fileService: IFileService): void {
323322

324323
// Fullscreen
325324
this.state.fullscreen = isFullscreen();
@@ -358,7 +357,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
358357
this.state.editor.restoreCentered = this.storageService.getBoolean(Storage.CENTERED_LAYOUT_ENABLED, StorageScope.WORKSPACE, false);
359358

360359
// Editors to open
361-
this.state.editor.editorsToOpen = this.resolveEditorsToOpen();
360+
this.state.editor.editorsToOpen = this.resolveEditorsToOpen(fileService);
362361

363362
// Panel visibility
364363
this.state.panel.hidden = this.storageService.getBoolean(Storage.PANEL_HIDDEN, StorageScope.WORKSPACE, true);
@@ -389,7 +388,7 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
389388
this.state.zenMode.restore = this.storageService.getBoolean(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE, false) && this.configurationService.getValue(Settings.ZEN_MODE_RESTORE);
390389
}
391390

392-
private resolveEditorsToOpen(): Promise<IResourceEditor[]> | IResourceEditor[] {
391+
private resolveEditorsToOpen(fileService: IFileService): Promise<IResourceEditor[]> | IResourceEditor[] {
393392
const configuration = this.environmentService.configuration;
394393
const hasInitialFilesToOpen = this.hasInitialFilesToOpen();
395394

@@ -400,21 +399,19 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
400399
if (hasInitialFilesToOpen) {
401400

402401
// Files to diff is exclusive
403-
const filesToDiff = this.toInputs(configuration.filesToDiff, false);
404-
if (filesToDiff && filesToDiff.length === 2) {
405-
return [<IResourceDiffInput>{
406-
leftResource: filesToDiff[0].resource,
407-
rightResource: filesToDiff[1].resource,
408-
options: { pinned: true },
409-
forceFile: true
410-
}];
411-
}
412-
413-
const filesToCreate = this.toInputs(configuration.filesToCreate, true);
414-
const filesToOpen = this.toInputs(configuration.filesToOpen, false);
402+
return pathsToEditors(configuration.filesToDiff, fileService).then(filesToDiff => {
403+
if (filesToDiff && filesToDiff.length === 2) {
404+
return [{
405+
leftResource: filesToDiff[0].resource,
406+
rightResource: filesToDiff[1].resource,
407+
options: { pinned: true },
408+
forceFile: true
409+
}];
410+
}
415411

416-
// Otherwise: Open/Create files
417-
return [...filesToOpen, ...filesToCreate];
412+
// Otherwise: Open/Create files
413+
return pathsToEditors(configuration.filesToOpenOrCreate, fileService);
414+
});
418415
}
419416

420417
// Empty workbench
@@ -439,38 +436,9 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
439436
const configuration = this.environmentService.configuration;
440437

441438
return !!(
442-
(configuration.filesToCreate && configuration.filesToCreate.length > 0) ||
443-
(configuration.filesToOpen && configuration.filesToOpen.length > 0) ||
444-
(configuration.filesToDiff && configuration.filesToDiff.length > 0));
445-
}
446-
447-
private toInputs(paths: IPath[] | undefined, isNew: boolean): Array<IResourceInput | IUntitledResourceInput> {
448-
if (!paths || !paths.length) {
449-
return [];
450-
}
451-
452-
return coalesce(paths.map(p => {
453-
const resource = p.fileUri;
454-
if (!resource) {
455-
return undefined;
456-
}
457-
458-
let input: IResourceInput | IUntitledResourceInput;
459-
if (isNew) {
460-
input = { filePath: resource.fsPath, options: { pinned: true } };
461-
} else {
462-
input = { resource, options: { pinned: true }, forceFile: true };
463-
}
464-
465-
if (!isNew && typeof p.lineNumber === 'number') {
466-
input.options!.selection = {
467-
startLineNumber: p.lineNumber,
468-
startColumn: p.columnNumber || 1
469-
};
470-
}
471-
472-
return input;
473-
}));
439+
(configuration.filesToOpenOrCreate && configuration.filesToOpenOrCreate.length > 0) ||
440+
(configuration.filesToDiff && configuration.filesToDiff.length > 0)
441+
);
474442
}
475443

476444
private updatePanelPosition() {

0 commit comments

Comments
 (0)