textfiles.ts 9.8 KB
Newer Older
1 2 3 4 5
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

6
import { URI } from 'vs/base/common/uri';
M
Matt Bierner 已提交
7
import { Event } from 'vs/base/common/event';
J
Johannes Rieken 已提交
8
import { IDisposable } from 'vs/base/common/lifecycle';
9
import { IEncodingSupport, ConfirmResult, IRevertOptions } from 'vs/workbench/common/editor';
10
import { IBaseStat, IResolveContentOptions, ITextSnapshot } from 'vs/platform/files/common/files';
J
Johannes Rieken 已提交
11
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
J
Joao Moreno 已提交
12
import { ITextEditorModel } from 'vs/editor/common/services/resolverService';
13
import { ITextBufferFactory } from 'vs/editor/common/model';
I
isidor 已提交
14
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
15 16

/**
N
Nick Schonning 已提交
17
 * The save error handler can be installed on the text file editor model to install code that executes when save errors occur.
18 19 20 21 22 23
 */
export interface ISaveErrorHandler {

	/**
	 * Called whenever a save fails.
	 */
B
Benjamin Pasero 已提交
24
	onSaveError(error: Error, model: ITextFileEditorModel): void;
25 26 27 28 29 30 31
}

export interface ISaveParticipant {

	/**
	 * Participate in a save of a model. Allows to change the model before it is being saved to disk.
	 */
J
Johannes Rieken 已提交
32
	participate(model: ITextFileEditorModel, env: { reason: SaveReason }): Promise<void>;
33 34 35
}

/**
N
Nick Schonning 已提交
36
 * States the text file editor model can be in.
37
 */
38
export const enum ModelState {
39 40 41
	SAVED,
	DIRTY,
	PENDING_SAVE,
42 43 44 45 46

	/**
	 * A model is in conflict mode when changes cannot be saved because the
	 * underlying file has changed. Models in conflict mode are always dirty.
	 */
47
	CONFLICT,
48 49 50 51 52 53 54 55 56 57

	/**
	 * A model is in orphan state when the underlying file has been deleted.
	 */
	ORPHAN,

	/**
	 * Any error that happens during a save that is not causing the CONFLICT state.
	 * Models in error mode are always diry.
	 */
58 59 60
	ERROR
}

61
export const enum StateChange {
62 63 64 65 66
	DIRTY,
	SAVING,
	SAVE_ERROR,
	SAVED,
	REVERTED,
67
	ENCODING,
68 69
	CONTENT_CHANGE,
	ORPHANED_CHANGE
70 71 72 73 74 75 76 77 78 79 80
}

export class TextFileModelChangeEvent {
	private _resource: URI;
	private _kind: StateChange;

	constructor(model: ITextFileEditorModel, kind: StateChange) {
		this._resource = model.getResource();
		this._kind = kind;
	}

B
Benjamin Pasero 已提交
81
	get resource(): URI {
82 83 84
		return this._resource;
	}

B
Benjamin Pasero 已提交
85
	get kind(): StateChange {
86 87 88 89 90
		return this._kind;
	}
}

export const TEXT_FILE_SERVICE_ID = 'textFileService';
I
isidor 已提交
91
export const AutoSaveContext = new RawContextKey<string>('config.files.autoSave', undefined);
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

export interface ITextFileOperationResult {
	results: IResult[];
}

export interface IResult {
	source: URI;
	target?: URI;
	success?: boolean;
}

export interface IAutoSaveConfiguration {
	autoSaveDelay: number;
	autoSaveFocusChange: boolean;
	autoSaveApplicationChange: boolean;
}

109
export const enum AutoSaveMode {
110 111 112 113 114 115 116
	OFF,
	AFTER_SHORT_DELAY,
	AFTER_LONG_DELAY,
	ON_FOCUS_CHANGE,
	ON_WINDOW_CHANGE
}

117
export const enum SaveReason {
118 119 120 121 122 123
	EXPLICIT = 1,
	AUTO = 2,
	FOCUS_CHANGE = 3,
	WINDOW_CHANGE = 4
}

124
export const enum LoadReason {
125 126 127 128 129
	EDITOR = 1,
	REFERENCE = 2,
	OTHER = 3
}

130 131 132 133 134 135 136
export const ITextFileService = createDecorator<ITextFileService>(TEXT_FILE_SERVICE_ID);

export interface IRawTextContent extends IBaseStat {

	/**
	 * The line grouped content of a text file.
	 */
137
	value: ITextBufferFactory;
138 139 140 141 142 143 144

