Should I regret a lack of better commit messages?

This commit is contained in:
Garen Torikian
2013-04-12 22:35:54 -05:00
parent 37b3784129
commit 8bd02358d2
19 changed files with 273 additions and 20 deletions

View File

@@ -364,6 +364,9 @@ class Cursor
isAtEndOfLine: ->
@getBufferPosition().isEqual(@getCurrentLineBufferRange().end)
# Public: Retrieves the grammar's token scopes for the line.
#
# Returns an {Array} of {String}s.
getScopes: ->
@editSession.scopesForBufferPosition(@getBufferPosition())

View File

@@ -34,6 +34,7 @@ class DisplayBuffer
setVisible: (visible) -> @tokenizedBuffer.setVisible(visible)
# Internal:
buildLineMap: ->
@lineMap = new LineMap
@lineMap.insertAtScreenRow 0, @buildLinesForBufferRows(0, @buffer.getLastRow())
@@ -45,6 +46,9 @@ class DisplayBuffer
@trigger 'changed', eventProperties
@resumeMarkerObservers()
# Public: Defines the limit at which the buffer begins to soft wrap text.
#
# softWrapColumn - A {Number} defining the soft wrap limit.
setSoftWrapColumn: (@softWrapColumn) ->
start = 0
end = @getLastRow()
@@ -52,13 +56,27 @@ class DisplayBuffer
screenDelta = @getLastRow() - end
bufferDelta = 0
@triggerChanged({ start, end, screenDelta, bufferDelta })
# Public: Gets the line for the given screen row.
#
# screenRow - A {Number} indicating the screen row.
#
# Returns a {String}.
lineForRow: (row) ->
@lineMap.lineForScreenRow(row)
# Public: Gets the lines for the given screen row boundaries.
#
# startRow - A {Number} indicating the beginning screen row.
# endRow - A {Number} indicating the ending screen row.
#
# Returns an {Array} of {String}s.
linesForRows: (startRow, endRow) ->
@lineMap.linesForScreenRows(startRow, endRow)
# Public: Gets the lines in the buffer.
#
# Returns an {Array} of {String}s.
getLines: ->
@lineMap.linesForScreenRows(0, @lineMap.lastScreenRow())
@@ -123,6 +141,8 @@ class DisplayBuffer
#
# startRow - The row {Number} to start folding at
# endRow - The row {Number} to end the fold
#
# Returns the new {Fold}.
createFold: (startRow, endRow) ->
return fold if fold = @foldFor(startRow, endRow)
fold = new Fold(this, startRow, endRow)
@@ -256,6 +276,9 @@ class DisplayBuffer
bufferRangeForScreenRange: (screenRange) ->
@lineMap.bufferRangeForScreenRange(screenRange)
# Public: Gets the number of lines in the buffer.
#
# Returns a {Number}.
lineCount: ->
@lineMap.screenLineCount()
@@ -265,6 +288,9 @@ class DisplayBuffer
getLastRow: ->
@lineCount() - 1
# Public: Gets the length of the longest screen line.
#
# Returns a {Number}.
maxLineLength: ->
@lineMap.maxScreenLineLength
@@ -286,7 +312,12 @@ class DisplayBuffer
# Returns a {Point}.
bufferPositionForScreenPosition: (position, options) ->
@lineMap.bufferPositionForScreenPosition(position, options)
# Public: Retrieves the grammar's token scopes for a buffer position.
#
# bufferPosition - A {Point} in the {Buffer}
#
# Returns an {Array} of {String}s.
scopesForBufferPosition: (bufferPosition) ->
@tokenizedBuffer.scopesForPosition(bufferPosition)
@@ -490,13 +521,16 @@ class DisplayBuffer
for marker in @getMarkers()
marker.notifyObservers(bufferChanged: false)
# Internal:
destroy: ->
@tokenizedBuffer.destroy()
@buffer.off 'markers-updated', @handleMarkersUpdated
# Internal:
logLines: (start, end) ->
@lineMap.logLines(start, end)
# Internal:
getDebugSnapshot: ->
lines = ["Display Buffer:"]
for screenLine, row in @lineMap.linesForScreenRows(0, @getLastRow())

View File

