UNPKG

22.5 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(
288 options?: {
289 maintainHistory?: boolean | undefined;
290 persistent?: boolean | undefined;
291 role?: string | undefined;
292 },
293 ): MarkerLayer;
294
295 /**
296 * Get a MarkerLayer by id.
297 * Returns a MarkerLayer or undefined if no layer exists with the given id.
298 */
299 getMarkerLayer(id: string): MarkerLayer | undefined;
300
301 /** Get the default MarkerLayer. */
302 getDefaultMarkerLayer(): MarkerLayer;
303
304 /** Create a marker with the given range in the default marker layer. */
305 markRange(
306 range: RangeCompatible,
307 properties?: {
308 reversed?: boolean | undefined;
309 invalidate?: "never" | "surround" | "overlap" | "inside" | "touch" | undefined;
310 exclusive?: boolean | undefined;
311 },
312 ): Marker;
313
314 /** Create a marker at the given position with no tail in the default marker layer. */
315 markPosition(
316 position: PointCompatible,
317 options?: {
318 invalidate?: "never" | "surround" | "overlap" | "inside" | "touch" | undefined;
319 exclusive?: boolean | undefined;
320 },
321 ): Marker;
322
323 /** Get all existing markers on the default marker layer. */
324 getMarkers(): Marker[];
325
326 /** Get an existing marker by its id from the default marker layer. */
327 getMarker(id: number): Marker;
328
329 /** Find markers conforming to the given parameters in the default marker layer. */
330 findMarkers(params: FindMarkerOptions): Marker[];
331
332 /** Get the number of markers in the default marker layer. */
333 getMarkerCount(): number;
334
335 // History
336 /**
337 * Undo the last operation. If a transaction is in progress, aborts it.
338 * @return A boolean of whether or not a change was made.
339 */
340 undo(options?: HistoryTraversalOptions): boolean;
341
342 /**
343 * Redo the last operation.
344 * @return A boolean of whether or not a change was made.
345 */
346 redo(options?: HistoryTraversalOptions): boolean;
347
348 /** Batch multiple operations as a single undo/redo step. */
349 transact<T>(
350 optionsOrInterval: number | ({ groupingInterval?: number | undefined } & HistoryTransactionOptions),
351 fn: () => T,
352 ): T;
353 /** Batch multiple operations as a single undo/redo step. */
354 transact<T>(fn: () => T): T;
355
356 /**
357 * Abort the currently running transaction.
358 *
359 * Only intended to be called within the `fn` option to `::transact`.
360 */
361 abortTransaction(): void;
362
363 /** Clear the undo stack. */
364 clearUndoStack(): void;
365
366 /**
367 * Create a pointer to the current state of the buffer for use with
368 * `::revertToCheckpoint` and `::groupChangesSinceCheckpoint`.
369 * @return A checkpoint ID value.
370 */
371 createCheckpoint(options?: HistoryTransactionOptions): number;
372
373 /**
374 * Revert the buffer to the state it was in when the given checkpoint was created.
375 * @return A boolean indicating whether the operation succeeded.
376 */
377 revertToCheckpoint(checkpoint: number, options?: HistoryTraversalOptions): boolean;
378
379 /**
380 * Group all changes since the given checkpoint into a single transaction for
381 * purposes of undo/redo.
382 * @return A boolean indicating whether the operation succeeded.
383 */
384 groupChangesSinceCheckpoint(checkpoint: number, options?: HistoryTransactionOptions): boolean;
385
386 /**
387 * Group the last two text changes for purposes of undo/redo.
388 *
389 * This operation will only succeed if there are two changes on the undo stack.
390 * It will not group past the beginning of an open transaction.
391 * @return A boolean indicating whether the operation succeeded.
392 */
393 groupLastChanges(): boolean;
394
395 /**
396 * Returns a list of changes since the given checkpoint.
397 * If the given checkpoint is no longer present in the undo history, this method
398 * will return an empty Array.
399 */
400 getChangesSinceCheckpoint(
401 checkpoint: number,
402 ): Array<{
403 /** A Point representing where the change started. */
404 start: Point;
405
406 /** A Point representing the replaced extent. */
407 oldExtent: Point;
408
409 /** A Point representing the replacement extent. */
410 newExtent: Point;
411
412 /** A String representing the replacement text. */
413 newText: string;
414 }>;
415
416 // Search and Replace
417 /**
418 * Scan regular expression matches in the entire buffer, calling the given
419 * iterator function on each match.
420 */
421 scan(regex: RegExp, iterator: (params: BufferScanResult) => void): void;
422 /**
423 * Scan regular expression matches in the entire buffer, calling the given
424 * iterator function on each match.
425 */
426 scan(regex: RegExp, options: ScanContextOptions, iterator: (params: ContextualBufferScanResult) => void): void;
427
428 /**
429 * Scan regular expression matches in the entire buffer in reverse order,
430 * calling the given iterator function on each match.
431 */
432 backwardsScan(regex: RegExp, iterator: (params: BufferScanResult) => void): void;
433 /**
434 * Scan regular expression matches in the entire buffer in reverse order,
435 * calling the given iterator function on each match.
436 */
437 backwardsScan(
438 regex: RegExp,
439 options: ScanContextOptions,
440 iterator: (params: ContextualBufferScanResult) => void,
441 ): void;
442
443 /**
444 * Scan regular expression matches in a given range , calling the given
445 * iterator function on each match.
446 */
447 scanInRange(regex: RegExp, range: RangeCompatible, iterator: (params: BufferScanResult) => void): void;
448 /**
449 * Scan regular expression matches in a given range , calling the given
450 * iterator function on each match.
451 */
452 scanInRange(
453 regex: RegExp,
454 range: RangeCompatible,
455 options: ScanContextOptions,
456 iterator: (params: ContextualBufferScanResult) => void,
457 ): void;
458
459 /**
460 * Scan regular expression matches in a given range in reverse order,
461 * calling the given iterator function on each match.
462 */
463 backwardsScanInRange(regex: RegExp, range: RangeCompatible, iterator: (params: BufferScanResult) => void): void;
464 /**
465 * Scan regular expression matches in a given range in reverse order,
466 * calling the given iterator function on each match.
467 */
468 backwardsScanInRange(
469 regex: RegExp,
470 range: RangeCompatible,
471 options: ScanContextOptions,
472 iterator: (params: ContextualBufferScanResult) => void,
473 ): void;
474
475 /** Replace all regular expression matches in the entire buffer. */
476 replace(regex: RegExp, replacementText: string): number;
477
478 // Buffer Range Details
479 /** Get the range spanning from [0, 0] to ::getEndPosition. */
480 getRange(): Range;
481
482 /** Get the number of lines in the buffer. */
483 getLineCount(): number;
484
485 /** Get the last 0-indexed row in the buffer. */
486 getLastRow(): number;
487
488 /** Get the first position in the buffer, which is always [0, 0]. */
489 getFirstPosition(): Point;
490
491 /** Get the maximal position in the buffer, where new text would be appended. */
492 getEndPosition(): Point;
493
494 /** Get the length of the buffer's text. */
495 getLength(): number;
496
497 /** Get the length of the buffer in characters. */
498 getMaxCharacterIndex(): number;
499
500 /**
501 * Get the range for the given row.
502 * @param row A number representing a 0-indexed row.
503 * @param includeNewline A boolean indicating whether or not to include the
504 * newline, which results in a range that extends to the start of the next line.
505 * (default: false)
506 */
507 rangeForRow(row: number, includeNewline?: boolean): Range;
508
509 /**
510 * Convert a position in the buffer in row/column coordinates to an absolute
511 * character offset, inclusive of line ending characters.
512 */
513 characterIndexForPosition(position: PointCompatible): number;
514
515 /**
516 * Convert an absolute character offset, inclusive of newlines, to a position
517 * in the buffer in row/column coordinates.
518 */
519 positionForCharacterIndex(offset: number): Point;
520
521 /** Clip the given range so it starts and ends at valid positions. */
522 clipRange(range: RangeCompatible): Range;
523
524 /** Clip the given point so it is at a valid position in the buffer. */
525 clipPosition(position: PointCompatible): Point;
526
527 // Buffer Operations
528 /** Save the buffer. */
529 save(): Promise<void>;
530
531 /** Save the buffer at a specific path. */
532 saveAs(filePath: string): Promise<void>;
533
534 /** Reload the buffer's contents from disk. */
535 reload(): void;
536
537 /** Destroy the buffer, even if there are retainers for it. */
538 destroy(): void;
539
540 /** Returns whether or not this buffer is alive. */
541 isAlive(): boolean;
542
543 /** Returns whether or not this buffer has been destroyed. */
544 isDestroyed(): boolean;
545
546 /** Returns whether or not this buffer has a retainer. */
547 isRetained(): boolean;
548
549 /**
550 * Places a retainer on the buffer, preventing its destruction until the
551 * final retainer has called ::release().
552 */
553 retain(): TextBuffer;
554
555 /**
556 * Releases a retainer on the buffer, destroying the buffer if there are
557 * no additional retainers.
558 */
559 release(): TextBuffer;
560
561 /** Identifies if the buffer belongs to multiple editors. */
562 hasMultipleEditors(): boolean;
563}
564
565export interface TextBufferFileBackend {
566 /** A {Function} that returns the {String} path to the file. */
567 getPath(): string;
568
569 /**
570 * A {Function} that returns a `Readable` stream
571 * that can be used to load the file's content.
572 */
573 createReadStream(): ReadStream;
574
575 /**
576 * A {Function} that returns a `Writable` stream
577 * that can be used to save content to the file.
578 */
579 createWriteStream(): WriteStream;
580
581 /** A {Function} that returns a {Boolean}, true if the file exists, false otherwise. */
582 existsSync(): boolean;
583
584 /**
585 * A {Function} that invokes its callback argument
586 * when the file changes. The method should return a {Disposable} that
587 * can be used to prevent further calls to the callback.
588 */
589 onDidChange?(callback: () => void): Disposable;
590
591 /**
592 * A {Function} that invokes its callback argument
593 * when the file is deleted. The method should return a {Disposable} that
594 * can be used to prevent further calls to the callback.
595 */
596 onDidDelete?(callback: () => void): Disposable;
597 /**
598 * A {Function} that invokes its callback argument
599 * when the file is renamed. The method should return a {Disposable} that
600 * can be used to prevent further calls to the callback.
601 */
602 onDidRename?(callback: () => void): Disposable;
603}
604
605export interface BufferChangingEvent {
606 /** Range of the old text. */
607 oldRange: Range;
608}
609
610export interface BufferChangedEvent {
611 /**
612 * An array of objects summarizing the aggregated changes that occurred
613 * during the transaction.
614 */
615 changes: Array<{
616 /**
617 * The Range of the deleted text in the contents of the buffer as it existed
618 * before the batch of changes reported by this event.
619 */
620 oldRange: Range;
621
622 /** The Range of the inserted text in the current contents of the buffer. */
623 newRange: Range;
624 }>;
625
626 /** Range of the old text. */
627 oldRange: Range;
628
629 /** Range of the new text. */
630 newRange: Range;
631
632 /** String containing the text that was replaced. */
633 oldText: string;
634
635 /** String containing the text that was inserted. */
636 newText: string;
637}
638
639export interface BufferStoppedChangingEvent {
640 changes: TextChange[];
641}
642
643export interface BufferLoadOptions {
644 /** The file's encoding. */
645 encoding?: string | undefined;
646
647 /**
648 * A function that returns a boolean indicating whether the buffer should
649 * be destroyed if its file is deleted.
650 */
651 shouldDestroyOnFileDelete?(): boolean;
652}
653
654export interface BufferScanResult {
655 buffer: TextBuffer;
656 lineText: string;
657 match: RegExpExecArray;
658 matchText: string;
659 range: Range;
660 replace(replacementText: string): void;
661 stop(): void;
662 stopped: boolean;
663}
664
665export interface ContextualBufferScanResult extends BufferScanResult {
666 leadingContextLines: string[];
667 trailingContextLines: string[];
668}
669
670export interface ScanContextOptions {
671 /** The number of lines before the matched line to include in the results object. */
672 leadingContextLineCount?: number | undefined;
673
674 /** The number of lines after the matched line to include in the results object. */
675 trailingContextLineCount?: number | undefined;
676}
677
\No newline at end of file