	/**
	 * The encoding of the content if known.
	 */
	encoding: string;
}

145
export interface IModelLoadOrCreateOptions {
146

147 148 149 150
	/**
	 * Context why the model is being loaded or created.
	 */
	reason?: LoadReason;
151 152 153 154

	/**
	 * The encoding to use when resolving the model text content.
	 */
155
	encoding?: string;
156 157

	/**
158 159 160 161 162 163
	 * If the model was already loaded before, allows to trigger
	 * a reload of it to fetch the latest contents:
	 * - async: loadOrCreate() will return immediately and trigger
	 * a reload that will run in the background.
	 * - sync: loadOrCreate() will only return resolved when the
	 * model has finished reloading.
164
	 */
165 166 167
	reload?: {
		async: boolean
	};
168 169 170 171 172

	/**
	 * Allow to load a model even if we think it is a binary file.
	 */
	allowBinary?: boolean;
173 174
}

175 176
export interface ITextFileEditorModelManager {

177
	onModelDisposed: Event<URI>;
178
	onModelContentChanged: Event<TextFileModelChangeEvent>;
179 180
	onModelEncodingChanged: Event<TextFileModelChangeEvent>;

181 182 183 184
	onModelDirty: Event<TextFileModelChangeEvent>;
	onModelSaveError: Event<TextFileModelChangeEvent>;
	onModelSaved: Event<TextFileModelChangeEvent>;
	onModelReverted: Event<TextFileModelChangeEvent>;
185
	onModelOrphanedChanged: Event<TextFileModelChangeEvent>;
186 187 188 189 190

	onModelsDirty: Event<TextFileModelChangeEvent[]>;
	onModelsSaveError: Event<TextFileModelChangeEvent[]>;
	onModelsSaved: Event<TextFileModelChangeEvent[]>;
	onModelsReverted: Event<TextFileModelChangeEvent[]>;
191 192 193 194 195

	get(resource: URI): ITextFileEditorModel;

	getAll(resource?: URI): ITextFileEditorModel[];

J
Johannes Rieken 已提交
196
	loadOrCreate(resource: URI, options?: IModelLoadOrCreateOptions): Promise<ITextFileEditorModel>;
197 198

	disposeModel(model: ITextFileEditorModel): void;
199 200
}

201
export interface ISaveOptions {
202
	force?: boolean;
203 204 205
	reason?: SaveReason;
	overwriteReadonly?: boolean;
	overwriteEncoding?: boolean;
206
	skipSaveParticipants?: boolean;
207
	writeElevated?: boolean;
208 209
}

210 211 212 213 214 215 216 217 218 219 220
export interface ILoadOptions {

	/**
	 * Go to disk bypassing any cache of the model if any.
	 */
	forceReadFromDisk?: boolean;

	/**
	 * Allow to load a model even if we think it is a binary file.
	 */
	allowBinary?: boolean;
221 222 223 224 225

	/**
	 * Context why the model is being loaded.
	 */
	reason?: LoadReason;
226 227
}

228 229
export interface ITextFileEditorModel extends ITextEditorModel, IEncodingSupport {

230
	onDidContentChange: Event<StateChange>;
231 232
	onDidStateChange: Event<StateChange>;

233 234
	getVersionId(): number;

235 236
	getResource(): URI;

237
	hasState(state: ModelState): boolean;
238

239
	getETag(): string | null;
240

241 242
	updatePreferredEncoding(encoding: string): void;

J
Johannes Rieken 已提交
243
	save(options?: ISaveOptions): Promise<void>;
244

J
Johannes Rieken 已提交
245
	load(options?: ILoadOptions): Promise<ITextFileEditorModel>;
B
Benjamin Pasero 已提交
246

J
Johannes Rieken 已提交
247
	revert(soft?: boolean): Promise<void>;
248

249
	createSnapshot(): ITextSnapshot | null;
250

251 252
	isDirty(): boolean;

253 254
	isResolved(): boolean;

255 256 257
	isDisposed(): boolean;
}

258 259 260 261

export interface IWillMoveEvent {
	oldResource: URI;
	newResource: URI;
J
Johannes Rieken 已提交
262
	waitUntil(p: Promise<any>): void;
263 264
}

265 266
export interface ITextFileService extends IDisposable {
	_serviceBrand: any;
B
Benjamin Pasero 已提交
267 268 269 270

	readonly onAutoSaveConfigurationChange: Event<IAutoSaveConfiguration>;
	readonly onFilesAssociationChange: Event<void>;

271 272
	onWillMove: Event<IWillMoveEvent>;

B
Benjamin Pasero 已提交
273
	readonly isHotExitEnabled: boolean;
274 275 276 277