@@ -10,7 +10,7 @@ Range = require 'range'
_ = require 'underscore'
fsUtils = require 'fs-utils'
# Public: `EditSession`s manage the states between file {Buffer}s, and the project as a whole.
# Public: An `EditSession` manages the states between {Editor}s, {Buffer}s, and the project as a whole.
module.exports =
class EditSession
registerDeserializer(this)
@@ -250,6 +250,9 @@ class EditSession
#
# Returns a {String}.
getBuffer: -> @buffer
# Public: Retrieves the current buffer's URI.
#
# Returns a {String}.
getUri: -> @getPath()
# Public: Given a buffer row, identifies if it is blank.
#
@@ -291,7 +294,17 @@ class EditSession
#
# Returns a {Number}.
lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row)
# Public: Scans for text in the buffer, calling a function on each match.
#
# regex - A {RegExp} representing the text to find
# range - A {Range} in the buffer to search within
# iterator - A {Function} that's called on each match
scanInBufferRange: (args...) -> @buffer.scanInRange(args...)
# Public: Scans for text in the buffer _backwards_, calling a function on each match.
#
# regex - A {RegExp} representing the text to find
# range - A {Range} in the buffer to search within
# iterator - A {Function} that's called on each match
backwardsScanInBufferRange: (args...) -> @buffer.backwardsScanInRange(args...)
# Public: Identifies if the {Buffer} is modified (and not saved).
#
@@ -365,8 +378,17 @@ class EditSession
#
# Returns an {Array} of {Range}s.
bufferRowsForScreenRows: (startRow, endRow) -> @displayBuffer.bufferRowsForScreenRows(startRow, endRow)
# Public: Retrieves the grammar's token scopes for a buffer position.
#
# bufferPosition - A {Point} in the {Buffer}
#
# Returns an {Array} of {String}s.
scopesForBufferPosition: (bufferPosition) -> @displayBuffer.scopesForBufferPosition(bufferPosition)
# Public: Retrieves the grammar's token scopes for the line with the most recently added cursor.
#
# Returns an {Array} of {String}s.
getCursorScopes: -> @getCursor().getScopes()
# Internal:
logScreenLines: (start, end) -> @displayBuffer.logLines(start, end)
# Public: Determines whether the {Editor} will auto indent rows.
@@ -565,6 +587,8 @@ class EditSession
#
# startRow - The row {Number} to start folding at
# endRow - The row {Number} to end the fold
#
# Returns the new {Fold}.
createFold: (startRow, endRow) ->
@displayBuffer.createFold(startRow, endRow)
@@ -675,6 +699,8 @@ class EditSession
#
# startRow - The row {Number} to start at
# endRow - The row {Number} to end at
#
# Returns an {Array} of the commented {Ranges}.
toggleLineCommentsForBufferRows: (start, end) ->
@languageMode.toggleLineCommentsForBufferRows(start, end)
@@ -1334,6 +1360,7 @@ class EditSession
markersForBufferPosition: (bufferPosition) ->
@buffer.markersForPosition(bufferPosition)
# Internal:
mergeCursors: ->
positions = []
for cursor in @getCursors()

View File

@@ -431,6 +431,12 @@ class Editor extends View
transact: (fn) -> @activeEditSession.transact(fn)
commit: -> @activeEditSession.commit()
abort: -> @activeEditSession.abort()
# Public: Creates a new fold between two row numbers.
#
# startRow - The row {Number} to start folding at
# endRow - The row {Number} to end the fold
#
# Returns the new {Fold}.
createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow)
# Public: Folds the current row.
foldCurrentRow: -> @activeEditSession.foldCurrentRow()
@@ -636,7 +642,17 @@ class Editor extends View
#
# Returns a {Range}.
rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row)
# Public: Scans for text in the buffer, calling a function on each match.
#
# regex - A {RegExp} representing the text to find
# range - A {Range} in the buffer to search within
# iterator - A {Function} that's called on each match
scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...)
# Public: Scans for text in the buffer _backwards_, calling a function on each match.
#
# regex - A {RegExp} representing the text to find
# range - A {Range} in the buffer to search within
# iterator - A {Function} that's called on each match
backwardsScanInBufferRange: (args...) -> @getBuffer().backwardsScanInRange(args...)
# Internal:
@@ -1090,6 +1106,7 @@ class Editor extends View
appendToLinesView: (view) ->
@overlayer.append(view)
# Internal:
calculateDimensions: ->
fragment = $('<pre class="line" style="position: absolute; visibility: hidden;"><span>x</span></div>')
@renderedLines.append(fragment)

