UNPKG

simple-text-buffer

Version:

A version of Atom's text-buffer with marker layers and file support removed

968 lines (833 loc) 31.6 kB
(function() { var CompositeDisposable, Disposable, Emitter, History, MatchIterator, Patch, Point, Range, SearchCallbackArgument, SpanSkipList, TextBuffer, TransactionAbortedError, crypto, diff, newlineRegex, normalizePatchChanges, ref, ref1, spliceArray, bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; }, hasProp = {}.hasOwnProperty; ref = require('event-kit'), Emitter = ref.Emitter, CompositeDisposable = ref.CompositeDisposable, Disposable = ref.Disposable; SpanSkipList = require('span-skip-list'); diff = require('diff'); crypto = require('crypto'); Patch = require('atom-patch'); Point = require('./point'); Range = require('./range'); History = require('./history'); MatchIterator = require('./match-iterator'); ref1 = require('./helpers'), spliceArray = ref1.spliceArray, newlineRegex = ref1.newlineRegex, normalizePatchChanges = ref1.normalizePatchChanges; SearchCallbackArgument = (function() { Object.defineProperty(SearchCallbackArgument.prototype, "range", { get: function() { var endPosition, matchEndIndex, matchStartIndex, startPosition; if (this.computedRange != null) { return this.computedRange; } matchStartIndex = this.match.index; matchEndIndex = matchStartIndex + this.matchText.length; startPosition = this.buffer.positionForCharacterIndex(matchStartIndex + this.lengthDelta); endPosition = this.buffer.positionForCharacterIndex(matchEndIndex + this.lengthDelta); return this.computedRange = new Range(startPosition, endPosition); }, set: function(range) { return this.computedRange = range; } }); function SearchCallbackArgument(buffer1, match1, lengthDelta1) { this.buffer = buffer1; this.match = match1; this.lengthDelta = lengthDelta1; this.stop = bind(this.stop, this); this.replace = bind(this.replace, this); this.stopped = false; this.replacementText = null; this.matchText = this.match[0]; } SearchCallbackArgument.prototype.getReplacementDelta = function() { if (this.replacementText == null) { return 0; } return this.replacementText.length - this.matchText.length; }; SearchCallbackArgument.prototype.replace = function(text) { this.replacementText = text; return this.buffer.setTextInRange(this.range, this.replacementText); }; SearchCallbackArgument.prototype.stop = function() { return this.stopped = true; }; SearchCallbackArgument.prototype.keepLooping = function() { return this.stopped === false; }; return SearchCallbackArgument; })(); TransactionAbortedError = (function(superClass) { extend(TransactionAbortedError, superClass); function TransactionAbortedError() { TransactionAbortedError.__super__.constructor.apply(this, arguments); } return TransactionAbortedError; })(Error); module.exports = TextBuffer = (function() { TextBuffer.version = 5; TextBuffer.Point = Point; TextBuffer.Range = Range; TextBuffer.Patch = require('./patch'); TextBuffer.newlineRegex = newlineRegex; TextBuffer.prototype.cachedText = null; TextBuffer.prototype.encoding = null; TextBuffer.prototype.stoppedChangingDelay = 300; TextBuffer.prototype.stoppedChangingTimeout = null; TextBuffer.prototype.refcount = 0; TextBuffer.prototype.backwardsScanChunkSize = 8000; TextBuffer.prototype.defaultMaxUndoEntries = 10000; TextBuffer.prototype.changeCount = 0; /* Section: Construction */ function TextBuffer(params) { var maxUndoEntries, ref2, ref3, ref4, ref5, text; this.eventIdCounter = 0; if (typeof params === 'string') { text = params; } this.emitter = new Emitter; this.patchesSinceLastStoppedChangingEvent = []; this.id = (ref2 = params != null ? params.id : void 0) != null ? ref2 : crypto.randomBytes(16).toString('hex'); this.lines = ['']; this.lineEndings = ['']; this.offsetIndex = new SpanSkipList('rows', 'characters'); this.setTextInRange([[0, 0], [0, 0]], (ref3 = text != null ? text : params != null ? params.text : void 0) != null ? ref3 : '', { normalizeLineEndings: false }); maxUndoEntries = (ref4 = params != null ? params.maxUndoEntries : void 0) != null ? ref4 : this.defaultMaxUndoEntries; this.history = (ref5 = params != null ? params.history : void 0) != null ? ref5 : new History(this, maxUndoEntries); this.setEncoding(params != null ? params.encoding : void 0); this.setPreferredLineEnding(params != null ? params.preferredLineEnding : void 0); this.transactCallDepth = 0; } TextBuffer.deserialize = function(params) { var buffer; if (params.version !== TextBuffer.prototype.version) { return; } buffer = Object.create(TextBuffer.prototype); params.history = History.deserialize(params.history, buffer); TextBuffer.call(buffer, params); return buffer; }; TextBuffer.prototype.getId = function() { return this.id; }; TextBuffer.prototype.serialize = function(options) { if (options == null) { options = {}; } return { id: this.getId(), text: this.getText(), history: this.history.serialize(options), encoding: this.getEncoding(), preferredLineEnding: this.preferredLineEnding }; }; /* Section: Event Subscription */ TextBuffer.prototype.onWillChange = function(callback) { return this.emitter.on('will-change', callback); }; TextBuffer.prototype.onDidChange = function(callback) { return this.emitter.on('did-change', callback); }; TextBuffer.prototype.onDidChangeText = function(callback) { return this.emitter.on('did-change-text', callback); }; TextBuffer.prototype.preemptDidChange = function(callback) { return this.emitter.preempt('did-change', callback); }; TextBuffer.prototype.onDidStopChanging = function(callback) { return this.emitter.on('did-stop-changing', callback); }; TextBuffer.prototype.onDidChangeEncoding = function(callback) { return this.emitter.on('did-change-encoding', callback); }; TextBuffer.prototype.onDidDestroy = function(callback) { return this.emitter.on('did-destroy', callback); }; TextBuffer.prototype.getStoppedChangingDelay = function() { return this.stoppedChangingDelay; }; /* Section: File Details */ TextBuffer.prototype.setEncoding = function(encoding) { if (encoding == null) { encoding = 'utf8'; } if (encoding === this.getEncoding()) { return; } this.encoding = encoding; this.emitter.emit('did-change-encoding', encoding); }; TextBuffer.prototype.getEncoding = function() { return this.encoding; }; TextBuffer.prototype.setPreferredLineEnding = function(preferredLineEnding) { if (preferredLineEnding == null) { preferredLineEnding = null; } return this.preferredLineEnding = preferredLineEnding; }; TextBuffer.prototype.getPreferredLineEnding = function() { return this.preferredLineEnding; }; /* Section: Reading Text */ TextBuffer.prototype.isEmpty = function() { return this.getLastRow() === 0 && this.lineLengthForRow(0) === 0; }; TextBuffer.prototype.getText = function() { var i, ref2, row, text; if (this.cachedText != null) { return this.cachedText; } else { text = ''; for (row = i = 0, ref2 = this.getLastRow(); 0 <= ref2 ? i <= ref2 : i >= ref2; row = 0 <= ref2 ? ++i : --i) { text += this.lineForRow(row) + this.lineEndingForRow(row); } return this.cachedText = text; } }; TextBuffer.prototype.getTextInRange = function(range) { var endRow, i, line, ref2, ref3, row, startRow, text; range = this.clipRange(Range.fromObject(range)); startRow = range.start.row; endRow = range.end.row; if (startRow === endRow) { return this.lineForRow(startRow).slice(range.start.column, range.end.column); } else { text = ''; for (row = i = ref2 = startRow, ref3 = endRow; ref2 <= ref3 ? i <= ref3 : i >= ref3; row = ref2 <= ref3 ? ++i : --i) { line = this.lineForRow(row); if (row === startRow) { text += line.slice(range.start.column); } else if (row === endRow) { text += line.slice(0, range.end.column); continue; } else { text += line; } text += this.lineEndingForRow(row); } return text; } }; TextBuffer.prototype.getLines = function() { return this.lines.slice(); }; TextBuffer.prototype.getLastLine = function() { return this.lineForRow(this.getLastRow()); }; TextBuffer.prototype.lineForRow = function(row) { return this.lines[row]; }; TextBuffer.prototype.lineEndingForRow = function(row) { return this.lineEndings[row]; }; TextBuffer.prototype.lineLengthForRow = function(row) { return this.lines[row].length; }; TextBuffer.prototype.isRowBlank = function(row) { return !/\S/.test(this.lineForRow(row)); }; TextBuffer.prototype.previousNonBlankRow = function(startRow) { var i, ref2, row; if (startRow === 0) { return null; } startRow = Math.min(startRow, this.getLastRow()); for (row = i = ref2 = startRow - 1; ref2 <= 0 ? i <= 0 : i >= 0; row = ref2 <= 0 ? ++i : --i) { if (!this.isRowBlank(row)) { return row; } } return null; }; TextBuffer.prototype.nextNonBlankRow = function(startRow) { var i, lastRow, ref2, ref3, row; lastRow = this.getLastRow(); if (startRow < lastRow) { for (row = i = ref2 = startRow + 1, ref3 = lastRow; ref2 <= ref3 ? i <= ref3 : i >= ref3; row = ref2 <= ref3 ? ++i : --i) { if (!this.isRowBlank(row)) { return row; } } } return null; }; /* Section: Mutating Text */ TextBuffer.prototype.setText = function(text) { return this.setTextInRange(this.getRange(), text, { normalizeLineEndings: false }); }; TextBuffer.prototype.setTextViaDiff = function(text) { var computeBufferColumn, currentText, endsWithNewline; currentText = this.getText(); if (currentText === text) { return; } endsWithNewline = function(str) { return /[\r\n]+$/g.test(str); }; computeBufferColumn = function(str) { var newlineIndex; newlineIndex = Math.max(str.lastIndexOf('\n'), str.lastIndexOf('\r')); if (endsWithNewline(str)) { return 0; } else if (newlineIndex === -1) { return str.length; } else { return str.length - newlineIndex - 1; } }; return this.transact((function(_this) { return function() { var change, changeOptions, column, currentPosition, endColumn, endRow, i, len, lineCount, lineDiff, ref2, ref3, row; row = 0; column = 0; currentPosition = [0, 0]; lineDiff = diff.diffLines(currentText, text); changeOptions = { normalizeLineEndings: false }; for (i = 0, len = lineDiff.length; i < len; i++) { change = lineDiff[i]; lineCount = (ref2 = (ref3 = change.value.match(newlineRegex)) != null ? ref3.length : void 0) != null ? ref2 : 0; currentPosition[0] = row; currentPosition[1] = column; if (change.added) { row += lineCount; column = computeBufferColumn(change.value); _this.setTextInRange([currentPosition, currentPosition], change.value, changeOptions); } else if (change.removed) { endRow = row + lineCount; endColumn = column + computeBufferColumn(change.value); _this.setTextInRange([currentPosition, [endRow, endColumn]], '', changeOptions); } else { row += lineCount; column = computeBufferColumn(change.value); } } }; })(this)); }; TextBuffer.prototype.setTextInRange = function(range, newText, options) { var change, newRange, normalizeLineEndings, oldRange, oldText, ref2, undo; if (this.transactCallDepth === 0) { return this.transact((function(_this) { return function() { return _this.setTextInRange(range, newText, options); }; })(this)); } if (options != null) { normalizeLineEndings = options.normalizeLineEndings, undo = options.undo; } if (normalizeLineEndings == null) { normalizeLineEndings = true; } oldRange = this.clipRange(range); oldText = this.getTextInRange(oldRange); newRange = Range.fromText(oldRange.start, newText); change = { newStart: oldRange.start, oldExtent: oldRange.getExtent(), newExtent: newRange.getExtent(), oldText: oldText, newText: newText, normalizeLineEndings: normalizeLineEndings }; if (undo !== 'skip') { if ((ref2 = this.history) != null) { ref2.pushChange(change); } } this.applyChange(change); return newRange; }; TextBuffer.prototype.insert = function(position, text, options) { return this.setTextInRange(new Range(position, position), text, options); }; TextBuffer.prototype.append = function(text, options) { return this.insert(this.getEndPosition(), text, options); }; TextBuffer.prototype.applyChange = function(change) { var changeEvent, endRow, ending, lastIndex, lastLine, lastLineEnding, line, lineEndings, lineStartIndex, lines, newExtent, newRange, newStart, newText, normalizeLineEndings, normalizedEnding, normalizedNewText, offsets, oldExtent, oldRange, oldText, prefix, ref2, result, rowCount, start, startRow, suffix; newStart = change.newStart, oldExtent = change.oldExtent, newExtent = change.newExtent, oldText = change.oldText, newText = change.newText, normalizeLineEndings = change.normalizeLineEndings; start = Point.fromObject(newStart); oldRange = Range(start, start.traverse(oldExtent)); newRange = Range(start, start.traverse(newExtent)); oldRange.freeze(); newRange.freeze(); this.cachedText = null; startRow = oldRange.start.row; endRow = oldRange.end.row; rowCount = endRow - startRow + 1; if (normalizeLineEndings) { normalizedEnding = (ref2 = this.preferredLineEnding) != null ? ref2 : this.lineEndingForRow(startRow); if (!normalizedEnding) { if (startRow > 0) { normalizedEnding = this.lineEndingForRow(startRow - 1); } else { normalizedEnding = null; } } } lines = []; lineEndings = []; lineStartIndex = 0; normalizedNewText = ""; while (result = newlineRegex.exec(newText)) { line = newText.slice(lineStartIndex, result.index); ending = normalizedEnding != null ? normalizedEnding : result[0]; lines.push(line); lineEndings.push(ending); normalizedNewText += line + ending; lineStartIndex = newlineRegex.lastIndex; } lastLine = newText.slice(lineStartIndex); lines.push(lastLine); lineEndings.push(''); normalizedNewText += lastLine; newText = normalizedNewText; changeEvent = Object.freeze({ oldRange: oldRange, newRange: newRange, oldText: oldText, newText: newText, eventId: this.eventIdCounter++ }); this.emitter.emit('will-change', changeEvent); prefix = this.lineForRow(startRow).slice(0, oldRange.start.column); lines[0] = prefix + lines[0]; suffix = this.lineForRow(endRow).slice(oldRange.end.column); lastIndex = lines.length - 1; lines[lastIndex] += suffix; lastLineEnding = this.lineEndingForRow(endRow); if (lastLineEnding !== '' && (normalizedEnding != null)) { lastLineEnding = normalizedEnding; } lineEndings[lastIndex] = lastLineEnding; spliceArray(this.lines, startRow, rowCount, lines); spliceArray(this.lineEndings, startRow, rowCount, lineEndings); offsets = lines.map(function(line, index) { return { rows: 1, characters: line.length + lineEndings[index].length }; }); this.offsetIndex.spliceArray('rows', startRow, rowCount, offsets); this.changeCount++; return this.emitDidChangeEvent(changeEvent); }; TextBuffer.prototype.emitDidChangeEvent = function(changeEvent) { return this.emitter.emit('did-change', changeEvent); }; TextBuffer.prototype["delete"] = function(range) { return this.setTextInRange(range, ''); }; TextBuffer.prototype.deleteRow = function(row) { return this.deleteRows(row, row); }; TextBuffer.prototype.deleteRows = function(startRow, endRow) { var endPoint, lastRow, ref2, startPoint; lastRow = this.getLastRow(); if (startRow > endRow) { ref2 = [endRow, startRow], startRow = ref2[0], endRow = ref2[1]; } if (endRow < 0) { return new Range(this.getFirstPosition(), this.getFirstPosition()); } if (startRow > lastRow) { return new Range(this.getEndPosition(), this.getEndPosition()); } startRow = Math.max(0, startRow); endRow = Math.min(lastRow, endRow); if (endRow < lastRow) { startPoint = new Point(startRow, 0); endPoint = new Point(endRow + 1, 0); } else { if (startRow === 0) { startPoint = new Point(startRow, 0); } else { startPoint = new Point(startRow - 1, this.lineLengthForRow(startRow - 1)); } endPoint = new Point(endRow, this.lineLengthForRow(endRow)); } return this["delete"](new Range(startPoint, endPoint)); }; /* Section: History */ TextBuffer.prototype.undo = function() { var change, i, len, pop, ref2; if (pop = this.history.popUndoStack()) { ref2 = pop.patch.getChanges(); for (i = 0, len = ref2.length; i < len; i++) { change = ref2[i]; this.applyChange(change); } this.emitDidChangeTextEvent(pop.patch); return true; } else { return false; } }; TextBuffer.prototype.redo = function() { var change, i, len, pop, ref2; if (pop = this.history.popRedoStack()) { ref2 = pop.patch.getChanges(); for (i = 0, len = ref2.length; i < len; i++) { change = ref2[i]; this.applyChange(change); } this.emitDidChangeTextEvent(pop.patch); return true; } else { return false; } }; TextBuffer.prototype.transact = function(groupingInterval, fn) { var checkpointBefore, compactedChanges, error1, exception, ref2, result; if (typeof groupingInterval === 'function') { fn = groupingInterval; groupingInterval = 0; } checkpointBefore = this.history.createCheckpoint(true); try { this.transactCallDepth++; result = fn(); } catch (error1) { exception = error1; this.revertToCheckpoint(checkpointBefore, true); if (!(exception instanceof TransactionAbortedError)) { throw exception; } return; } finally { this.transactCallDepth--; } compactedChanges = this.history.groupChangesSinceCheckpoint(checkpointBefore, true); if ((ref2 = global.atom) != null) { ref2.assert(compactedChanges, "groupChangesSinceCheckpoint() returned false.", (function(_this) { return function(error) { return error.metadata = { history: _this.history.toString() }; }; })(this)); } this.history.applyGroupingInterval(groupingInterval); this.history.enforceUndoStackSizeLimit(); if (compactedChanges) { this.emitDidChangeTextEvent(compactedChanges); } return result; }; TextBuffer.prototype.abortTransaction = function() { throw new TransactionAbortedError("Transaction aborted."); }; TextBuffer.prototype.clearUndoStack = function() { return this.history.clearUndoStack(); }; TextBuffer.prototype.createCheckpoint = function() { return this.history.createCheckpoint(false); }; TextBuffer.prototype.revertToCheckpoint = function(checkpoint) { var change, i, len, ref2, truncated; if (truncated = this.history.truncateUndoStack(checkpoint)) { ref2 = truncated.patch.getChanges(); for (i = 0, len = ref2.length; i < len; i++) { change = ref2[i]; this.applyChange(change); } this.emitDidChangeTextEvent(truncated.patch); return true; } else { return false; } }; TextBuffer.prototype.groupChangesSinceCheckpoint = function(checkpoint) { return this.history.groupChangesSinceCheckpoint(checkpoint, false); }; TextBuffer.prototype.getChangesSinceCheckpoint = function(checkpoint) { var patch; if (patch = this.history.getChangesSinceCheckpoint(checkpoint)) { return normalizePatchChanges(patch.getChanges()); } else { return []; } }; /* Section: Search And Replace */ TextBuffer.prototype.scan = function(regex, iterator) { return this.scanInRange(regex, this.getRange(), (function(_this) { return function(result) { result.lineText = _this.lineForRow(result.range.start.row); result.lineTextOffset = 0; return iterator(result); }; })(this)); }; TextBuffer.prototype.backwardsScan = function(regex, iterator) { return this.backwardsScanInRange(regex, this.getRange(), (function(_this) { return function(result) { result.lineText = _this.lineForRow(result.range.start.row); result.lineTextOffset = 0; return iterator(result); }; })(this)); }; TextBuffer.prototype.scanInRange = function(regex, range, iterator, reverse) { var callbackArgument, endIndex, flags, global, lengthDelta, match, matches, next, startIndex; if (reverse == null) { reverse = false; } range = this.clipRange(range); global = regex.global; flags = "gm"; if (regex.ignoreCase) { flags += "i"; } regex = new RegExp(regex.source, flags); startIndex = this.characterIndexForPosition(range.start); endIndex = this.characterIndexForPosition(range.end); if (reverse) { matches = new MatchIterator.Backwards(this.getText(), regex, startIndex, endIndex, this.backwardsScanChunkSize); } else { matches = new MatchIterator.Forwards(this.getText(), regex, startIndex, endIndex); } lengthDelta = 0; while (!(next = matches.next()).done) { match = next.value; callbackArgument = new SearchCallbackArgument(this, match, lengthDelta); iterator(callbackArgument); if (!reverse) { lengthDelta += callbackArgument.getReplacementDelta(); } if (!(global && callbackArgument.keepLooping())) { break; } } }; TextBuffer.prototype.backwardsScanInRange = function(regex, range, iterator) { return this.scanInRange(regex, range, iterator, true); }; TextBuffer.prototype.replace = function(regex, replacementText) { var replacements; replacements = 0; this.transact((function(_this) { return function() { return _this.scan(regex, function(arg) { var matchText, replace; matchText = arg.matchText, replace = arg.replace; replace(matchText.replace(regex, replacementText)); return replacements++; }); }; })(this)); return replacements; }; /* Section: Buffer Range Details */ TextBuffer.prototype.getRange = function() { return new Range(this.getFirstPosition(), this.getEndPosition()); }; TextBuffer.prototype.getLineCount = function() { return this.lines.length; }; TextBuffer.prototype.getLastRow = function() { return this.getLineCount() - 1; }; TextBuffer.prototype.getFirstPosition = function() { return new Point(0, 0); }; TextBuffer.prototype.getEndPosition = function() { var lastRow; lastRow = this.getLastRow(); return new Point(lastRow, this.lineLengthForRow(lastRow)); }; TextBuffer.prototype.getMaxCharacterIndex = function() { return this.offsetIndex.totalTo(Infinity, 'rows').characters; }; TextBuffer.prototype.rangeForRow = function(row, includeNewline) { row = Math.max(row, 0); row = Math.min(row, this.getLastRow()); if (includeNewline && row < this.getLastRow()) { return new Range(new Point(row, 0), new Point(row + 1, 0)); } else { return new Range(new Point(row, 0), new Point(row, this.lineLengthForRow(row))); } }; TextBuffer.prototype.characterIndexForPosition = function(position) { var characters, column, ref2, row; ref2 = this.clipPosition(Point.fromObject(position)), row = ref2.row, column = ref2.column; if (row < 0 || row > this.getLastRow() || column < 0 || column > this.lineLengthForRow(row)) { throw new Error("Position " + position + " is invalid"); } characters = this.offsetIndex.totalTo(row, 'rows').characters; return characters + column; }; TextBuffer.prototype.positionForCharacterIndex = function(offset) { var characters, ref2, rows; offset = Math.max(0, offset); offset = Math.min(this.getMaxCharacterIndex(), offset); ref2 = this.offsetIndex.totalTo(offset, 'characters'), rows = ref2.rows, characters = ref2.characters; if (rows > this.getLastRow()) { return this.getEndPosition(); } else { return new Point(rows, offset - characters); } }; TextBuffer.prototype.clipRange = function(range) { var end, start; range = Range.fromObject(range); start = this.clipPosition(range.start); end = this.clipPosition(range.end); if (range.start.isEqual(start) && range.end.isEqual(end)) { return range; } else { return new Range(start, end); } }; TextBuffer.prototype.clipPosition = function(position, options) { var column, row; position = Point.fromObject(position); Point.assertValid(position); row = position.row, column = position.column; if (row < 0) { return this.getFirstPosition(); } else if (row > this.getLastRow()) { return this.getEndPosition(); } else if (column < 0) { return Point(row, 0); } else if (column >= this.lineLengthForRow(row)) { if ((options != null ? options.clipDirection : void 0) === 'forward' && row < this.getLastRow()) { return Point(row + 1, 0); } else { return Point(row, this.lineLengthForRow(row)); } } else { return position; } }; /* Section: Private Utility Methods */ TextBuffer.prototype.destroy = function() { if (!this.destroyed) { this.cancelStoppedChangingTimeout(); this.destroyed = true; return this.emitter.emit('did-destroy'); } }; TextBuffer.prototype.isAlive = function() { return !this.destroyed; }; TextBuffer.prototype.isDestroyed = function() { return this.destroyed; }; TextBuffer.prototype.isRetained = function() { return this.refcount > 0; }; TextBuffer.prototype.retain = function() { this.refcount++; return this; }; TextBuffer.prototype.release = function() { this.refcount--; if (!this.isRetained()) { this.destroy(); } return this; }; TextBuffer.prototype.emitDidChangeTextEvent = function(patch) { if (this.transactCallDepth !== 0) { return; } this.emitter.emit('did-change-text', { changes: Object.freeze(normalizePatchChanges(patch.getChanges())) }); this.patchesSinceLastStoppedChangingEvent.push(patch); return this.scheduleDidStopChangingEvent(); }; TextBuffer.prototype.hasMultipleEditors = function() { return this.refcount > 1; }; TextBuffer.prototype.cancelStoppedChangingTimeout = function() { if (this.stoppedChangingTimeout) { return clearTimeout(this.stoppedChangingTimeout); } }; TextBuffer.prototype.scheduleDidStopChangingEvent = function() { var stoppedChangingCallback; this.cancelStoppedChangingTimeout(); stoppedChangingCallback = (function(_this) { return function() { _this.stoppedChangingTimeout = null; _this.emitter.emit('did-stop-changing', { changes: Object.freeze(normalizePatchChanges(Patch.compose(_this.patchesSinceLastStoppedChangingEvent).getChanges())) }); return _this.patchesSinceLastStoppedChangingEvent = []; }; })(this); return this.stoppedChangingTimeout = setTimeout(stoppedChangingCallback, this.stoppedChangingDelay); }; TextBuffer.prototype.logLines = function(start, end) { var i, line, ref2, ref3, row; if (start == null) { start = 0; } if (end == null) { end = this.getLastRow(); } for (row = i = ref2 = start, ref3 = end; ref2 <= ref3 ? i <= ref3 : i >= ref3; row = ref2 <= ref3 ? ++i : --i) { line = this.lineForRow(row); console.log(row, line, line.length); } }; /* Section: Private History Delegate Methods */ TextBuffer.prototype.invertChange = function(change) { return Object.freeze({ oldRange: change.newRange, newRange: change.oldRange, oldText: change.newText, newText: change.oldText }); }; TextBuffer.prototype.serializeChange = function(change) { return { oldRange: change.oldRange.serialize(), newRange: change.newRange.serialize(), oldText: change.oldText, newText: change.newText }; }; TextBuffer.prototype.deserializeChange = function(change) { return { oldRange: Range.deserialize(change.oldRange), newRange: Range.deserialize(change.newRange), oldText: change.oldText, newText: change.newText }; }; return TextBuffer; })(); }).call(this);