diff --git a/src/app/text-buffer.coffee b/src/app/text-buffer.coffee index 1bd928cd9..39cf60ee1 100644 --- a/src/app/text-buffer.coffee +++ b/src/app/text-buffer.coffee @@ -8,7 +8,7 @@ UndoManager = require 'undo-manager' BufferChangeOperation = require 'buffer-change-operation' BufferMarker = require 'buffer-marker' -# Public: Represents the contents of a file. +# Represents the contents of a file. # # The `Buffer` is often associated with a {File}. However, this is not always # the case, as a `Buffer` could be an unsaved chunk of text. @@ -29,7 +29,7 @@ class Buffer invalidMarkers: null refcount: 0 - # Public: Creates a new buffer. + # Creates a new buffer. # # path - A {String} representing the file path # initialText - A {String} setting the starting text @@ -95,17 +95,17 @@ class Buffer @file.on "moved", => @trigger "path-changed", this - + ### Public ### - # Public: Identifies if the buffer belongs to multiple editors. + # Identifies if the buffer belongs to multiple editors. # # For example, if the {Editor} was split. # - # Returns a {Boolean}. + # Returns a {Boolean}. hasMultipleEditors: -> @refcount > 1 - # Public: Reloads a file in the {EditSession}. + # Reloads a file in the {EditSession}. # # Essentially, this performs a force read of the file. reload: -> @@ -115,25 +115,25 @@ class Buffer @triggerModifiedStatusChanged(false) @trigger 'reloaded' - # Public: Rereads the contents of the file, and stores them in the cache. + # Rereads the contents of the file, and stores them in the cache. # # Essentially, this performs a force read of the file on disk. updateCachedDiskContents: -> @cachedDiskContents = @file.read() - # Public: Gets the file's basename--that is, the file without any directory information. + # Gets the file's basename--that is, the file without any directory information. # # Returns a {String}. getBaseName: -> @file?.getBaseName() - # Public: Retrieves the path for the file. + # Retrieves the path for the file. # # Returns a {String}. getPath: -> @file?.getPath() - # Public: Sets the path for the file. + # Sets the path for the file. # # path - A {String} representing the new file path setPath: (path) -> @@ -146,7 +146,7 @@ class Buffer @trigger "path-changed", this - # Public: Retrieves the current buffer's file extension. + # Retrieves the current buffer's file extension. # # Returns a {String}. getExtension: -> @@ -155,25 +155,25 @@ class Buffer else null - # Public: Retrieves the cached buffer contents. + # Retrieves the cached buffer contents. # # Returns a {String}. getText: -> @cachedMemoryContents ?= @getTextInRange(@getRange()) - # Public: Replaces the current buffer contents. + # Replaces the current buffer contents. # # text - A {String} containing the new buffer contents. setText: (text) -> @change(@getRange(), text, normalizeLineEndings: false) - # Public: Gets the range of the buffer contents. + # Gets the range of the buffer contents. # # Returns a new {Range}, from `[0, 0]` to the end of the buffer. getRange: -> new Range([0, 0], [@getLastRow(), @getLastLine().length]) - # Public: Given a range, returns the lines of text within it. + # Given a range, returns the lines of text within it. # # range - A {Range} object specifying your points of interest # @@ -193,13 +193,13 @@ class Buffer return multipleLines.join '' - # Public: Gets all the lines in a file. + # Gets all the lines in a file. # # Returns an {Array} of {String}s. getLines: -> @lines - # Public: Given a row, returns the line of text. + # Given a row, returns the line of text. # # row - A {Number} indicating the row. # @@ -213,7 +213,7 @@ class Buffer suggestedLineEndingForRow: (row) -> @lineEndingForRow(row) ? @lineEndingForRow(row - 1) - # Public: Given a row, returns the length of the line of text. + # Given a row, returns the length of the line of text. # # row - A {Number} indicating the row. # @@ -224,10 +224,10 @@ class Buffer lineEndingLengthForRow: (row) -> (@lineEndingForRow(row) ? '').length - # Public: Given a buffer row, this retrieves the range for that line. + # Given a buffer row, this retrieves the range for that line. # # row - A {Number} identifying the row - # options - A hash with one key, `includeNewline`, which specifies whether you + # options - A hash with one key, `includeNewline`, which specifies whether you # want to include the trailing newline # # Returns a {Range}. @@ -237,25 +237,25 @@ class Buffer else new Range([row, 0], [row, @lineLengthForRow(row)]) - # Public: Gets the number of lines in a file. + # Gets the number of lines in a file. # # Returns a {Number}. getLineCount: -> @getLines().length - # Public: Gets the row number of the last line. + # Gets the row number of the last line. # # Returns a {Number}. getLastRow: -> @getLines().length - 1 - # Public: Finds the last line in the current buffer. + # Finds the last line in the current buffer. # # Returns a {String}. getLastLine: -> @lineForRow(@getLastRow()) - # Public: Finds the last point in the current buffer. + # Finds the last point in the current buffer. # # Returns a {Point} representing the last position. getEofPosition: -> @@ -278,13 +278,13 @@ class Buffer new Point(row, index) - # Public: Given a row, this deletes it from the buffer. + # Given a row, this deletes it from the buffer. # # row - A {Number} representing the row to delete deleteRow: (row) -> @deleteRows(row, row) - # Public: Deletes a range of rows from the buffer. + # Deletes a range of rows from the buffer. # # start - A {Number} representing the starting row # end - A {Number} representing the ending row @@ -303,36 +303,29 @@ class Buffer @delete(new Range(startPoint, endPoint)) - # Public: Adds text to the end of the buffer. + # Adds text to the end of the buffer. # # text - A {String} of text to add append: (text) -> @insert(@getEofPosition(), text) - # Public: Adds text to a specific point in the buffer + # Adds text to a specific point in the buffer # # point - A {Point} in the buffer to insert into # text - A {String} of text to add insert: (point, text) -> @change(new Range(point, point), text) - # Public: Deletes text from the buffer + # Deletes text from the buffer # # range - A {Range} whose text to delete delete: (range) -> @change(range, '') - # Internal: - change: (oldRange, newText, options) -> - oldRange = Range.fromObject(oldRange) - operation = new BufferChangeOperation({buffer: this, oldRange, newText, options}) - range = @pushOperation(operation) - range - - # Public: Given a position, this clips it to a real position. + # Given a position, this clips it to a real position. # # For example, if `position`'s row exceeds the row count of the buffer, - # or if its column goes beyond a line's length, this "sanitizes" the value + # or if its column goes beyond a line's length, this "sanitizes" the value # to a real position. # # Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed. @@ -346,11 +339,11 @@ class Buffer column = Math.max(position.column, 0) column = Math.min(@lineLengthForRow(row), column) new Point(row, column) - - # Public: Given a range, this clips it to a real range. + + # Given a range, this clips it to a real range. # # For example, if `range`'s row exceeds the row count of the buffer, - # or if its column goes beyond a line's length, this "sanitizes" the value + # or if its column goes beyond a line's length, this "sanitizes" the value # to a real range. # # range - The {Point} to clip @@ -364,33 +357,23 @@ class Buffer prefix: @lines[range.start.row][0...range.start.column] suffix: @lines[range.end.row][range.end.column..] - # Internal: - pushOperation: (operation, editSession) -> - if @undoManager - @undoManager.pushOperation(operation, editSession) - else - operation.do() - - # Internal: - transact: (fn) -> @undoManager.transact(fn) - - # Public: Undos the last operation. + # Undos the last operation. # # editSession - The {EditSession} associated with the buffer. undo: (editSession) -> @undoManager.undo(editSession) - # Public: Redos the last operation. + # Redos the last operation. # # editSession - The {EditSession} associated with the buffer. redo: (editSession) -> @undoManager.redo(editSession) commit: -> @undoManager.commit() abort: -> @undoManager.abort() - # Public: Saves the buffer. + # Saves the buffer. save: -> @saveAs(@getPath()) if @isModified() - # Public: Saves the buffer at a specific path. + # Saves the buffer at a specific path. # # path - The path to save at. saveAs: (path) -> @@ -403,7 +386,7 @@ class Buffer @triggerModifiedStatusChanged(false) @trigger 'saved' - # Public: Identifies if the buffer was modified. + # Identifies if the buffer was modified. # # Returns a {Boolean}. isModified: -> @@ -412,12 +395,12 @@ class Buffer else not @isEmpty() - # Public: Identifies if a buffer is in a git conflict with `HEAD`. + # Identifies if a buffer is in a git conflict with `HEAD`. # # Returns a {Boolean}. isInConflict: -> @conflict - # Public: Identifies if a buffer is empty. + # Identifies if a buffer is empty. # # Returns a {Boolean}. isEmpty: -> @lines.length is 1 and @lines[0].length is 0 @@ -425,13 +408,13 @@ class Buffer getMarkers: -> _.values(@validMarkers) - # Public: Retrieves the quantity of markers in a buffer. + # Retrieves the quantity of markers in a buffer. # # Returns a {Number}. getMarkerCount: -> _.size(@validMarkers) - # Public: Constructs a new marker at a given range. + # Constructs a new marker at a given range. # # range - The marker {Range} (representing the distance between the head and tail) # options - Options to pass to the {BufferMarker} constructor @@ -446,7 +429,7 @@ class Buffer @validMarkers[marker.id] = marker marker.id - # Public: Constructs a new marker at a given position. + # Constructs a new marker at a given position. # # position - The marker {Point}; there won't be a tail # options - Options to pass to the {BufferMarker} constructor @@ -455,7 +438,7 @@ class Buffer markPosition: (position, options) -> @markRange([position, position], _.defaults({noTail: true}, options)) - # Public: Removes the marker with the given id. + # Removes the marker with the given id. # # id - The {Number} of the ID to remove destroyMarker: (id) -> @@ -468,7 +451,7 @@ class Buffer setMarkerPosition: (args...) -> @setMarkerHeadPosition(args...) - # Public: Retrieves the position of the marker's head. + # Retrieves the position of the marker's head. # # id - A {Number} representing the marker to check # @@ -476,7 +459,7 @@ class Buffer getMarkerHeadPosition: (id) -> @validMarkers[id]?.getHeadPosition() - # Public: Sets the position of the marker's head. + # Sets the position of the marker's head. # # id - A {Number} representing the marker to change # position - The new {Point} to place the head @@ -488,7 +471,7 @@ class Buffer setMarkerHeadPosition: (id, position, options) -> @validMarkers[id]?.setHeadPosition(position) - # Public: Retrieves the position of the marker's tail. + # Retrieves the position of the marker's tail. # # id - A {Number} representing the marker to check # @@ -496,7 +479,7 @@ class Buffer getMarkerTailPosition: (id) -> @validMarkers[id]?.getTailPosition() - # Public: Sets the position of the marker's tail. + # Sets the position of the marker's tail. # # id - A {Number} representing the marker to change # position - The new {Point} to place the tail @@ -508,15 +491,15 @@ class Buffer setMarkerTailPosition: (id, position, options) -> @validMarkers[id]?.setTailPosition(position) - # Public: Retrieves the {Range} between a marker's head and its tail. - # + # Retrieves the {Range} between a marker's head and its tail. + # # id - A {Number} representing the marker to check # # Returns a {Range}. getMarkerRange: (id) -> @validMarkers[id]?.getRange() - # Public: Sets the marker's range, potentialy modifying both its head and tail. + # Sets the marker's range, potentialy modifying both its head and tail. # # id - A {Number} representing the marker to change # range - The new {Range} the marker should cover @@ -526,7 +509,7 @@ class Buffer setMarkerRange: (id, range, options) -> @validMarkers[id]?.setRange(range, options) - # Public: Sets the marker's tail to the same position as the marker's head. + # Sets the marker's tail to the same position as the marker's head. # # This only works if there isn't already a tail position. # @@ -536,13 +519,13 @@ class Buffer placeMarkerTail: (id) -> @validMarkers[id]?.placeTail() - # Public: Removes the tail from the marker. + # Removes the tail from the marker. # # id - A {Number} representing the marker to change clearMarkerTail: (id) -> @validMarkers[id]?.clearTail() - # Public: Identifies if the ending position of a marker is greater than the starting position. + # Identifies if the ending position of a marker is greater than the starting position. # # This can happen when, for example, you highlight text "up" in a {Buffer}. # @@ -552,7 +535,7 @@ class Buffer isMarkerReversed: (id) -> @validMarkers[id]?.isReversed() - # Public: Identifies if the marker's head position is equal to its tail. + # Identifies if the marker's head position is equal to its tail. # # id - A {Number} representing the marker to check # @@ -560,14 +543,14 @@ class Buffer isMarkerRangeEmpty: (id) -> @validMarkers[id]?.isRangeEmpty() - # Public: Sets a callback to be fired whenever a marker is changed. + # Sets a callback to be fired whenever a marker is changed. # # id - A {Number} representing the marker to watch # callback - A {Function} to execute observeMarker: (id, callback) -> @validMarkers[id]?.observe(callback) - # Public: Given a buffer position, this finds all markers that contain the position. + # Given a buffer position, this finds all markers that contain the position. # # bufferPosition - A {Point} to check # @@ -579,7 +562,7 @@ class Buffer ids.push(id) if marker.containsPoint(bufferPosition) ids - # Public: Identifies if a character sequence is within a certain range. + # Identifies if a character sequence is within a certain range. # # regex - The {RegExp} to check # startIndex - The starting row {Number} @@ -609,14 +592,14 @@ class Buffer matches - # Public: Scans for text in the buffer, calling a function on each match. + # Scans for text in the buffer, calling a function on each match. # # regex - A {RegExp} representing the text to find # iterator - A {Function} that's called on each match scan: (regex, iterator) -> @scanInRange(regex, @getRange(), iterator) - # Public: Scans for text in a given range, calling a function on each match. + # Scans for text in a given range, calling a function on each match. # # regex - A {RegExp} representing the text to find # range - A {Range} in the buffer to search within @@ -659,7 +642,7 @@ class Buffer break unless global and keepLooping - # Public: Scans for text in a given range _backwards_, calling a function on each match. + # Scans for text in a given range _backwards_, calling a function on each match. # # regex - A {RegExp} representing the text to find # range - A {Range} in the buffer to search within @@ -667,7 +650,7 @@ class Buffer backwardsScanInRange: (regex, range, iterator) -> @scanInRange regex, range, iterator, true - # Public: Given a row, identifies if it is blank. + # Given a row, identifies if it is blank. # # row - A row {Number} to check # @@ -675,7 +658,7 @@ class Buffer isRowBlank: (row) -> not /\S/.test @lineForRow(row) - # Public: Given a row, this finds the next row above it that's empty. + # Given a row, this finds the next row above it that's empty. # # startRow - A {Number} identifying the row to start checking at # @@ -689,7 +672,7 @@ class Buffer return row unless @isRowBlank(row) null - # Public: Given a row, this finds the next row that's blank. + # Given a row, this finds the next row that's blank. # # startRow - A row {Number} to check # @@ -702,7 +685,7 @@ class Buffer return row unless @isRowBlank(row) null - # Public: Identifies if the buffer has soft tabs anywhere. + # Identifies if the buffer has soft tabs anywhere. # # Returns a {Boolean}, usesSoftTabs: -> @@ -711,21 +694,34 @@ class Buffer return match[0][0] != '\t' undefined - # Public: Checks out the current `HEAD` revision of the file. + # Checks out the current `HEAD` revision of the file. checkoutHead: -> path = @getPath() return unless path git?.checkoutHead(path) - # Public: Checks to see if a file exists. + # Checks to see if a file exists. # # Returns a {Boolean}. fileExists: -> @file? && @file.exists() - ### Internal ### + change: (oldRange, newText, options) -> + oldRange = Range.fromObject(oldRange) + operation = new BufferChangeOperation({buffer: this, oldRange, newText, options}) + range = @pushOperation(operation) + range + + pushOperation: (operation, editSession) -> + if @undoManager + @undoManager.pushOperation(operation, editSession) + else + operation.do() + + transact: (fn) -> @undoManager.transact(fn) + scheduleModifiedEvents: -> clearTimeout(@stoppedChangingTimeout) if @stoppedChangingTimeout stoppedChangingCallback = =>