View File

@@ -1,10 +1,10 @@
Range = require 'range'
Point = require 'point'
# Public: Represents a fold in the {Gutter}.
# Public: Represents a fold that's hiding text from the screen.
#
# Folds hide away text from the screen. They're the primary reason
# that screen ranges and buffer ranges vary.
# Folds are the primary reason that screen ranges and buffer ranges vary. Their
# creation is managed by the {DisplayBuffer}.
module.exports =
class Fold
@idCounter: 1

View File

@@ -3,6 +3,9 @@ Range = require 'range'
$ = require 'jquery'
_ = require 'underscore'
# Public: Represents the portion of the {Editor} containing row numbers.
#
# The gutter also indicates if rows are folded.
module.exports =
class Gutter extends View
@@ -15,6 +18,7 @@ class Gutter extends View
lastScreenRow: -1
highestNumberWidth: null
# Internal:
afterAttach: (onDom) ->
return if @attached or not onDom
@attached = true
@@ -34,6 +38,7 @@ class Gutter extends View
beforeRemove: ->
$(document).off(".gutter-#{@getEditor().id}")
# Internal:
handleMouseEvents: (e) ->
editor = @getEditor()
startRow = editor.screenPositionFromMouseEvent(e).row
@@ -52,9 +57,13 @@ class Gutter extends View
$(document).on "mousemove.gutter-#{@getEditor().id}", moveHandler
$(document).one "mouseup.gutter-#{@getEditor().id}", => $(document).off 'mousemove', moveHandler
# Public: Defines whether to show the gutter or not.
#
# showLineNumbers - A {Boolean} which, if `false`, hides the gutter
setShowLineNumbers: (showLineNumbers) ->
if showLineNumbers then @lineNumbers.show() else @lineNumbers.hide()
# Internal:
updateLineNumbers: (changes, renderFrom, renderTo) ->
if renderFrom < @firstScreenRow or renderTo > @lastScreenRow
performUpdate = true
@@ -67,7 +76,8 @@ class Gutter extends View
break
@renderLineNumbers(renderFrom, renderTo) if performUpdate
# Internal:
renderLineNumbers: (startScreenRow, endScreenRow) ->
editor = @getEditor()
maxDigits = editor.getLineCount().toString().length
@@ -93,6 +103,7 @@ class Gutter extends View
@highlightedRows = null
@highlightLines()
# Internal:
removeLineHighlights: ->
return unless @highlightedLineNumbers
for line in @highlightedLineNumbers
@@ -100,6 +111,7 @@ class Gutter extends View
line.classList.remove('cursor-line-no-selection')
@highlightedLineNumbers = null
# Internal:
addLineHighlight: (row, emptySelection) ->
return if row < @firstScreenRow or row > @lastScreenRow
@highlightedLineNumbers ?= []
@@ -108,6 +120,7 @@ class Gutter extends View
highlightedLineNumber.classList.add('cursor-line-no-selection') if emptySelection
@highlightedLineNumbers.push(highlightedLineNumber)
# Internal:
highlightLines: ->
if @getEditor().getSelection().isEmpty()
row = @getEditor().getCursorScreenPosition().row

View File

@@ -1,6 +1,9 @@
fsUtils = require 'fs-utils'
_ = require 'underscore'
# Public: Manages the states between {Editor}s, images, and the project as a whole.
#
# Essentially, the graphical version of a {EditSession}.
module.exports=
class ImageEditSession
registerDeserializer(this)
@@ -48,9 +51,20 @@ class ImageEditSession
else
'untitled'
# Public: Retrieves the URI of the current image.
#
# Returns a {String}.
getUri: -> @path
# Public: Retrieves the path of the current image.
#
# Returns a {String}.
getPath: -> @path
# Public: Compares two `ImageEditSession`s to determine equality.
#
# Equality is based on the condition that the two URIs are the same.
#
# Returns a {Boolean}.
isEqual: (other) ->
other instanceof ImageEditSession and @getUri() is other.getUri()