	/**
	 * Access to the manager of text file editor models providing further methods to work with them.
	 */
B
Benjamin Pasero 已提交
278
	readonly models: ITextFileEditorModelManager;
279 280 281 282

	/**
	 * Resolve the contents of a file identified by the resource.
	 */
J
Johannes Rieken 已提交
283
	resolveTextContent(resource: URI, options?: IResolveContentOptions): Promise<IRawTextContent>;
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304

	/**
	 * A resource is dirty if it has unsaved changes or is an untitled file not yet saved.
	 *
	 * @param resource the resource to check for being dirty. If it is not specified, will check for
	 * all dirty resources.
	 */
	isDirty(resource?: URI): boolean;

	/**
	 * Returns all resources that are currently dirty matching the provided resources or all dirty resources.
	 *
	 * @param resources the resources to check for being dirty. If it is not specified, will check for
	 * all dirty resources.
	 */
	getDirty(resources?: URI[]): URI[];

	/**
	 * Saves the resource.
	 *
	 * @param resource the resource to save
305
	 * @param options optional save options
306
	 * @return true if the resource was saved.
307
	 */
J
Johannes Rieken 已提交
308
	save(resource: URI, options?: ISaveOptions): Promise<boolean>;
309 310

	/**
311
	 * Saves the provided resource asking the user for a file name or using the provided one.
312 313
	 *
	 * @param resource the resource to save as.
314 315
	 * @param targetResource the optional target to save to.
	 * @param options optional save options
316
	 * @return true if the file was saved.
317
	 */
J
Johannes Rieken 已提交
318
	saveAs(resource: URI, targetResource?: URI, options?: ISaveOptions): Promise<URI>;
319 320 321 322 323 324 325

	/**
	 * Saves the set of resources and returns a promise with the operation result.
	 *
	 * @param resources can be null to save all.
	 * @param includeUntitled to save all resources and optionally exclude untitled ones.
	 */
J
Johannes Rieken 已提交
326 327
	saveAll(includeUntitled?: boolean, options?: ISaveOptions): Promise<ITextFileOperationResult>;
	saveAll(resources: URI[], options?: ISaveOptions): Promise<ITextFileOperationResult>;
328 329 330 331 332 333 334

	/**
	 * Reverts the provided resource.
	 *
	 * @param resource the resource of the file to revert.
	 * @param force to force revert even when the file is not dirty
	 */
J
Johannes Rieken 已提交
335
	revert(resource: URI, options?: IRevertOptions): Promise<boolean>;
336 337 338 339

	/**
	 * Reverts all the provided resources and returns a promise with the operation result.
	 */
J
Johannes Rieken 已提交
340
	revertAll(resources?: URI[], options?: IRevertOptions): Promise<ITextFileOperationResult>;
341

B
Benjamin Pasero 已提交
342 343 344 345
	/**
	 * Create a file. If the file exists it will be overwritten with the contents if
	 * the options enable to overwrite.
	 */
J
Johannes Rieken 已提交
346
	create(resource: URI, contents?: string, options?: { overwrite?: boolean }): Promise<void>;
B
Benjamin Pasero 已提交
347

B
Benjamin Pasero 已提交
348 349 350
	/**
	 * Delete a file. If the file is dirty, it will get reverted and then deleted from disk.
	 */
J
Johannes Rieken 已提交
351
	delete(resource: URI, options?: { useTrash?: boolean, recursive?: boolean }): Promise<void>;
B
Benjamin Pasero 已提交
352 353 354 355

	/**
	 * Move a file. If the file is dirty, its contents will be preserved and restored.
	 */
J
Johannes Rieken 已提交
356
	move(source: URI, target: URI, overwrite?: boolean): Promise<void>;
B
Benjamin Pasero 已提交
357

358 359 360 361 362 363
	/**
	 * Brings up the confirm dialog to either save, don't save or cancel.
	 *
	 * @param resources the resources of the files to ask for confirmation or null if
	 * confirming for all dirty resources.
	 */
J
Johannes Rieken 已提交
364
	confirmSave(resources?: URI[]): Promise<ConfirmResult>;
365 366 367 368 369 370 371 372 373 374

	/**
	 * Convinient fast access to the current auto save mode.
	 */
	getAutoSaveMode(): AutoSaveMode;

	/**
	 * Convinient fast access to the raw configured auto save settings.
	 */
	getAutoSaveConfiguration(): IAutoSaveConfiguration;
I
isidor 已提交
375
}