UNPKG

22.4 kBTypeScriptView Raw
1import { ReadStream, WriteStream } from 'fs';
2import {
3 Disposable,
4 FileSavedEvent,
5 HandleableErrorEvent,
6 HistoryTransactionOptions,
7 HistoryTraversalOptions,
8 TextEditOptions,
9} from '../../../index';
10import {
11 FindMarkerOptions,
12 Marker,
13 MarkerLayer,
14 Point,
15 PointCompatible,
16 Range,
17 RangeCompatible,
18 TextChange,
19} from './text-buffer';
20
21export * from './display-marker';
22export * from './display-marker-layer';
23export * from './helpers';
24export * from './marker';
25export * from './marker-layer';
26export * from './point';
27export * from './range';
28
29/**
30 * A mutable text container with undo/redo support and the ability to
31 * annotate logical regions in the text.
32 */
33export class TextBuffer {
34 /** The unique identifier for this buffer. */
35 readonly id: string;
36
37 /** The number of retainers for the buffer. */
38 readonly refcount: number;
39
40 /** Whether or not the bufffer has been destroyed. */
41 readonly destroyed: boolean;
42
43 /** Create a new buffer backed by the given file path. */
44 static load(filePath: string | TextBufferFileBackend, params?: BufferLoadOptions): Promise<TextBuffer>;
45
46 /**
47 * Create a new buffer backed by the given file path. For better performance,
48 * use TextBuffer.load instead.
49 */
50 static loadSync(filePath: string, params?: BufferLoadOptions): TextBuffer;
51
52 /**
53 * Restore a TextBuffer based on an earlier state created using the
54 * TextBuffer::serialize method.
55 */
56 static deserialize(params: object): Promise<TextBuffer>;
57
58 /** Create a new buffer with the given starting text. */
59 constructor(text: string);
60 /** Create a new buffer with the given params. */
61 constructor(params?: {
62 /** The initial string text of the buffer. */
63 text?: string | undefined;
64 /**
65 * A function that returns a Boolean indicating whether the buffer should
66 * be destroyed if its file is deleted.
67 */
68 shouldDestroyOnFileDelete?(): boolean;
69 });
70
71 /** Returns a plain javascript object representation of the TextBuffer. */
72 serialize(options?: { markerLayers?: boolean | undefined; history?: boolean | undefined }): object;
73
74 /** Returns the unique identifier for this buffer. */
75 getId(): string;
76
77 // Event Subscription
78 /**
79 * Invoke the given callback synchronously before the content of the buffer
80 * changes.
81 */
82 onWillChange(callback: (event: BufferChangingEvent) => void): Disposable;
83
84 /**
85 * Invoke the given callback synchronously when the content of the buffer
86 * changes. You should probably not be using this in packages.
87 */
88 onDidChange(callback: (event: BufferChangedEvent) => void): Disposable;
89
90 /**
91 * Invoke the given callback synchronously when a transaction finishes with
92 * a list of all the changes in the transaction.
93 */
94 onDidChangeText(callback: (event: BufferStoppedChangingEvent) => void): Disposable;
95
96 /**
97 * Invoke the given callback asynchronously following one or more changes after
98 * ::getStoppedChangingDelay milliseconds elapse without an additional change.
99 */
100 onDidStopChanging(callback: (event: BufferStoppedChangingEvent) => void): Disposable;
101
102 /**
103 * Invoke the given callback when the in-memory contents of the buffer become
104 * in conflict with the contents of the file on disk.
105 */
106 onDidConflict(callback: () => void): Disposable;
107
108 /** Invoke the given callback if the value of ::isModified changes. */
109 onDidChangeModified(callback: (modified: boolean) => void): Disposable;
110
111 /**
112 * Invoke the given callback when all marker ::onDidChange observers have been
113 * notified following a change to the buffer.
114 */
115 onDidUpdateMarkers(callback: () => void): Disposable;
116
117 onDidCreateMarker(callback: (marker: Marker) => void): Disposable;
118
119 /** Invoke the given callback when the value of ::getPath changes. */
120 onDidChangePath(callback: (path: string) => void): Disposable;
121
122 /** Invoke the given callback when the value of ::getEncoding changes. */
123 onDidChangeEncoding(callback: (encoding: string) => void): Disposable;
124
125 /**
126 * Invoke the given callback before the buffer is saved to disk. If the
127 * given callback returns a promise, then the buffer will not be saved until
128 * the promise resolves.
129 */
130 onWillSave(callback: () => Promise<void> | void): Disposable;
131
132 /** Invoke the given callback after the buffer is saved to disk. */
133 onDidSave(callback: (event: FileSavedEvent) => void): Disposable;
134
135 /** Invoke the given callback after the file backing the buffer is deleted. */
136 onDidDelete(callback: () => void): Disposable;
137
138 /**
139 * Invoke the given callback before the buffer is reloaded from the contents
140 * of its file on disk.
141 */
142 onWillReload(callback: () => void): Disposable;
143
144 /**
145 * Invoke the given callback after the buffer is reloaded from the contents
146 * of its file on disk.
147 */
148 onDidReload(callback: () => void): Disposable;
149
150 /** Invoke the given callback when the buffer is destroyed. */
151 onDidDestroy(callback: () => void): Disposable;
152
153 /** Invoke the given callback when there is an error in watching the file. */
154 onWillThrowWatchError(callback: (errorObject: HandleableErrorEvent) => void): Disposable;
155
156 /**
157 * Get the number of milliseconds that will elapse without a change before
158 * ::onDidStopChanging observers are invoked following a change.
159 */
160 getStoppedChangingDelay(): number;
161
162 // File Details
163 /**
164 * Determine if the in-memory contents of the buffer differ from its contents
165 * on disk.
166 * If the buffer is unsaved, always returns true unless the buffer is empty.
167 */
168 isModified(): boolean;
169
170 /**
171 * Determine if the in-memory contents of the buffer conflict with the on-disk
172 * contents of its associated file.
173 */
174 isInConflict(): boolean;
175
176 /** Get the path of the associated file. */
177 getPath(): string | undefined;
178
179 /** Set the path for the buffer's associated file. */
180 setPath(filePath: string): void;
181
182 /** Experimental: Set a custom {TextBufferFileBackend} object as the buffer's backing store. */
183 setFile(fileBackend: TextBufferFileBackend): void;
184
185 /** Sets the character set encoding for this buffer. */
186 setEncoding(encoding: string): void;
187
188 /** Returns the string encoding of this buffer. */
189 getEncoding(): string;
190
191 /** Get the path of the associated file. */
192 getUri(): string;
193
194 // Reading Text
195 /** Determine whether the buffer is empty. */
196 isEmpty(): boolean;
197
198 /**
199 * Get the entire text of the buffer. Avoid using this unless you know that
200 * the buffer's text is reasonably short.
201 */
202 getText(): string;
203
204 /** Get the text in a range. */
205 getTextInRange(range: RangeCompatible): string;
206
207 /** Get the text of all lines in the buffer, without their line endings. */
208 getLines(): string[];
209
210 /** Get the text of the last line of the buffer, without its line ending. */
211 getLastLine(): string;
212
213 /**
214 * Get the text of the line at the given 0-indexed row, without its line ending.
215 * @param row A number representing the row.
216 */
217 lineForRow(row: number): string | undefined;
218
219 /** Get the line ending for the given 0-indexed row. */
220 lineEndingForRow(row: number): string | undefined;
221
222 /**
223 * Get the length of the line for the given 0-indexed row, without its line
224 * ending.
225 */
226 lineLengthForRow(row: number): number;
227
228 /** Determine if the given row contains only whitespace. */
229 isRowBlank(row: number): boolean;
230
231 /**
232 * Given a row, find the first preceding row that's not blank.
233 * Returns a number or null if there's no preceding non-blank row.
234 */
235 previousNonBlankRow(startRow: number): number | null;
236
237 /**
238 * Given a row, find the next row that's not blank.
239 * Returns a number or null if there's no next non-blank row.
240 */
241 nextNonBlankRow(startRow: number): number | null;
242
243 /**
244 * Return true if the buffer contains any astral-plane Unicode characters that
245 * are encoded as surrogate pairs.
246 */
247 hasAstral(): boolean;
248
249 // Mutating Text
250 /** Replace the entire contents of the buffer with the given text. */
251 setText(text: string): Range;
252
253 /**
254 * Replace the current buffer contents by applying a diff based on the
255 * given text.
256 */
257 setTextViaDiff(text: string): void;
258
259 /** Set the text in the given range. */
260 setTextInRange(range: RangeCompatible, text: string, options?: TextEditOptions): Range;
261
262 /** Insert text at the given position. */
263 insert(position: PointCompatible, text: string, options?: TextEditOptions): Range;
264
265 /** Append text to the end of the buffer. */
266 append(text: string, options?: TextEditOptions): Range;
267
268 /** Delete the text in the given range. */
269 delete(range: RangeCompatible): Range;
270
271 /**
272 * Delete the line associated with a specified 0-indexed row.
273 * @param row A number representing the row to delete.
274 */
275 deleteRow(row: number): Range;
276
277 /**
278 * Delete the lines associated with the specified 0-indexed row range.
279 *
280 * If the row range is out of bounds, it will be clipped. If the `startRow`
281 * is greater than the `endRow`, they will be reordered.
282 */
283 deleteRows(startRow: number, endRow: number): Range;
284
285 // Markers
286 /** Create a layer to contain a set of related markers. */
287 addMarkerLayer(options?: { maintainHistory?: boolean | undefined; persistent?: boolean | undefined; role?: string | undefined }): MarkerLayer;
288
289 /**
290 * Get a MarkerLayer by id.
291 * Returns a MarkerLayer or undefined if no layer exists with the given id.
292 */
293 getMarkerLayer(id: string): MarkerLayer | undefined;
294
295 /** Get the default MarkerLayer. */
296 getDefaultMarkerLayer(): MarkerLayer;
297
298 /** Create a marker with the given range in the default marker layer. */
299 markRange(
300 range: RangeCompatible,
301 properties?: {
302 reversed?: boolean | undefined;
303 invalidate?: 'never' | 'surround' | 'overlap' | 'inside' | 'touch' | undefined;
304 exclusive?: boolean | undefined;
305 },
306 ): Marker;
307
308 /** Create a marker at the given position with no tail in the default marker layer. */
309 markPosition(
310 position: PointCompatible,
311 options?: {
312 invalidate?: 'never' | 'surround' | 'overlap' | 'inside' | 'touch' | undefined;
313 exclusive?: boolean | undefined;
314 },
315 ): Marker;
316
317 /** Get all existing markers on the default marker layer. */
318 getMarkers(): Marker[];
319
320 /** Get an existing marker by its id from the default marker layer. */
321 getMarker(id: number): Marker;
322
323 /** Find markers conforming to the given parameters in the default marker layer. */
324 findMarkers(params: FindMarkerOptions): Marker[];
325
326 /** Get the number of markers in the default marker layer. */
327 getMarkerCount(): number;
328
329 // History
330 /**
331 * Undo the last operation. If a transaction is in progress, aborts it.
332 * @return A boolean of whether or not a change was made.
333 */
334 undo(options?: HistoryTraversalOptions): boolean;
335
336 /**
337 * Redo the last operation.
338 * @return A boolean of whether or not a change was made.
339 */
340 redo(options?: HistoryTraversalOptions): boolean;
341
342 /** Batch multiple operations as a single undo/redo step. */
343 transact<T>(
344 optionsOrInterval: number | ({ groupingInterval?: number | undefined } & HistoryTransactionOptions),
345 fn: () => T,
346 ): T;
347 /** Batch multiple operations as a single undo/redo step. */
348 transact<T>(fn: () => T): T;
349
350 /**
351 * Abort the currently running transaction.
352 *
353 * Only intended to be called within the `fn` option to `::transact`.
354 */
355 abortTransaction(): void;
356
357 /** Clear the undo stack. */
358 clearUndoStack(): void;
359
360 /**
361 * Create a pointer to the current state of the buffer for use with
362 * `::revertToCheckpoint` and `::groupChangesSinceCheckpoint`.
363 * @return A checkpoint ID value.
364 */
365 createCheckpoint(options?: HistoryTransactionOptions): number;
366
367 /**
368 * Revert the buffer to the state it was in when the given checkpoint was created.
369 * @return A boolean indicating whether the operation succeeded.
370 */
371 revertToCheckpoint(checkpoint: number, options?: HistoryTraversalOptions): boolean;
372
373 /**
374 * Group all changes since the given checkpoint into a single transaction for
375 * purposes of undo/redo.
376 * @return A boolean indicating whether the operation succeeded.
377 */
378 groupChangesSinceCheckpoint(checkpoint: number, options?: HistoryTransactionOptions): boolean;
379
380 /**
381 * Group the last two text changes for purposes of undo/redo.
382 *
383 * This operation will only succeed if there are two changes on the undo stack.
384 * It will not group past the beginning of an open transaction.
385 * @return A boolean indicating whether the operation succeeded.
386 */
387 groupLastChanges(): boolean;
388
389 /**
390 * Returns a list of changes since the given checkpoint.
391 * If the given checkpoint is no longer present in the undo history, this method
392 * will return an empty Array.
393 */
394 getChangesSinceCheckpoint(
395 checkpoint: number,
396 ): Array<{
397 /** A Point representing where the change started. */
398 start: Point;
399
400 /** A Point representing the replaced extent. */
401 oldExtent: Point;
402
403 /** A Point representing the replacement extent. */
404 newExtent: Point;
405
406 /** A String representing the replacement text. */
407 newText: string;
408 }>;
409
410 // Search and Replace
411 /**
412 * Scan regular expression matches in the entire buffer, calling the given
413 * iterator function on each match.
414 */
415 scan(regex: RegExp, iterator: (params: BufferScanResult) => void): void;
416 /**
417 * Scan regular expression matches in the entire buffer, calling the given
418 * iterator function on each match.
419 */
420 scan(regex: RegExp, options: ScanContextOptions, iterator: (params: ContextualBufferScanResult) => void): void;
421
422 /**
423 * Scan regular expression matches in the entire buffer in reverse order,
424 * calling the given iterator function on each match.
425 */
426 backwardsScan(regex: RegExp, iterator: (params: BufferScanResult) => void): void;
427 /**
428 * Scan regular expression matches in the entire buffer in reverse order,
429 * calling the given iterator function on each match.
430 */
431 backwardsScan(
432 regex: RegExp,
433 options: ScanContextOptions,
434 iterator: (params: ContextualBufferScanResult) => void,
435 ): void;
436
437 /**
438 * Scan regular expression matches in a given range , calling the given
439 * iterator function on each match.
440 */
441 scanInRange(regex: RegExp, range: RangeCompatible, iterator: (params: BufferScanResult) => void): void;
442 /**
443 * Scan regular expression matches in a given range , calling the given
444 * iterator function on each match.
445 */
446 scanInRange(
447 regex: RegExp,
448 range: RangeCompatible,
449 options: ScanContextOptions,
450 iterator: (params: ContextualBufferScanResult) => void,
451 ): void;
452
453 /**
454 * Scan regular expression matches in a given range in reverse order,
455 * calling the given iterator function on each match.
456 */
457 backwardsScanInRange(regex: RegExp, range: RangeCompatible, iterator: (params: BufferScanResult) => void): void;
458 /**
459 * Scan regular expression matches in a given range in reverse order,
460 * calling the given iterator function on each match.
461 */
462 backwardsScanInRange(
463 regex: RegExp,
464 range: RangeCompatible,
465 options: ScanContextOptions,
466 iterator: (params: ContextualBufferScanResult) => void,
467 ): void;
468
469 /** Replace all regular expression matches in the entire buffer. */
470 replace(regex: RegExp, replacementText: string): number;
471
472 // Buffer Range Details
473 /** Get the range spanning from [0, 0] to ::getEndPosition. */
474 getRange(): Range;
475
476 /** Get the number of lines in the buffer. */
477 getLineCount(): number;
478
479 /** Get the last 0-indexed row in the buffer. */
480 getLastRow(): number;
481
482 /** Get the first position in the buffer, which is always [0, 0]. */
483 getFirstPosition(): Point;
484
485 /** Get the maximal position in the buffer, where new text would be appended. */
486 getEndPosition(): Point;
487
488 /** Get the length of the buffer's text. */
489 getLength(): number;
490
491 /** Get the length of the buffer in characters. */
492 getMaxCharacterIndex(): number;
493
494 /**
495 * Get the range for the given row.
496 * @param row A number representing a 0-indexed row.
497 * @param includeNewline A boolean indicating whether or not to include the
498 * newline, which results in a range that extends to the start of the next line.
499 * (default: false)
500 */
501 rangeForRow(row: number, includeNewline?: boolean): Range;
502
503 /**
504 * Convert a position in the buffer in row/column coordinates to an absolute
505 * character offset, inclusive of line ending characters.
506 */
507 characterIndexForPosition(position: PointCompatible): number;
508
509 /**
510 * Convert an absolute character offset, inclusive of newlines, to a position
511 * in the buffer in row/column coordinates.
512 */
513 positionForCharacterIndex(offset: number): Point;
514
515 /** Clip the given range so it starts and ends at valid positions. */
516 clipRange(range: RangeCompatible): Range;
517
518 /** Clip the given point so it is at a valid position in the buffer. */
519 clipPosition(position: PointCompatible): Point;
520
521 // Buffer Operations
522 /** Save the buffer. */
523 save(): Promise<void>;
524
525 /** Save the buffer at a specific path. */
526 saveAs(filePath: string): Promise<void>;
527
528 /** Reload the buffer's contents from disk. */
529 reload(): void;
530
531 /** Destroy the buffer, even if there are retainers for it. */
532 destroy(): void;
533
534 /** Returns whether or not this buffer is alive. */
535 isAlive(): boolean;
536
537 /** Returns whether or not this buffer has been destroyed. */
538 isDestroyed(): boolean;
539
540 /** Returns whether or not this buffer has a retainer. */
541 isRetained(): boolean;
542
543 /**
544 * Places a retainer on the buffer, preventing its destruction until the
545 * final retainer has called ::release().
546 */
547 retain(): TextBuffer;
548
549 /**
550 * Releases a retainer on the buffer, destroying the buffer if there are
551 * no additional retainers.
552 */
553 release(): TextBuffer;
554
555 /** Identifies if the buffer belongs to multiple editors. */
556 hasMultipleEditors(): boolean;
557}
558
559export interface TextBufferFileBackend {
560 /** A {Function} that returns the {String} path to the file. */
561 getPath(): string;
562
563 /**
564 * A {Function} that returns a `Readable` stream
565 * that can be used to load the file's content.
566 */
567 createReadStream(): ReadStream;
568
569 /**
570 * A {Function} that returns a `Writable` stream
571 * that can be used to save content to the file.
572 */
573 createWriteStream(): WriteStream;
574
575 /** A {Function} that returns a {Boolean}, true if the file exists, false otherwise. */
576 existsSync(): boolean;
577
578 /**
579 * A {Function} that invokes its callback argument
580 * when the file changes. The method should return a {Disposable} that
581 * can be used to prevent further calls to the callback.
582 */
583 onDidChange?(callback: () => void): Disposable;
584
585 /**
586 * A {Function} that invokes its callback argument
587 * when the file is deleted. The method should return a {Disposable} that
588 * can be used to prevent further calls to the callback.
589 */
590 onDidDelete?(callback: () => void): Disposable;
591 /**
592 * A {Function} that invokes its callback argument
593 * when the file is renamed. The method should return a {Disposable} that
594 * can be used to prevent further calls to the callback.
595 */
596 onDidRename?(callback: () => void): Disposable;
597}
598
599export interface BufferChangingEvent {
600 /** Range of the old text. */
601 oldRange: Range;
602}
603
604export interface BufferChangedEvent {
605 /**
606 * An array of objects summarizing the aggregated changes that occurred
607 * during the transaction.
608 */
609 changes: Array<{
610 /**
611 * The Range of the deleted text in the contents of the buffer as it existed
612 * before the batch of changes reported by this event.
613 */
614 oldRange: Range;
615
616 /** The Range of the inserted text in the current contents of the buffer. */
617 newRange: Range;
618 }>;
619
620 /** Range of the old text. */
621 oldRange: Range;
622
623 /** Range of the new text. */
624 newRange: Range;
625
626 /** String containing the text that was replaced. */
627 oldText: string;
628
629 /** String containing the text that was inserted. */
630 newText: string;
631}
632
633export interface BufferStoppedChangingEvent {
634 changes: TextChange[];
635}
636
637export interface BufferLoadOptions {
638 /** The file's encoding. */
639 encoding?: string | undefined;
640
641 /**
642 * A function that returns a boolean indicating whether the buffer should
643 * be destroyed if its file is deleted.
644 */
645 shouldDestroyOnFileDelete?(): boolean;
646}
647
648export interface BufferScanResult {
649 buffer: TextBuffer;
650 lineText: string;
651 match: RegExpExecArray;
652 matchText: string;
653 range: Range;
654 replace(replacementText: string): void;
655 stop(): void;
656 stopped: boolean;
657}
658
659export interface ContextualBufferScanResult extends BufferScanResult {
660 leadingContextLines: string[];
661 trailingContextLines: string[];
662}
663
664export interface ScanContextOptions {
665 /** The number of lines before the matched line to include in the results object. */
666 leadingContextLineCount?: number | undefined;
667
668 /** The number of lines after the matched line to include in the results object. */
669 trailingContextLineCount?: number | undefined;
670}
671
\No newline at end of file