View File

@@ -2,6 +2,7 @@ ScrollView = require 'scroll-view'
_ = require 'underscore'
$ = require 'jquery'
# Public: Renders images in the {Editor}.
module.exports =
class ImageView extends ScrollView
@@ -28,6 +29,7 @@ class ImageView extends ScrollView
@command 'image-view:zoom-out', => @zoomOut()
@command 'image-view:reset-zoom', => @resetZoom()
# Internal:
afterAttach: (onDom) ->
return unless onDom
@@ -38,6 +40,7 @@ class ImageView extends ScrollView
@active = @is(pane.activeView)
@centerImage() if @active and not wasActive
# Public: Places the image in the center of the {Editor}.
centerImage: ->
return unless @loaded and @isVisible()
@@ -46,6 +49,9 @@ class ImageView extends ScrollView
'left': Math.max((@width() - @image.outerWidth()) / 2, 0)
@image.show()
# Public: Indicates the path of the image.
#
# path - A {String} for the new image path.
setPath: (path) ->
if path?
if @image.attr('src') isnt path
@@ -54,12 +60,18 @@ class ImageView extends ScrollView
else
@image.hide()
# Internal:
setModel: (imageEditSession) ->
@setPath(imageEditSession?.getPath())
# Public: Retrieve's the {Editor}'s pane.
#
# Returns a {Pane}.
getPane: ->
@parent('.item-views').parent('.pane').view()
# Internal:
adjustSize: (factor) ->
return unless @loaded and @isVisible()
@@ -69,12 +81,19 @@ class ImageView extends ScrollView
@image.height(newHeight)
@centerImage()
# Public: Zooms the image out.
#
# This is done by a factor of `0.9`.
zoomOut: ->
@adjustSize(0.9)
# Public: Zooms the image in.
#
# This is done by a factor of `1.1`.
zoomIn: ->
@adjustSize(1.1)
# Public: Zooms the image to its normal width and height.
resetZoom: ->
return unless @loaded and @isVisible()

View File

@@ -5,6 +5,19 @@ CSON = require 'cson'
BindingSet = require 'binding-set'
# Internal: Associates keymaps with actions.
#
# Keymaps are defined in a CSON format. A typical keymap looks something like this:
#
# ```cson
# 'body':
# 'ctrl-l': 'package:do-something'
#'.someClass':
# 'enter': 'package:confirm'
# ```
#
# As a key, you define the DOM element you want to work on, using CSS notation. For that
# key, you define one or more key:value pairs, associating keystrokes with a command to execute.
module.exports =
class Keymap
bindingSets: null
@@ -12,10 +25,12 @@ class Keymap
bindingSetsByFirstKeystroke: null
queuedKeystrokes: null
# Internal:
constructor: ->
@bindingSets = []
@bindingSetsByFirstKeystroke = {}
# Internal:
bindDefaultKeys: ->
@add
'body':
@@ -31,31 +46,37 @@ class Keymap
$(document).command 'open', => atom.open()
$(document).command 'open-dev', => atom.openDev()
# Internal:
loadBundledKeymaps: ->
@loadDirectory(fsUtils.resolveOnLoadPath('keymaps'))
loadUserKeymaps: ->
@loadDirectory(fsUtils.join(config.configDirPath, 'keymaps'))
# Internal: Loads all the keys in a package.
loadDirectory: (directoryPath) ->
@load(filePath) for filePath in fsUtils.list(directoryPath, ['.cson', '.json'])
# Internal: Loads keys at a specific path.
load: (path) ->
@add(path, CSON.readObject(path))
# Internal: Force adds a keymapping.
add: (args...) ->
name = args.shift() if args.length > 1
keymap = args.shift()
for selector, bindings of keymap
@bindKeys(name, selector, bindings)
# Internal: Removes a keymapping by name.
remove: (name) ->
for bindingSet in @bindingSets.filter((bindingSet) -> bindingSet.name is name)
_.remove(@bindingSets, bindingSet)
for keystrokes of bindingSet.commandsByKeystrokes
keystroke = keystrokes.split(' ')[0]
_.remove(@bindingSetsByFirstKeystroke[keystroke], bindingSet)
# Internal:
bindKeys: (args...) ->
name = args.shift() if args.length > 2
[selector, bindings] = args
@@ -65,7 +86,8 @@ class Keymap
keystroke = keystrokes.split(' ')[0] # only index by first keystroke
@bindingSetsByFirstKeystroke[keystroke] ?= []
@bindingSetsByFirstKeystroke[keystroke].push(bindingSet)
# Internal:
unbindKeys: (selector, bindings) ->
bindingSet = _.detect @bindingSets, (bindingSet) ->
bindingSet.selector is selector and bindingSet.bindings is bindings
@@ -73,7 +95,8 @@ class Keymap
if bindingSet
console.log "binding set", bindingSet
_.remove(@bindingSets, bindingSet)
# Internal:
bindingsForElement: (element) ->
keystrokeMap = {}
currentNode = $(element)
@@ -85,6 +108,7 @@ class Keymap
keystrokeMap
# Internal:
handleKeyEvent: (event) =>
event.keystrokes = @multiKeystrokeStringForEvent(event)
isMultiKeystroke = @queuedKeystrokes?
@@ -113,6 +137,7 @@ class Keymap
return false if isMultiKeystroke
return false if firstKeystroke is 'tab'
# Internal:
bindingSetsForNode: (node, candidateBindingSets = @bindingSets) ->
bindingSets = candidateBindingSets.filter (set) -> node.is(set.selector)
bindingSets.sort (a, b) ->
@@ -121,6 +146,7 @@ class Keymap
else
b.specificity - a.specificity
# Internal:
triggerCommandEvent: (keyEvent, commandName) ->
keyEvent.target = rootView[0] if keyEvent.target == document.body and window.rootView
commandEvent = $.Event(commandName)
@@ -132,6 +158,7 @@ class Keymap
$(keyEvent.target).trigger(commandEvent)
aborted
# Internal:
multiKeystrokeStringForEvent: (event) ->
currentKeystroke = @keystrokeStringForEvent(event)
if @queuedKeystrokes
@@ -163,6 +190,7 @@ class Keymap
[modifiers..., key].join('-')
# Internal:
keyFromCharCode: (charCode) ->
switch charCode
when 8 then 'backspace'

View File

@@ -44,6 +44,8 @@ class LanguageMode
#
# startRow - The row {Number} to start at
# endRow - The row {Number} to end at
#
# Returns an {Array} of the commented {Ranges}.
toggleLineCommentsForBufferRows: (start, end) ->
scopes = @editSession.scopesForBufferPosition([start, 0])
return unless commentStartString = syntax.getProperty(scopes, "editor.commentStart")

View File

@@ -25,10 +25,21 @@ class LineMap
for screenLine in maxLengthCandidates
@maxScreenLineLength = Math.max(@maxScreenLineLength, screenLine.text.length)
# Public: Gets the line for the given screen row.
#
# screenRow - A {Number} indicating the screen row.
#
# Returns a {String}.
lineForScreenRow: (row) ->
@screenLines[row]
# Public: Gets the lines for the given screen row boundaries.
#
# start - A {Number} indicating the beginning screen row.
# end - A {Number} indicating the ending screen row.
#
# Returns an {Array} of {String}s.
linesForScreenRows: (startRow, endRow) ->
@screenLines[startRow..endRow]
@@ -166,6 +177,7 @@ class LineMap
end = @bufferPositionForScreenPosition(screenRange.end)
new Range(start, end)
# Internal:
logLines: (start=0, end=@screenLineCount() - 1)->
for row in [start..end]
line = @lineForScreenRow(row).text

View File

@@ -3,13 +3,15 @@ $ = require 'jquery'
module.exports =
class PaneAxis extends View
# Internal:
@deserialize: ({children}) ->
childViews = children.map (child) -> deserialize(child)
new this(childViews)
# Internal:
initialize: (children=[]) ->
@append(children...)
# Internal:
serialize: ->
deserializer: @className()
children: @childViewStates()

View File

@@ -141,12 +141,12 @@ class Project
# softTabs - A {Boolean} which, if `true`, sets soft wrapping
setSoftWrap: (@softWrap) ->
# Public: Given a path to a file, this constructs and associates a new {EditSession}.
# Public: Given a path to a file, this constructs and associates a new `EditSession`, showing the file.
#
# filePath - The {String} path of the file to associate with
# editSessionOptions - Options that you can pass to the `EditSession` constructor
#
# Returns an {EditSession}.
# Returns either an {EditSession} (for text) or {ImageEditSession} (for images).
buildEditSession: (filePath, editSessionOptions={}) ->
if ImageEditSession.canOpen(filePath)
new ImageEditSession(filePath)

View File

@@ -13,6 +13,7 @@ PaneRow = require 'pane-row'
PaneContainer = require 'pane-container'
EditSession = require 'edit-session'
# Public: The container for the entire Atom application.
module.exports =
class RootView extends View
registerDeserializers(this, Pane, PaneRow, PaneColumn, Editor)
@@ -78,9 +79,11 @@ class RootView extends View
deserializer: 'RootView'
panes: @panes.serialize()
# Public: Shows a dialog asking if the pane was _really_ meant to be closed.
confirmClose: ->
@panes.confirmClose()
# Internal:
handleFocus: (e) ->
if @getActivePane()
@getActivePane().focus()
@@ -93,10 +96,13 @@ class RootView extends View
false
else
true
# Internal:
afterAttach: (onDom) ->
@focus() if onDom
# Public: Given a filepath, this opens it in Atom.
#
# Returns the `EditSession` for the file URI.
open: (path, options = {}) ->
changeFocus = options.changeFocus ? true
path = project.resolve(path) if path?
@@ -111,6 +117,7 @@ class RootView extends View
activePane.focus() if changeFocus
editSession
# Public: Updates the application's title, based on whichever file is open.
updateTitle: ->
if projectPath = project.getPath()
if item = @getActivePaneItem()
@@ -120,12 +127,21 @@ class RootView extends View
else
@setTitle('untitled')
# Public: Sets the application's title.
#
# Returns a {String}.
setTitle: (title) ->
document.title = title
# Public: Retrieves all of the application's {Editor}s.
#
# Returns an {Array} of {Editor}s.
getEditors: ->
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
# Public: Retrieves all of the modified buffers that are open and unsaved.
#
# Returns an {Array} of {Buffer}s.
getModifiedBuffers: ->
modifiedBuffers = []
for pane in @getPanes()
@@ -133,9 +149,15 @@ class RootView extends View
modifiedBuffers.push item.buffer if item.buffer.isModified()
modifiedBuffers
# Public: Retrieves all of the paths to open files.
#
# Returns an {Array} of {String}s.
getOpenBufferPaths: ->
_.uniq(_.flatten(@getEditors().map (editor) -> editor.getOpenBufferPaths()))
# Public: Retrieves the pane that's currently open.
#
# Returns an {Pane}.
getActivePane: ->
@panes.getActivePane()
@@ -149,29 +171,51 @@ class RootView extends View
focusNextPane: -> @panes.focusNextPane()
getFocusedPane: -> @panes.getFocusedPane()
# Internal: Destroys everything.
remove: ->
editor.remove() for editor in @getEditors()
project.destroy()
super
# Public: Saves all of the open buffers.
saveAll: ->
@panes.saveAll()
# Public: Fires a callback on each open {Pane}.
#
# callback - A {Function} to call
eachPane: (callback) ->
@panes.eachPane(callback)
# Public: Retrieves all of the open {Pane}s.
#
# Returns an {Array} of {Pane}.
getPanes: ->
@panes.getPanes()
# Public: Given a {Pane}, this fetches its ID.
#
# pane - An open {Pane}
#
# Returns a {Number}.
indexOfPane: (pane) ->
@panes.indexOfPane(pane)
# Public: Fires a callback on each open {Editor}.
#
# callback - A {Function} to call
eachEditor: (callback) ->
callback(editor) for editor in @getEditors()
@on 'editor:attached', (e, editor) -> callback(editor)
# Public: Fires a callback on each open {EditSession}.
#
# callback - A {Function} to call
eachEditSession: (callback) ->
project.eachEditSession(callback)
# Public: Fires a callback on each open {Buffer}.
#
# callback - A {Function} to call
eachBuffer: (callback) ->
project.eachBuffer(callback)

View File

@@ -450,17 +450,29 @@ class Selection
[start, end] = @getBufferRowRange()
@editSession.autoIndentBufferRows(start, end)
# Public: Wraps the selected lines in comments.
#
# Returns an {Array} of the commented {Ranges}.
toggleLineComments: ->
@editSession.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
# Public: Performs a cut operation on the selection, until the end of the line.
#
# maintainPasteboard - A {Boolean} indicating TODO
cutToEndOfLine: (maintainPasteboard) ->
@selectToEndOfLine() if @isEmpty()
@cut(maintainPasteboard)
# Public: Performs a cut operation on the selection.
#
# maintainPasteboard - A {Boolean} indicating TODO
cut: (maintainPasteboard=false) ->
@copy(maintainPasteboard)
@delete()
# Public: Performs a copy operation on the selection.
#
# maintainPasteboard - A {Boolean} indicating TODO
copy: (maintainPasteboard=false) ->
return if @isEmpty()
text = @editSession.buffer.getTextInRange(@getBufferRange())
@@ -472,6 +484,7 @@ class Selection
pasteboard.write(text, metadata)
# Public: Folds the selection.
fold: ->
range = @getBufferRange()
@editSession.createFold(range.start.row, range.end.row)

View File

@@ -16,6 +16,7 @@ class Syntax
syntax.grammarOverridesByPath = grammarOverridesByPath
syntax
# Internal:
constructor: ->
@nullGrammar = new NullGrammar
@grammars = [@nullGrammar]
@@ -24,6 +25,7 @@ class Syntax
@scopedPropertiesIndex = 0
@scopedProperties = []
# Internal:
serialize: ->
{ deserializer: @constructor.name, @grammarOverridesByPath }

View File

@@ -498,9 +498,19 @@ class Buffer
matches
# Public: 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.
#
# regex - A {RegExp} representing the text to find
# range - A {Range} in the buffer to search within
# iterator - A {Function} that's called on each match
# reverse - A {Boolean} indicating if the search should be backwards (default: `false`)
scanInRange: (regex, range, iterator, reverse=false) ->
range = @clipRange(range)
global = regex.global
@@ -538,6 +548,11 @@ class Buffer
break unless global and keepLooping
# Public: 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
# iterator - A {Function} that's called on each match
backwardsScanInRange: (regex, range, iterator) ->
@scanInRange regex, range, iterator, true

View File

@@ -18,6 +18,7 @@ class TokenizedBuffer
invalidRows: null
visible: false
# Internal:
constructor: (@buffer, { @languageMode, @tabLength }) ->
@tabLength ?= 2
@id = @constructor.idCounter++
@@ -33,9 +34,15 @@ class TokenizedBuffer
setVisible: (@visible) ->
@tokenizeInBackground() if @visible
# Public: Retrieves the current tab length.
#
# Returns a {Number}.
getTabLength: ->
@tabLength
# Public: Specifies the tab length.
#
# tabLength - A {Number} that defines the new tab length.
setTabLength: (@tabLength) ->
lastRow = @buffer.getLastRow()
@screenLines = @buildPlaceholderScreenLinesForRows(0, lastRow)

View File

@@ -10,7 +10,7 @@ require 'space-pen-extensions'
deserializers = {}
deferredDeserializers = {}
# This method is called in any window needing a general environment, including specs
# Internal: This method is called in any window needing a general environment, including specs
window.setUpEnvironment = ->
Config = require 'config'
Syntax = require 'syntax'
@@ -35,7 +35,7 @@ window.setUpEnvironment = ->
if nativeStylesheetPath = fsUtils.resolveOnLoadPath(process.platform, ['css', 'less'])
requireStylesheet(nativeStylesheetPath)
# This method is only called when opening a real application window
# Internal: This method is only called when opening a real application window
window.startup = ->
directory = _.find ['/opt/boxen', '/opt/github', '/usr/local'], (dir) -> fsUtils.isDirectory(dir)
if directory
@@ -213,5 +213,6 @@ window.profile = (description, fn) ->
console.profileEnd(description)
value
# Public: Shows a dialog asking if the window was _really_ meant to be closed.
confirmClose = ->
rootView.confirmClose().done -> window.close()