mirror of
https://github.com/atom/atom.git
synced 2026-01-22 21:38:10 -05:00
Merge remote-tracking branch 'origin/master' into know-when-to-foldem
Conflicts: src/app/buffer-marker.coffee src/app/cursor.coffee src/app/display-buffer-marker.coffee src/app/display-buffer.coffee src/app/edit-session.coffee src/app/fold.coffee src/app/line-map.coffee src/app/range.coffee src/app/selection.coffee src/app/text-buffer.coffee
This commit is contained in:
@@ -1,3 +1,9 @@
|
||||
* Improved: App icon
|
||||
* Fixed: End of line invisibles rendering incorrectly with the indent guide
|
||||
* Fixed: Updates not installing automatically on restart
|
||||
* Fixed: Wrap guide not displaying
|
||||
* Fixed: Error when saving with the markdown preview focused
|
||||
|
||||
* Fixed: Atom always running in dev mode
|
||||
* Fixed: Crash when running in dev mode without a path to the Atom source
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ bindings, but here's a list of a few useful commands.
|
||||
- `meta-g` : repeat the last local search
|
||||
- `meta-shift-f` : open command prompt with `Xx/` for a project-wide search
|
||||
- `meta-\` : focus/open tree view, or close it when it is focused
|
||||
- `meta-shift-\` : open tree view with the current file selected
|
||||
- `meta-|` : open tree view with the current file selected
|
||||
- `ctrl-w v`, `ctrl-|` : split screen vertically
|
||||
- `ctrl-w s`, `ctrl--` : split screen horizontally
|
||||
- `meta-l` : go to line
|
||||
@@ -111,14 +111,14 @@ operate on the whole buffer.
|
||||
|
||||
### Split Panes
|
||||
|
||||
You can split any editor pane horizontally or vertically by using `ctrl-shift-|` or
|
||||
You can split any editor pane horizontally or vertically by using `ctrl-\` or
|
||||
`ctrl-w v`. Once you have a split pane, you can move focus between them with
|
||||
`ctrl-tab` or `ctrl-w w`. To close a pane, close all tabs inside it.
|
||||
|
||||
### Folding
|
||||
|
||||
You can fold everything with `ctrl-shift-[` and unfold everything with
|
||||
`ctrl-shift-]`. Or, you can fold / unfold by a single level with `ctrl-[` and
|
||||
You can fold everything with `ctrl-{` and unfold everything with
|
||||
`ctrl-}`. Or, you can fold / unfold by a single level with `ctrl-[` and
|
||||
`ctrl-]`. The user interaction around folds is still a bit rough, but we're
|
||||
planning to improve it soon.
|
||||
|
||||
|
||||
@@ -278,13 +278,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:
|
||||
(NSApplication *)sender {
|
||||
for (NSWindow *window in [self windows]) {
|
||||
[window performClose:self];
|
||||
// The first call to terminate is canceled so that every window can be closed.
|
||||
// On AtomCefClient the OnBeforeClose method is called when a browser is
|
||||
// finished closing. Once all browsers have finished closing, AtomCefClient
|
||||
// calls terminate again, which will complete since no windows will be open.
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender {
|
||||
bool atomWindowsAreOpen = NO;
|
||||
for (NSWindow *window in self.windows) {
|
||||
if ([window.windowController isKindOfClass:[AtomWindowController class]]) {
|
||||
atomWindowsAreOpen = YES;
|
||||
[window performClose:self];
|
||||
}
|
||||
}
|
||||
|
||||
if (atomWindowsAreOpen) {
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
else {
|
||||
CefQuitMessageLoop();
|
||||
return NSTerminateNow;
|
||||
}
|
||||
|
||||
return NSTerminateCancel;
|
||||
}
|
||||
|
||||
# pragma mark CefAppProtocol
|
||||
|
||||
@@ -171,11 +171,10 @@ bool AtomCefClient::OnKeyEvent(CefRefPtr<CefBrowser> browser,
|
||||
}
|
||||
|
||||
void AtomCefClient::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
// REQUIRE_UI_THREAD(); // When uncommented this fails when app is terminated
|
||||
m_Browser = NULL;
|
||||
numberOfOpenBrowsers--;
|
||||
if (numberOfOpenBrowsers == 0) {
|
||||
CefQuitMessageLoop();
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -127,6 +127,7 @@ class AtomCefClient : public CefClient,
|
||||
void ShowSaveDialog(int replyId, CefRefPtr<CefBrowser> browser);
|
||||
CefRefPtr<CefListValue> CreateReplyDescriptor(int replyId, int callbackIndex);
|
||||
void Exit(int status);
|
||||
void Terminate();
|
||||
void Log(const char *message);
|
||||
void Show(CefRefPtr<CefBrowser> browser);
|
||||
void ToggleFullScreen(CefRefPtr<CefBrowser> browser);
|
||||
|
||||
@@ -159,6 +159,10 @@ void AtomCefClient::Exit(int status) {
|
||||
exit(status);
|
||||
}
|
||||
|
||||
void AtomCefClient::Terminate() {
|
||||
[NSApp terminate:NSApp];
|
||||
}
|
||||
|
||||
void AtomCefClient::Log(const char *message) {
|
||||
NSLog(@"%s", message);
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -23,7 +23,7 @@
|
||||
},
|
||||
|
||||
"devDependencies" : {
|
||||
"biscotto" : "0.0.9"
|
||||
"biscotto" : "0.0.11"
|
||||
},
|
||||
|
||||
"private": true,
|
||||
|
||||
@@ -39,9 +39,28 @@ describe "ConfigPanel", ->
|
||||
panel.floatInput.val('90.2').change()
|
||||
expect(config.get('foo.float')).toBe 90.2
|
||||
|
||||
panel.intInput.val('0').change()
|
||||
expect(config.get('foo.int')).toBe 0
|
||||
|
||||
panel.floatInput.val('0').change()
|
||||
expect(config.get('foo.float')).toBe 0
|
||||
|
||||
panel.stringInput.val('moo').change()
|
||||
expect(config.get('foo.string')).toBe 'moo'
|
||||
|
||||
panel.intInput.val('abcd').change()
|
||||
expect(config.get('foo.int')).toBe 'abcd'
|
||||
|
||||
panel.floatInput.val('defg').change()
|
||||
expect(config.get('foo.float')).toBe 'defg'
|
||||
|
||||
panel.intInput.val('').change()
|
||||
expect(config.get('foo.int')).toBe undefined
|
||||
panel.floatInput.val('').change()
|
||||
expect(config.get('foo.float')).toBe undefined
|
||||
panel.stringInput.val('').change()
|
||||
expect(config.get('foo.string')).toBe undefined
|
||||
|
||||
it "automatically binds named editors to their corresponding config keys", ->
|
||||
class TestPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@@ -54,6 +73,7 @@ describe "ConfigPanel", ->
|
||||
config.set('foo.float', 1.1)
|
||||
config.set('foo.string', 'I think therefore I am.')
|
||||
panel = new TestPanel
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(panel.intEditor.getText()).toBe '1'
|
||||
expect(panel.floatEditor.getText()).toBe '1.1'
|
||||
expect(panel.stringEditor.getText()).toBe 'I think therefore I am.'
|
||||
@@ -73,10 +93,46 @@ describe "ConfigPanel", ->
|
||||
expect(config.get('foo.float')).toBe 3.3
|
||||
expect(config.get('foo.string')).toBe 'All limitations are self imposed.'
|
||||
|
||||
|
||||
panel.intEditor.setText('not an int')
|
||||
panel.floatEditor.setText('not a float')
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(config.get('foo.int')).toBe 'not an int'
|
||||
expect(config.get('foo.float')).toBe 'not a float'
|
||||
|
||||
panel.intEditor.setText('')
|
||||
panel.floatEditor.setText('')
|
||||
panel.stringEditor.setText('')
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(config.get('foo.int')).toBe undefined
|
||||
expect(config.get('foo.float')).toBe undefined
|
||||
expect(config.get('foo.string')).toBe undefined
|
||||
|
||||
panel.intEditor.setText('0')
|
||||
panel.floatEditor.setText('0')
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(config.get('foo.int')).toBe 0
|
||||
expect(config.get('foo.float')).toBe 0
|
||||
expect(config.get('foo.string')).toBe undefined
|
||||
|
||||
it "does not save the config value until it has been changed to a new value", ->
|
||||
class TestPanel extends ConfigPanel
|
||||
@content: ->
|
||||
@div =>
|
||||
@subview "fooInt", new Editor(mini: true, attributes: {id: 'foo.int', type: 'int'})
|
||||
|
||||
config.set('foo.int', 1)
|
||||
observeHandler = jasmine.createSpy("observeHandler")
|
||||
config.observe "foo.int", observeHandler
|
||||
observeHandler.reset()
|
||||
|
||||
testPanel = new TestPanel
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(observeHandler).not.toHaveBeenCalled()
|
||||
|
||||
testPanel.fooInt.setText("1")
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(observeHandler).not.toHaveBeenCalled()
|
||||
|
||||
testPanel.fooInt.setText("2")
|
||||
window.advanceClock(10000) # wait for contents-modified to be triggered
|
||||
expect(observeHandler).toHaveBeenCalled()
|
||||
|
||||
@@ -1,12 +1,17 @@
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
describe "Config", ->
|
||||
describe ".get(keyPath) and .set(keyPath, value)", ->
|
||||
it "allows a key path's value to be read and written", ->
|
||||
describe ".get(keyPath)", ->
|
||||
it "allows a key path's value to be read", ->
|
||||
expect(config.set("foo.bar.baz", 42)).toBe 42
|
||||
expect(config.get("foo.bar.baz")).toBe 42
|
||||
expect(config.get("bogus.key.path")).toBeUndefined()
|
||||
|
||||
describe ".set(keyPath, value)", ->
|
||||
it "allows a key path's value to be written", ->
|
||||
expect(config.set("foo.bar.baz", 42)).toBe 42
|
||||
expect(config.get("foo.bar.baz")).toBe 42
|
||||
|
||||
it "updates observers and saves when a key path is set", ->
|
||||
observeHandler = jasmine.createSpy "observeHandler"
|
||||
config.observe "foo.bar.baz", observeHandler
|
||||
@@ -17,6 +22,28 @@ describe "Config", ->
|
||||
expect(config.save).toHaveBeenCalled()
|
||||
expect(observeHandler).toHaveBeenCalledWith 42
|
||||
|
||||
describe "when the value equals the default value", ->
|
||||
it "does not store the value", ->
|
||||
config.setDefaults("foo", same: 1, changes: 1)
|
||||
expect(config.settings.foo).toBeUndefined()
|
||||
config.set('foo.same', 1)
|
||||
config.set('foo.changes', 2)
|
||||
expect(config.settings.foo).toEqual {changes: 2}
|
||||
|
||||
config.set('foo.changes', 1)
|
||||
expect(config.settings.foo).toEqual {}
|
||||
|
||||
describe ".getPositiveInt(keyPath, defaultValue)", ->
|
||||
it "returns the proper current or default value", ->
|
||||
config.set('editor.preferredLineLength', 0)
|
||||
expect(config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
|
||||
config.set('editor.preferredLineLength', -1234)
|
||||
expect(config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
|
||||
config.set('editor.preferredLineLength', 'abcd')
|
||||
expect(config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
|
||||
config.set('editor.preferredLineLength', null)
|
||||
expect(config.getPositiveInt('editor.preferredLineLength', 80)).toBe 80
|
||||
|
||||
describe ".save()", ->
|
||||
beforeEach ->
|
||||
spyOn(fsUtils, 'write')
|
||||
|
||||
@@ -320,8 +320,9 @@ describe "Editor", ->
|
||||
expect(editor.verticalScrollbarContent.height()).toBe buffer.getLineCount() * editor.lineHeight
|
||||
|
||||
newEditor = new Editor(editor.activeEditSession.copy())
|
||||
editor.remove()
|
||||
newEditor.attachToDom()
|
||||
expect(editor.css('font-size')).toBe '30px'
|
||||
expect(newEditor.css('font-size')).toBe '30px'
|
||||
|
||||
it "updates the position and size of selection regions", ->
|
||||
config.set("editor.fontSize", 10)
|
||||
@@ -541,20 +542,23 @@ describe "Editor", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual(row: 5, column: 27)
|
||||
|
||||
it "selects and scrolls if the mouse is dragged outside of the editor itself", ->
|
||||
intervalFns = []
|
||||
editor.vScrollMargin = 0
|
||||
editor.attachToDom(heightInLines: 5)
|
||||
editor.scrollToBottom()
|
||||
|
||||
spyOn(window, 'setInterval').andCallFake (fn) -> intervalFns.push(fn)
|
||||
spyOn(window, 'setInterval').andCallFake ->
|
||||
|
||||
# start
|
||||
editor.renderedLines.trigger mousedownEvent(editor: editor, point: [12, 0])
|
||||
originalScrollTop = editor.scrollTop()
|
||||
|
||||
# moving changes selection
|
||||
$(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -15)
|
||||
expect(editor.scrollTop()).toBe 4 * editor.lineHeight
|
||||
$(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -1)
|
||||
expect(editor.scrollTop()).toBe originalScrollTop - editor.lineHeight
|
||||
|
||||
# if cursor stays off screen, we keep moving / scrolling up
|
||||
fn() for fn in intervalFns
|
||||
# every mouse move selects more text
|
||||
for x in [0..10]
|
||||
$(document).trigger mousemoveEvent(editor: editor, pageX: 0, pageY: -1)
|
||||
|
||||
expect(editor.scrollTop()).toBe 0
|
||||
|
||||
@@ -1210,7 +1214,7 @@ describe "Editor", ->
|
||||
|
||||
describe "when scrolling more than the editors height", ->
|
||||
it "removes lines that are offscreen and not in range of the overdraw and builds lines that become visible", ->
|
||||
editor.scrollTop(editor.scrollView.prop('scrollHeight') - editor.scrollView.height())
|
||||
editor.scrollTop(editor.layerHeight - editor.scrollView.height())
|
||||
expect(editor.renderedLines.find('.line').length).toBe 8
|
||||
expect(editor.renderedLines.find('.line:first').text()).toBe buffer.lineForRow(5)
|
||||
expect(editor.renderedLines.find('.line:last').text()).toBe buffer.lineForRow(12)
|
||||
@@ -1547,6 +1551,31 @@ describe "Editor", ->
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe ' '
|
||||
|
||||
describe "when the line has leading and trailing whitespace", ->
|
||||
it "does not display the indent guide in the trailing whitespace", ->
|
||||
editor.attachToDom()
|
||||
config.set("editor.showIndentGuide", true)
|
||||
|
||||
editor.insertText("/*\n * \n*/")
|
||||
expect(editor.renderedLines.find('.line:eq(1) .indent-guide').length).toBe 1
|
||||
expect(editor.renderedLines.find('.line:eq(1) .indent-guide')).toHaveClass('leading-whitespace')
|
||||
|
||||
describe "when the line is empty and end of show invisibles are enabled", ->
|
||||
it "renders the indent guides interleaved the end of line invisibles", ->
|
||||
editor.attachToDom()
|
||||
config.set("editor.showIndentGuide", true)
|
||||
config.set("editor.showInvisibles", true)
|
||||
eol = editor.invisibles?.eol
|
||||
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 1
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} "
|
||||
|
||||
editor.setCursorBufferPosition([9])
|
||||
editor.indent()
|
||||
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').length).toBe 2
|
||||
expect(editor.renderedLines.find('.line:eq(10) .indent-guide').text()).toBe "#{eol} "
|
||||
|
||||
describe "when soft-wrap is enabled", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom()
|
||||
@@ -2125,16 +2154,13 @@ describe "Editor", ->
|
||||
|
||||
it "move the cursor to the end of the file", ->
|
||||
expect(editor.getCursorScreenPosition()).toEqual [0,0]
|
||||
event = $.Event("click")
|
||||
event.offsetY = Infinity
|
||||
event = mousedownEvent(editor: editor, point: [Infinity, 10])
|
||||
editor.underlayer.trigger event
|
||||
expect(editor.getCursorScreenPosition()).toEqual [12,2]
|
||||
|
||||
it "selects to the end of the files when shift is pressed", ->
|
||||
expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [0,0]]
|
||||
event = $.Event("click")
|
||||
event.offsetY = Infinity
|
||||
event.shiftKey = true
|
||||
event = mousedownEvent(editor: editor, point: [Infinity, 10], shiftKey: true)
|
||||
editor.underlayer.trigger event
|
||||
expect(editor.getSelection().getScreenRange()).toEqual [[0,0], [12,2]]
|
||||
|
||||
|
||||
@@ -303,6 +303,7 @@ describe "Pane", ->
|
||||
|
||||
describe "when the current item has no save method", ->
|
||||
it "does nothing", ->
|
||||
pane.activeItem.getUri = -> 'you are eye'
|
||||
expect(pane.activeItem.save).toBeUndefined()
|
||||
pane.trigger 'core:save'
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "Window", ->
|
||||
|
||||
beforeEach ->
|
||||
spyOn(atom, 'getPathToOpen').andReturn(project.getPath())
|
||||
window.handleWindowEvents()
|
||||
window.handleEvents()
|
||||
window.deserializeEditorWindow()
|
||||
projectPath = project.getPath()
|
||||
|
||||
@@ -229,3 +229,25 @@ describe "Window", ->
|
||||
event = buildDragEvent("drop", [])
|
||||
window.onDrop(event)
|
||||
expect(atom.open).not.toHaveBeenCalled()
|
||||
|
||||
describe "when a link is clicked", ->
|
||||
it "opens the http/https links in an external application", ->
|
||||
ChildProcess = require 'child_process'
|
||||
spyOn(ChildProcess, 'spawn')
|
||||
|
||||
$("<a href='http://github.com'>the website</a>").appendTo(document.body).click().remove()
|
||||
expect(ChildProcess.spawn).toHaveBeenCalled()
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe "http://github.com"
|
||||
|
||||
ChildProcess.spawn.reset()
|
||||
$("<a href='https://github.com'>the website</a>").appendTo(document.body).click().remove()
|
||||
expect(ChildProcess.spawn).toHaveBeenCalled()
|
||||
expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe "https://github.com"
|
||||
|
||||
ChildProcess.spawn.reset()
|
||||
$("<a href=''>the website</a>").appendTo(document.body).click().remove()
|
||||
expect(ChildProcess.spawn).not.toHaveBeenCalled()
|
||||
|
||||
ChildProcess.spawn.reset()
|
||||
$("<a href='#scroll-me'>link</a>").appendTo(document.body).click().remove()
|
||||
expect(ChildProcess.spawn).not.toHaveBeenCalled()
|
||||
|
||||
@@ -73,6 +73,8 @@ describe "CSON", ->
|
||||
|
||||
it "returns formatted CSON", ->
|
||||
expect(CSON.stringify(a: {b: 'c'})).toBe "'a':\n 'b': 'c'"
|
||||
expect(CSON.stringify(a:{})).toBe "'a': {}"
|
||||
expect(CSON.stringify(a:[])).toBe "'a': []"
|
||||
|
||||
describe "when converting back to an object", ->
|
||||
it "produces the original object", ->
|
||||
|
||||
@@ -6,9 +6,7 @@ $ = require 'jquery'
|
||||
CSON = require 'cson'
|
||||
|
||||
|
||||
###
|
||||
# Internal: Loads and resolves packages. #
|
||||
###
|
||||
### Internal: Loads and resolves packages. ###
|
||||
|
||||
module.exports =
|
||||
class AtomPackage extends Package
|
||||
|
||||
@@ -5,13 +5,13 @@ Theme = require 'theme'
|
||||
module.exports =
|
||||
class AtomTheme extends Theme
|
||||
|
||||
# Internal: Given a path, this loads it as a stylesheet.
|
||||
# Given a path, this loads it as a stylesheet.
|
||||
#
|
||||
# stylesheetPath - A {String} to a stylesheet
|
||||
loadStylesheet: (stylesheetPath)->
|
||||
@stylesheets[stylesheetPath] = window.loadStylesheet(stylesheetPath)
|
||||
|
||||
# Internal: Loads the stylesheets found in a `package.cson` file.
|
||||
# Loads the stylesheets found in a `package.cson` file.
|
||||
load: ->
|
||||
if fsUtils.extension(@path) in ['.css', '.less']
|
||||
@loadStylesheet(@path)
|
||||
|
||||
@@ -5,9 +5,7 @@ fsUtils = require 'fs-utils'
|
||||
Specificity = require 'specificity'
|
||||
PEG = require 'pegjs'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class BindingSet
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
Range = require 'range'
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class BufferChangeOperation
|
||||
|
||||
@@ -10,23 +10,20 @@ class BufferMarker
|
||||
suppressObserverNotification: false
|
||||
invalidationStrategy: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: ({@id, @buffer, range, @invalidationStrategy, @attributes, noTail, reverse}) ->
|
||||
@invalidationStrategy ?= 'contains'
|
||||
@setRange(range, {noTail, reverse})
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# 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.
|
||||
#
|
||||
# range - The new {Range} the marker should cover
|
||||
# options - A hash of options with the following keys:
|
||||
# :reverse - if `true`, the marker is reversed; that is, its tail is "above" the head
|
||||
# :noTail - if `true`, the marker doesn't have a tail
|
||||
# reverse: if `true`, the marker is reversed; that is, its tail is "above" the head
|
||||
# noTail: if `true`, the marker doesn't have a tail
|
||||
setRange: (range, options={}) ->
|
||||
@consolidateObserverNotifications false, =>
|
||||
range = Range.fromObject(range)
|
||||
@@ -37,7 +34,7 @@ class BufferMarker
|
||||
@setTailPosition(range.start) unless options.noTail
|
||||
@setHeadPosition(range.end)
|
||||
|
||||
# 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}.
|
||||
#
|
||||
@@ -63,13 +60,13 @@ class BufferMarker
|
||||
return false unless _.isEqual(@attributes[key], value)
|
||||
true
|
||||
|
||||
# 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.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isRangeEmpty: ->
|
||||
@getHeadPosition().isEqual(@getTailPosition())
|
||||
|
||||
# Public: Retrieves the {Range} between a marker's head and its tail.
|
||||
# Retrieves the {Range} between a marker's head and its tail.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getRange: ->
|
||||
@@ -78,22 +75,22 @@ class BufferMarker
|
||||
else
|
||||
new Range(@getHeadPosition(), @getHeadPosition())
|
||||
|
||||
# Public: Retrieves the position of the marker's head.
|
||||
# Retrieves the position of the marker's head.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getHeadPosition: -> @headPosition?.copy()
|
||||
|
||||
# Public: Retrieves the position of the marker's tail.
|
||||
# Retrieves the position of the marker's tail.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getTailPosition: -> @tailPosition?.copy() ? @getHeadPosition()
|
||||
|
||||
# Public: Sets the position of the marker's head.
|
||||
# Sets the position of the marker's head.
|
||||
#
|
||||
# newHeadPosition - The new {Point} to place the head
|
||||
# options - A hash with the following keys:
|
||||
# :clip - if `true`, the point is [clipped]{Buffer.clipPosition}
|
||||
# :bufferChanged - if `true`, indicates that the {Buffer} should trigger an event that it's changed
|
||||
# clip: if `true`, the point is [clipped]{Buffer.clipPosition}
|
||||
# bufferChanged: if `true`, indicates that the {Buffer} should trigger an event that it's changed
|
||||
#
|
||||
# Returns a {Point} representing the new head position.
|
||||
setHeadPosition: (newHeadPosition, options={}) ->
|
||||
@@ -106,12 +103,12 @@ class BufferMarker
|
||||
@notifyObservers({oldHeadPosition, newHeadPosition, bufferChanged})
|
||||
@headPosition
|
||||
|
||||
# Public: Sets the position of the marker's tail.
|
||||
# Sets the position of the marker's tail.
|
||||
#
|
||||
# newHeadPosition - The new {Point} to place the tail
|
||||
# options - A hash with the following keys:
|
||||
# :clip - if `true`, the point is [clipped]{Buffer.clipPosition}
|
||||
# :bufferChanged - if `true`, indicates that the {Buffer} should trigger an event that it's changed
|
||||
# clip: if `true`, the point is [clipped]{Buffer.clipPosition}
|
||||
# bufferChanged: if `true`, indicates that the {Buffer} should trigger an event that it's changed
|
||||
#
|
||||
# Returns a {Point} representing the new tail position.
|
||||
setTailPosition: (newTailPosition, options={}) ->
|
||||
@@ -124,19 +121,19 @@ class BufferMarker
|
||||
@notifyObservers({oldTailPosition, newTailPosition, bufferChanged})
|
||||
@tailPosition
|
||||
|
||||
# Public: Retrieves the starting position of the marker.
|
||||
# Retrieves the starting position of the marker.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getStartPosition: ->
|
||||
@getRange().start
|
||||
|
||||
# Public: Retrieves the ending position of the marker.
|
||||
# Retrieves the ending position of the marker.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getEndPosition: ->
|
||||
@getRange().end
|
||||
|
||||
# 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.
|
||||
#
|
||||
@@ -144,14 +141,14 @@ class BufferMarker
|
||||
placeTail: ->
|
||||
@setTailPosition(@getHeadPosition()) unless @tailPosition
|
||||
|
||||
# Public: Removes the tail from the marker.
|
||||
# Removes the tail from the marker.
|
||||
clearTail: ->
|
||||
oldTailPosition = @getTailPosition()
|
||||
@tailPosition = null
|
||||
newTailPosition = @getTailPosition()
|
||||
@notifyObservers({oldTailPosition, newTailPosition, bufferChanged: false})
|
||||
|
||||
# Public: Identifies if a {Point} is within the marker.
|
||||
# Identifies if a {Point} is within the marker.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
containsPoint: (point) ->
|
||||
@@ -174,9 +171,7 @@ class BufferMarker
|
||||
isDestroyed: ->
|
||||
not (@buffer.validMarkers[@id]? or @buffer.invalidMarkers[@id]?)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
tryToInvalidate: (changedRange) ->
|
||||
previousRange = @getRange()
|
||||
|
||||
@@ -17,22 +17,20 @@ class ConfigPanel extends View
|
||||
input = $(input)
|
||||
name = input.attr('id')
|
||||
type = input.attr('type')
|
||||
|
||||
@observeConfig name, (value) ->
|
||||
if type is 'checkbox'
|
||||
input.attr('checked', value)
|
||||
else
|
||||
input.val(value) if value
|
||||
input.on 'change', ->
|
||||
|
||||
input.on 'change', =>
|
||||
value = input.val()
|
||||
config.set name, switch type
|
||||
when 'int'
|
||||
parseInt(value)
|
||||
when 'float'
|
||||
parseFloat(value)
|
||||
when 'checkbox'
|
||||
!!input.attr('checked')
|
||||
else
|
||||
value
|
||||
if type == 'checkbox'
|
||||
value = !!input.attr('checked')
|
||||
else
|
||||
value = @parseValue(type, value)
|
||||
config.set(name, value)
|
||||
|
||||
bindEditors: ->
|
||||
for editor in @find('.editor[id]').views()
|
||||
@@ -45,9 +43,16 @@ class ConfigPanel extends View
|
||||
value ?= ""
|
||||
editor.setText(value.toString())
|
||||
|
||||
editor.getBuffer().on 'contents-modified', ->
|
||||
value = editor.getText()
|
||||
if type == 'int' then value = parseInt(value) or 0
|
||||
if type == 'float' then value = parseFloat(value) or 0
|
||||
if value == "" then value = undefined
|
||||
config.set name, value
|
||||
editor.getBuffer().on 'contents-modified', =>
|
||||
config.set(name, @parseValue(type, editor.getText()))
|
||||
|
||||
parseValue: (type, value) ->
|
||||
switch type
|
||||
when 'int'
|
||||
intValue = parseInt(value)
|
||||
value = intValue unless isNaN(intValue)
|
||||
when 'float'
|
||||
floatValue = parseFloat(value)
|
||||
value = floatValue unless isNaN(floatValue)
|
||||
value = undefined if value == ''
|
||||
value
|
||||
|
||||
@@ -29,9 +29,7 @@ class Config
|
||||
settings: null
|
||||
configFileHasErrors: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: ->
|
||||
@defaultSettings =
|
||||
@@ -46,7 +44,6 @@ class Config
|
||||
|
||||
fsUtils.makeDirectory(@configDirPath)
|
||||
|
||||
|
||||
queue = async.queue ({sourcePath, destinationPath}, callback) =>
|
||||
fsUtils.copy(sourcePath, destinationPath, callback)
|
||||
queue.drain = done
|
||||
@@ -90,29 +87,6 @@ class Config
|
||||
@watchSubscription?.close()
|
||||
@watchSubscription = null
|
||||
|
||||
# Public: Retrieves the setting for the given key.
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `null` if the key doesn't exist in either.
|
||||
get: (keyPath) ->
|
||||
_.valueForKeyPath(@settings, keyPath) ?
|
||||
_.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
# Public: Sets the value for a configuration setting.
|
||||
#
|
||||
# This value is stored in Atom's internal configuration file.
|
||||
#
|
||||
# keyPath - The {String} name of the key
|
||||
# value - The value of the setting
|
||||
#
|
||||
# Returns the `value`.
|
||||
set: (keyPath, value) ->
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
@update()
|
||||
value
|
||||
|
||||
setDefaults: (keyPath, defaults) ->
|
||||
keys = keyPath.split('.')
|
||||
hash = @defaultSettings
|
||||
@@ -123,9 +97,56 @@ class Config
|
||||
_.extend hash, defaults
|
||||
@update()
|
||||
|
||||
# Public: Establishes an event listener for a given key.
|
||||
### Public ###
|
||||
|
||||
# Retrieves the setting for the given key.
|
||||
#
|
||||
# Whenever the value of the key is changed, a callback is fired.
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `null` if the key doesn't exist in either.
|
||||
get: (keyPath) ->
|
||||
_.valueForKeyPath(@settings, keyPath) ?
|
||||
_.valueForKeyPath(@defaultSettings, keyPath)
|
||||
|
||||
# Retrieves the setting for the given key as an integer.
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `NaN` if the key doesn't exist in either.
|
||||
getInt: (keyPath, defaultValueWhenFalsy) ->
|
||||
parseInt(@get(keyPath))
|
||||
|
||||
# Retrieves the setting for the given key as a positive integer.
|
||||
#
|
||||
# keyPath - The {String} name of the key to retrieve
|
||||
# defaultValue - The integer {Number} to fall back to if the value isn't
|
||||
# positive
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration file,
|
||||
# or `defaultValue` if the key value isn't greater than zero.
|
||||
getPositiveInt: (keyPath, defaultValue) ->
|
||||
Math.max(@getInt(keyPath), 0) or defaultValue
|
||||
|
||||
# Sets the value for a configuration setting.
|
||||
#
|
||||
# This value is stored in Atom's internal configuration file.
|
||||
#
|
||||
# keyPath - The {String} name of the key
|
||||
# value - The value of the setting
|
||||
#
|
||||
# Returns the `value`.
|
||||
set: (keyPath, value) ->
|
||||
if @get(keyPath) != value
|
||||
value = undefined if _.valueForKeyPath(@defaultSettings, keyPath) == value
|
||||
_.setValueForKeyPath(@settings, keyPath, value)
|
||||
@update()
|
||||
value
|
||||
|
||||
# Establishes an event listener for a given key.
|
||||
#
|
||||
# `callback` is fired immediately and whenever the value of the key is changed
|
||||
#
|
||||
# keyPath - The {String} name of the key to watch
|
||||
# callback - The {Function} that fires when the. It is given a single argument, `value`,
|
||||
@@ -144,6 +165,8 @@ class Config
|
||||
callback(value)
|
||||
subscription
|
||||
|
||||
### Internal ###
|
||||
|
||||
update: ->
|
||||
return if @configFileHasErrors
|
||||
@save()
|
||||
|
||||
@@ -3,7 +3,7 @@ Point = require 'point'
|
||||
Range = require 'range'
|
||||
_ = require 'underscore'
|
||||
|
||||
# Internal:
|
||||
### Internal ###
|
||||
module.exports =
|
||||
class CursorView extends View
|
||||
@content: ->
|
||||
|
||||
@@ -14,9 +14,7 @@ class Cursor
|
||||
visible: true
|
||||
needsAutoscroll: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: ({@editSession, @marker}) ->
|
||||
@updateVisibility()
|
||||
@@ -53,47 +51,45 @@ class Cursor
|
||||
unless fn()
|
||||
@trigger 'autoscrolled' if @needsAutoscroll
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Moves a cursor to a given screen position.
|
||||
# Moves a cursor to a given screen position.
|
||||
#
|
||||
# screenPosition - An {Array} of two numbers: the screen row, and the screen column.
|
||||
# options - An object with the following keys:
|
||||
# :autoscroll - A {Boolean} which, if `true`, scrolls the {EditSession} to wherever the cursor moves to
|
||||
# autoscroll: A {Boolean} which, if `true`, scrolls the {EditSession} to wherever the cursor moves to
|
||||
#
|
||||
setScreenPosition: (screenPosition, options={}) ->
|
||||
@changePosition options, =>
|
||||
@marker.setHeadScreenPosition(screenPosition, options)
|
||||
|
||||
# Public: Gets the screen position of the cursor.
|
||||
# Gets the screen position of the cursor.
|
||||
#
|
||||
# Returns an {Array} of two numbers: the screen row, and the screen column.
|
||||
getScreenPosition: ->
|
||||
@marker.getHeadScreenPosition()
|
||||
|
||||
# Public: Moves a cursor to a given buffer position.
|
||||
# Moves a cursor to a given buffer position.
|
||||
#
|
||||
# bufferPosition - An {Array} of two numbers: the buffer row, and the buffer column.
|
||||
# options - An object with the following keys:
|
||||
# :autoscroll - A {Boolean} which, if `true`, scrolls the {EditSession} to wherever the cursor moves to
|
||||
# autoscroll: A {Boolean} which, if `true`, scrolls the {EditSession} to wherever the cursor moves to
|
||||
#
|
||||
setBufferPosition: (bufferPosition, options={}) ->
|
||||
@changePosition options, =>
|
||||
@marker.setHeadBufferPosition(bufferPosition, options)
|
||||
|
||||
# Public: Gets the current buffer position.
|
||||
# Gets the current buffer position.
|
||||
#
|
||||
# Returns an {Array} of two numbers: the buffer row, and the buffer column.
|
||||
getBufferPosition: ->
|
||||
@marker.getHeadBufferPosition()
|
||||
|
||||
# Public: If the marker range is empty, the cursor is marked as being visible.
|
||||
# If the marker range is empty, the cursor is marked as being visible.
|
||||
updateVisibility: ->
|
||||
@setVisible(@marker.getBufferRange().isEmpty())
|
||||
|
||||
# Public: Sets the visibility of the cursor.
|
||||
# Sets the visibility of the cursor.
|
||||
#
|
||||
# visible - A {Boolean} indicating whether the cursor should be visible
|
||||
setVisible: (visible) ->
|
||||
@@ -102,25 +98,27 @@ class Cursor
|
||||
@needsAutoscroll ?= true if @visible and @isLastCursor()
|
||||
@trigger 'visibility-changed', @visible
|
||||
|
||||
# Public: Retrieves the visibility of the cursor.
|
||||
# Retrieves the visibility of the cursor.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isVisible: -> @visible
|
||||
|
||||
# Public: Identifies what the cursor considers a "word" RegExp.
|
||||
# Identifies what the cursor considers a "word" RegExp.
|
||||
#
|
||||
# Returns a {RegExp}.
|
||||
wordRegExp: ->
|
||||
nonWordCharacters = config.get("editor.nonWordCharacters")
|
||||
new RegExp("^[\t ]*$|[^\\s#{_.escapeRegExp(nonWordCharacters)}]+|[#{_.escapeRegExp(nonWordCharacters)}]+", "g")
|
||||
|
||||
# Public: Identifies if this cursor is the last in the {EditSession}.
|
||||
# Identifies if this cursor is the last in the {EditSession}.
|
||||
#
|
||||
# "Last" is defined as the most recently added cursor.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isLastCursor: ->
|
||||
this == @editSession.getCursor()
|
||||
|
||||
# Public: Identifies if the cursor is surrounded by whitespace.
|
||||
# Identifies if the cursor is surrounded by whitespace.
|
||||
#
|
||||
# "Surrounded" here means that all characters before and after the cursor is whitespace.
|
||||
#
|
||||
@@ -130,84 +128,84 @@ class Cursor
|
||||
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
|
||||
/^\s+$/.test @editSession.getTextInBufferRange(range)
|
||||
|
||||
# Public: Removes the setting for auto-scroll.
|
||||
# Removes the setting for auto-scroll.
|
||||
clearAutoscroll: ->
|
||||
@needsAutoscroll = null
|
||||
|
||||
# Public: Deselects whatever the cursor is selecting.
|
||||
# Deselects whatever the cursor is selecting.
|
||||
clearSelection: ->
|
||||
if @selection
|
||||
@selection.goalBufferRange = null
|
||||
@selection.clear() unless @selection.retainSelection
|
||||
|
||||
# Public: Retrieves the cursor's screen row.
|
||||
# Retrieves the cursor's screen row.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getScreenRow: ->
|
||||
@getScreenPosition().row
|
||||
|
||||
# Public: Retrieves the cursor's screen column.
|
||||
# Retrieves the cursor's screen column.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getScreenColumn: ->
|
||||
@getScreenPosition().column
|
||||
|
||||
# Public: Retrieves the cursor's buffer row.
|
||||
# Retrieves the cursor's buffer row.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getBufferRow: ->
|
||||
@getBufferPosition().row
|
||||
|
||||
# Public: Retrieves the cursor's buffer column.
|
||||
# Retrieves the cursor's buffer column.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getBufferColumn: ->
|
||||
@getBufferPosition().column
|
||||
|
||||
# Public: Retrieves the cursor's buffer row text.
|
||||
# Retrieves the cursor's buffer row text.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getCurrentBufferLine: ->
|
||||
@editSession.lineForBufferRow(@getBufferRow())
|
||||
|
||||
# Public: Moves the cursor up one screen row.
|
||||
# Moves the cursor up one screen row.
|
||||
moveUp: (rowCount = 1) ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
@setScreenPosition({row: row - rowCount, column: column})
|
||||
@goalColumn = column
|
||||
|
||||
# Public: Moves the cursor down one screen row.
|
||||
# Moves the cursor down one screen row.
|
||||
moveDown: (rowCount = 1) ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
column = @goalColumn if @goalColumn?
|
||||
@setScreenPosition({row: row + rowCount, column: column})
|
||||
@goalColumn = column
|
||||
|
||||
# Public: Moves the cursor left one screen column.
|
||||
# Moves the cursor left one screen column.
|
||||
moveLeft: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
[row, column] = if column > 0 then [row, column - 1] else [row - 1, Infinity]
|
||||
@setScreenPosition({row, column})
|
||||
|
||||
# Public: Moves the cursor right one screen column.
|
||||
# Moves the cursor right one screen column.
|
||||
moveRight: ->
|
||||
{ row, column } = @getScreenPosition()
|
||||
@setScreenPosition([row, column + 1], skipAtomicTokens: true, wrapBeyondNewlines: true, wrapAtSoftNewlines: true)
|
||||
|
||||
# Public: Moves the cursor to the top of the buffer.
|
||||
# Moves the cursor to the top of the buffer.
|
||||
moveToTop: ->
|
||||
@setBufferPosition([0,0])
|
||||
|
||||
# Public: Moves the cursor to the bottom of the buffer.
|
||||
# Moves the cursor to the bottom of the buffer.
|
||||
moveToBottom: ->
|
||||
@setBufferPosition(@editSession.getEofBufferPosition())
|
||||
|
||||
# Public: Moves the cursor to the beginning of the buffer line.
|
||||
# Moves the cursor to the beginning of the buffer line.
|
||||
moveToBeginningOfLine: ->
|
||||
@setBufferPosition([@getBufferRow(), 0])
|
||||
|
||||
# Public: Moves the cursor to the beginning of the first character in the line.
|
||||
# Moves the cursor to the beginning of the first character in the line.
|
||||
moveToFirstCharacterOfLine: ->
|
||||
position = @getBufferPosition()
|
||||
scanRange = @getCurrentLineBufferRange()
|
||||
@@ -218,7 +216,7 @@ class Cursor
|
||||
newPosition = [position.row, 0] if newPosition.isEqual(position)
|
||||
@setBufferPosition(newPosition)
|
||||
|
||||
# Public: Moves the cursor to the beginning of the buffer line, skipping all whitespace.
|
||||
# Moves the cursor to the beginning of the buffer line, skipping all whitespace.
|
||||
skipLeadingWhitespace: ->
|
||||
position = @getBufferPosition()
|
||||
scanRange = @getCurrentLineBufferRange()
|
||||
@@ -228,28 +226,28 @@ class Cursor
|
||||
|
||||
@setBufferPosition(endOfLeadingWhitespace) if endOfLeadingWhitespace.isGreaterThan(position)
|
||||
|
||||
# Public: Moves the cursor to the end of the buffer line.
|
||||
# Moves the cursor to the end of the buffer line.
|
||||
moveToEndOfLine: ->
|
||||
@setBufferPosition([@getBufferRow(), Infinity])
|
||||
|
||||
# Public: Moves the cursor to the beginning of the word.
|
||||
# Moves the cursor to the beginning of the word.
|
||||
moveToBeginningOfWord: ->
|
||||
@setBufferPosition(@getBeginningOfCurrentWordBufferPosition())
|
||||
|
||||
# Public: Moves the cursor to the end of the word.
|
||||
# Moves the cursor to the end of the word.
|
||||
moveToEndOfWord: ->
|
||||
if position = @getEndOfCurrentWordBufferPosition()
|
||||
@setBufferPosition(position)
|
||||
|
||||
# Public: Moves the cursor to the beginning of the next word.
|
||||
# Moves the cursor to the beginning of the next word.
|
||||
moveToBeginningOfNextWord: ->
|
||||
if position = @getBeginningOfNextWordBufferPosition()
|
||||
@setBufferPosition(position)
|
||||
|
||||
# Public: Retrieves the buffer position of where the current word starts.
|
||||
# Retrieves the buffer position of where the current word starts.
|
||||
#
|
||||
# options - A hash with one option:
|
||||
# :wordRegex - A {RegExp} indicating what constitutes a "word" (default: {Cursor.wordRegExp})
|
||||
# wordRegex: A {RegExp} indicating what constitutes a "word" (default: {wordRegExp})
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBeginningOfCurrentWordBufferPosition: (options = {}) ->
|
||||
@@ -267,10 +265,10 @@ class Cursor
|
||||
|
||||
beginningOfWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Retrieves the buffer position of where the current word ends.
|
||||
# Retrieves the buffer position of where the current word ends.
|
||||
#
|
||||
# options - A hash with one option:
|
||||
# :wordRegex - A {RegExp} indicating what constitutes a "word" (default: {Cursor.wordRegExp})
|
||||
# wordRegex: A {RegExp} indicating what constitutes a "word" (default: {wordRegExp})
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getEndOfCurrentWordBufferPosition: (options = {}) ->
|
||||
@@ -287,10 +285,10 @@ class Cursor
|
||||
|
||||
endOfWordPosition ? currentBufferPosition
|
||||
|
||||
# Public: Retrieves the buffer position of where the next word starts.
|
||||
# Retrieves the buffer position of where the next word starts.
|
||||
#
|
||||
# options - A hash with one option:
|
||||
# :wordRegex - A {RegExp} indicating what constitutes a "word" (default: {Cursor.wordRegExp})
|
||||
# wordRegex: A {RegExp} indicating what constitutes a "word" (default: {wordRegExp})
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBeginningOfNextWordBufferPosition: (options = {}) ->
|
||||
@@ -305,7 +303,7 @@ class Cursor
|
||||
|
||||
beginningOfNextWordPosition or currentBufferPosition
|
||||
|
||||
# Public: Gets the word located under the cursor.
|
||||
# Gets the word located under the cursor.
|
||||
#
|
||||
# options - An object with properties based on {.getBeginningOfCurrentWordBufferPosition}.
|
||||
#
|
||||
@@ -315,7 +313,7 @@ class Cursor
|
||||
endOptions = _.extend(_.clone(options), allowNext: false)
|
||||
new Range(@getBeginningOfCurrentWordBufferPosition(startOptions), @getEndOfCurrentWordBufferPosition(endOptions))
|
||||
|
||||
# Public: Retrieves the range for the current line.
|
||||
# Retrieves the range for the current line.
|
||||
#
|
||||
# options - A hash with the same keys as {EditSession.bufferRangeForBufferRow}
|
||||
#
|
||||
@@ -323,7 +321,7 @@ class Cursor
|
||||
getCurrentLineBufferRange: (options) ->
|
||||
@editSession.bufferRangeForBufferRow(@getBufferRow(), options)
|
||||
|
||||
# Public: Retrieves the range for the current paragraph.
|
||||
# Retrieves the range for the current paragraph.
|
||||
#
|
||||
# A paragraph is defined as a block of text surrounded by empty lines.
|
||||
#
|
||||
@@ -345,19 +343,19 @@ class Cursor
|
||||
|
||||
new Range([startRow, 0], [endRow, @editSession.lineLengthForBufferRow(endRow)])
|
||||
|
||||
# Public: Retrieves the characters that constitute a word preceeding the current cursor position.
|
||||
# Retrieves the characters that constitute a word preceeding the current cursor position.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getCurrentWordPrefix: ->
|
||||
@editSession.getTextInBufferRange([@getBeginningOfCurrentWordBufferPosition(), @getBufferPosition()])
|
||||
|
||||
# Public: Identifies if the cursor is at the start of a line.
|
||||
# Identifies if the cursor is at the start of a line.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isAtBeginningOfLine: ->
|
||||
@getBufferPosition().column == 0
|
||||
|
||||
# Public: Retrieves the indentation level of the current line.
|
||||
# Retrieves the indentation level of the current line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getIndentLevel: ->
|
||||
@@ -366,13 +364,13 @@ class Cursor
|
||||
else
|
||||
@getBufferColumn()
|
||||
|
||||
# Public: Identifies if the cursor is at the end of a line.
|
||||
# Identifies if the cursor is at the end of a line.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isAtEndOfLine: ->
|
||||
@getBufferPosition().isEqual(@getCurrentLineBufferRange().end)
|
||||
|
||||
# Public: Retrieves the grammar's token scopes for the line.
|
||||
# Retrieves the grammar's token scopes for the line.
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
getScopes: ->
|
||||
|
||||
@@ -12,24 +12,26 @@ module.exports =
|
||||
class Directory
|
||||
path: null
|
||||
|
||||
# Public: Creates a new directory.
|
||||
### Public ###
|
||||
|
||||
# Creates a new directory.
|
||||
#
|
||||
# path - A {String} representing the file directory
|
||||
# symlink - A {Boolean} indicating if the path is a symlink (default: false)
|
||||
constructor: (@path, @symlink=false) ->
|
||||
|
||||
# Public: Retrieves the basename of the directory.
|
||||
# Retrieves the basename of the directory.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getBaseName: ->
|
||||
fsUtils.base(@path)
|
||||
|
||||
# Public: Retrieves the directory's path.
|
||||
# Retrieves the directory's path.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: -> @path
|
||||
|
||||
# Public: Retrieves the file entries in the directory.
|
||||
# Retrieves the file entries in the directory.
|
||||
#
|
||||
# This does follow symlinks.
|
||||
#
|
||||
@@ -51,9 +53,7 @@ class Directory
|
||||
|
||||
directories.concat(files)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
afterSubscribe: ->
|
||||
@subscribeToNativeChangeEvents() if @subscriptionCount() == 1
|
||||
|
||||
@@ -9,51 +9,47 @@ class DisplayBufferMarker
|
||||
tailScreenPosition: null
|
||||
valid: true
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: ({@bufferMarker, @displayBuffer}) ->
|
||||
@id = @bufferMarker.id
|
||||
@observeBufferMarker()
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Gets the screen range of the display marker.
|
||||
# Gets the screen range of the display marker.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getScreenRange: ->
|
||||
@displayBuffer.screenRangeForBufferRange(@getBufferRange(), wrapAtSoftNewlines: true)
|
||||
|
||||
# Public: Modifies the screen range of the display marker.
|
||||
# Modifies the screen range of the display marker.
|
||||
#
|
||||
# screenRange - The new {Range} to use
|
||||
# options - A hash of options matching those found in {BufferMarker.setRange}
|
||||
setScreenRange: (screenRange, options) ->
|
||||
@setBufferRange(@displayBuffer.bufferRangeForScreenRange(screenRange), options)
|
||||
|
||||
# Public: Gets the buffer range of the display marker.
|
||||
# Gets the buffer range of the display marker.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBufferRange: ->
|
||||
@bufferMarker.getRange()
|
||||
|
||||
# Public: Modifies the buffer range of the display marker.
|
||||
# Modifies the buffer range of the display marker.
|
||||
#
|
||||
# screenRange - The new {Range} to use
|
||||
# options - A hash of options matching those found in {BufferMarker.setRange}
|
||||
setBufferRange: (bufferRange, options) ->
|
||||
@bufferMarker.setRange(bufferRange, options)
|
||||
|
||||
# Public: Retrieves the screen position of the marker's head.
|
||||
# Retrieves the screen position of the marker's head.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getHeadScreenPosition: ->
|
||||
@headScreenPosition ?= @displayBuffer.screenPositionForBufferPosition(@getHeadBufferPosition(), wrapAtSoftNewlines: true)
|
||||
|
||||
# Public: Sets the screen position of the marker's head.
|
||||
# Sets the screen position of the marker's head.
|
||||
#
|
||||
# screenRange - The new {Point} to use
|
||||
# options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition}
|
||||
@@ -61,26 +57,26 @@ class DisplayBufferMarker
|
||||
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
|
||||
@setHeadBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options))
|
||||
|
||||
# Public: Retrieves the buffer position of the marker's head.
|
||||
# Retrieves the buffer position of the marker's head.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getHeadBufferPosition: ->
|
||||
@bufferMarker.getHeadPosition()
|
||||
|
||||
# Public: Sets the buffer position of the marker's head.
|
||||
# Sets the buffer position of the marker's head.
|
||||
#
|
||||
# screenRange - The new {Point} to use
|
||||
# options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition}
|
||||
setHeadBufferPosition: (bufferPosition) ->
|
||||
@bufferMarker.setHeadPosition(bufferPosition)
|
||||
|
||||
# Public: Retrieves the screen position of the marker's tail.
|
||||
# Retrieves the screen position of the marker's tail.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getTailScreenPosition: ->
|
||||
@tailScreenPosition ?= @displayBuffer.screenPositionForBufferPosition(@getTailBufferPosition(), wrapAtSoftNewlines: true)
|
||||
|
||||
# Public: Sets the screen position of the marker's tail.
|
||||
# Sets the screen position of the marker's tail.
|
||||
#
|
||||
# screenRange - The new {Point} to use
|
||||
# options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition}
|
||||
@@ -88,20 +84,20 @@ class DisplayBufferMarker
|
||||
screenPosition = @displayBuffer.clipScreenPosition(screenPosition, options)
|
||||
@setTailBufferPosition(@displayBuffer.bufferPositionForScreenPosition(screenPosition, options))
|
||||
|
||||
# Public: Retrieves the buffer position of the marker's tail.
|
||||
# Retrieves the buffer position of the marker's tail.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
getTailBufferPosition: ->
|
||||
@bufferMarker.getTailPosition()
|
||||
|
||||
# Public: Sets the buffer position of the marker's tail.
|
||||
# Sets the buffer position of the marker's tail.
|
||||
#
|
||||
# screenRange - The new {Point} to use
|
||||
# options - A hash of options matching those found in {DisplayBuffer.bufferPositionForScreenPosition}
|
||||
setTailBufferPosition: (bufferPosition) ->
|
||||
@bufferMarker.setTailPosition(bufferPosition)
|
||||
|
||||
# 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.
|
||||
#
|
||||
@@ -109,7 +105,7 @@ class DisplayBufferMarker
|
||||
placeTail: ->
|
||||
@bufferMarker.placeTail()
|
||||
|
||||
# Public: Removes the tail from the marker.
|
||||
# Removes the tail from the marker.
|
||||
clearTail: ->
|
||||
@bufferMarker.clearTail()
|
||||
|
||||
@@ -140,9 +136,7 @@ class DisplayBufferMarker
|
||||
inspect: ->
|
||||
"DisplayBufferMarker(id: #{@id}, bufferRange: #{@getBufferRange().inspect()})"
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
destroyed: ->
|
||||
delete @displayBuffer.markers[@id]
|
||||
|
||||
@@ -18,9 +18,7 @@ class DisplayBuffer
|
||||
markers: null
|
||||
foldsByMarkerId: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: (@buffer, options={}) ->
|
||||
@id = @constructor.idCounter++
|
||||
@@ -45,13 +43,14 @@ class DisplayBuffer
|
||||
@trigger 'changed', eventProperties
|
||||
@resumeMarkerObservers()
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Sets the visibility of the tokenized buffer.
|
||||
#
|
||||
# visible - A {Boolean} indicating of the tokenized buffer is shown
|
||||
setVisible: (visible) -> @tokenizedBuffer.setVisible(visible)
|
||||
|
||||
# Public: Defines the limit at which the buffer begins to soft wrap text.
|
||||
# Defines the limit at which the buffer begins to soft wrap text.
|
||||
#
|
||||
# softWrapColumn - A {Number} defining the soft wrap limit.
|
||||
setSoftWrapColumn: (@softWrapColumn) ->
|
||||
@@ -62,7 +61,7 @@ class DisplayBuffer
|
||||
bufferDelta = 0
|
||||
@triggerChanged({ start, end, screenDelta, bufferDelta })
|
||||
|
||||
# Public: Gets the screen line for the given screen row.
|
||||
# Gets the screen line for the given screen row.
|
||||
#
|
||||
# screenRow - A {Number} indicating the screen row.
|
||||
#
|
||||
@@ -70,7 +69,7 @@ class DisplayBuffer
|
||||
lineForRow: (row) ->
|
||||
@lineMap.lineForScreenRow(row)
|
||||
|
||||
# Public: Gets the screen lines for the given screen row range.
|
||||
# Gets the screen lines for the given screen row range.
|
||||
#
|
||||
# startRow - A {Number} indicating the beginning screen row.
|
||||
# endRow - A {Number} indicating the ending screen row.
|
||||
@@ -79,14 +78,14 @@ class DisplayBuffer
|
||||
linesForRows: (startRow, endRow) ->
|
||||
@lineMap.linesForScreenRows(startRow, endRow)
|
||||
|
||||
# Public: Gets all the screen lines.
|
||||
# Gets all the screen lines.
|
||||
#
|
||||
# Returns an {Array} of {ScreenLines}s.
|
||||
getLines: ->
|
||||
@lineMap.linesForScreenRows(0, @lineMap.lastScreenRow())
|
||||
|
||||
|
||||
# Public: Given starting and ending screen rows, this returns an array of the
|
||||
# Given starting and ending screen rows, this returns an array of the
|
||||
# buffer rows corresponding to every screen row in the range
|
||||
#
|
||||
# startRow - The screen row {Number} to start at
|
||||
@@ -96,7 +95,7 @@ class DisplayBuffer
|
||||
bufferRowsForScreenRows: (startRow, endRow) ->
|
||||
@lineMap.bufferRowsForScreenRows(startRow, endRow)
|
||||
|
||||
# Public: Creates a new fold between two row numbers.
|
||||
# Creates a new fold between two row numbers.
|
||||
#
|
||||
# startRow - The row {Number} to start folding at
|
||||
# endRow - The row {Number} to end the fold
|
||||
@@ -108,14 +107,16 @@ class DisplayBuffer
|
||||
@buffer.markRange([[startRow, 0], [endRow, Infinity]], @foldMarkerAttributes())
|
||||
@foldForMarker(foldMarker)
|
||||
|
||||
# Public: Removes any folds found that contain the given buffer row.
|
||||
# Removes any folds found that contain the given buffer row.
|
||||
#
|
||||
# bufferRow - The buffer row {Number} to check against
|
||||
destroyFoldsContainingBufferRow: (bufferRow) ->
|
||||
fold.destroy() for fold in @foldsContainingBufferRow(bufferRow)
|
||||
|
||||
# Largest is defined as the fold whose difference between its start and end rows
|
||||
# is the greatest.
|
||||
# Given a buffer row, this returns the largest fold that starts there.
|
||||
#
|
||||
# Largest is defined as the fold whose difference between its start and end points
|
||||
# are the greatest.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
#
|
||||
@@ -132,7 +133,7 @@ class DisplayBuffer
|
||||
for marker in @findFoldMarkers(startRow: bufferRow)
|
||||
@foldForMarker(marker)
|
||||
|
||||
# Public: Given a screen row, this returns the largest fold that starts there.
|
||||
# Given a screen row, this returns the largest fold that starts there.
|
||||
#
|
||||
# Largest is defined as the fold whose difference between its start and end points
|
||||
# are the greatest.
|
||||
@@ -143,7 +144,7 @@ class DisplayBuffer
|
||||
largestFoldStartingAtScreenRow: (screenRow) ->
|
||||
@largestFoldStartingAtBufferRow(@bufferRowForScreenRow(screenRow))
|
||||
|
||||
# Public: Given a buffer row, this returns the largest fold that includes it.
|
||||
# Given a buffer row, this returns the largest fold that includes it.
|
||||
#
|
||||
# Largest is defined as the fold whose difference between its start and end rows
|
||||
# is the greatest.
|
||||
@@ -164,7 +165,7 @@ class DisplayBuffer
|
||||
for marker in @findFoldMarkers(containsRow: bufferRow)
|
||||
@foldForMarker(marker)
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen range.
|
||||
# Given a buffer range, this converts it into a screen range.
|
||||
#
|
||||
# bufferRange - A {Range} consisting of buffer positions
|
||||
#
|
||||
@@ -174,7 +175,7 @@ class DisplayBuffer
|
||||
@lineMap.screenRangeForBufferRange(
|
||||
@expandBufferRangeToLineEnds(bufferRange)))
|
||||
|
||||
# Public: Given a buffer row, this converts it into a screen row.
|
||||
# Given a buffer row, this converts it into a screen row.
|
||||
#
|
||||
# bufferRow - A {Number} representing a buffer row
|
||||
#
|
||||
@@ -185,7 +186,7 @@ class DisplayBuffer
|
||||
lastScreenRowForBufferRow: (bufferRow) ->
|
||||
@lineMap.screenPositionForBufferPosition([bufferRow, Infinity]).row
|
||||
|
||||
# Public: Given a screen row, this converts it into a buffer row.
|
||||
# Given a screen row, this converts it into a buffer row.
|
||||
#
|
||||
# screenRow - A {Number} representing a screen row
|
||||
#
|
||||
@@ -193,7 +194,7 @@ class DisplayBuffer
|
||||
bufferRowForScreenRow: (screenRow) ->
|
||||
@lineMap.bufferPositionForScreenPosition([screenRow, 0]).row
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen position.
|
||||
# Given a buffer range, this converts it into a screen position.
|
||||
#
|
||||
# bufferRange - The {Range} to convert
|
||||
#
|
||||
@@ -201,7 +202,7 @@ class DisplayBuffer
|
||||
screenRangeForBufferRange: (bufferRange) ->
|
||||
@lineMap.screenRangeForBufferRange(bufferRange)
|
||||
|
||||
# Public: Given a screen range, this converts it into a buffer position.
|
||||
# Given a screen range, this converts it into a buffer position.
|
||||
#
|
||||
# screenRange - The {Range} to convert
|
||||
#
|
||||
@@ -209,49 +210,49 @@ class DisplayBuffer
|
||||
bufferRangeForScreenRange: (screenRange) ->
|
||||
@lineMap.bufferRangeForScreenRange(screenRange)
|
||||
|
||||
# Public: Gets the number of lines in the buffer.
|
||||
# Gets the number of screen lines.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLineCount: ->
|
||||
@lineMap.getScreenLineCount()
|
||||
|
||||
# Public: Gets the number of the last row in the buffer.
|
||||
# Gets the number of the last screen line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastRow: ->
|
||||
@getLineCount() - 1
|
||||
|
||||
# Public: Gets the length of the longest screen line.
|
||||
# Gets the length of the longest screen line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
maxLineLength: ->
|
||||
@lineMap.maxScreenLineLength
|
||||
|
||||
# Public: Given a buffer position, this converts it into a screen position.
|
||||
# Given a buffer position, this converts it into a screen position.
|
||||
#
|
||||
# bufferPosition - An object that represents a buffer position. It can be either
|
||||
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
|
||||
# options - A hash of options with the following keys:
|
||||
# :wrapBeyondNewlines -
|
||||
# :wrapAtSoftNewlines -
|
||||
# wrapBeyondNewlines:
|
||||
# wrapAtSoftNewlines:
|
||||
#
|
||||
# Returns a {Point}.
|
||||
screenPositionForBufferPosition: (position, options) ->
|
||||
@lineMap.screenPositionForBufferPosition(position, options)
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen position.
|
||||
# Given a buffer range, this converts it into a screen position.
|
||||
#
|
||||
# screenPosition - An object that represents a buffer position. It can be either
|
||||
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
|
||||
# options - A hash of options with the following keys:
|
||||
# :wrapBeyondNewlines -
|
||||
# :wrapAtSoftNewlines -
|
||||
# wrapBeyondNewlines:
|
||||
# wrapAtSoftNewlines:
|
||||
#
|
||||
# Returns a {Point}.
|
||||
bufferPositionForScreenPosition: (position, options) ->
|
||||
@lineMap.bufferPositionForScreenPosition(position, options)
|
||||
|
||||
# Public: Retrieves the grammar's token scopes for a buffer position.
|
||||
# Retrieves the grammar's token scopes for a buffer position.
|
||||
#
|
||||
# bufferPosition - A {Point} in the {Buffer}
|
||||
#
|
||||
@@ -259,7 +260,7 @@ class DisplayBuffer
|
||||
scopesForBufferPosition: (bufferPosition) ->
|
||||
@tokenizedBuffer.scopesForPosition(bufferPosition)
|
||||
|
||||
# Public: Retrieves the grammar's token for a buffer position.
|
||||
# Retrieves the grammar's token for a buffer position.
|
||||
#
|
||||
# bufferPosition - A {Point} in the {Buffer}.
|
||||
#
|
||||
@@ -267,28 +268,33 @@ class DisplayBuffer
|
||||
tokenForBufferPosition: (bufferPosition) ->
|
||||
@tokenizedBuffer.tokenForPosition(bufferPosition)
|
||||
|
||||
# Public: Retrieves the current tab length.
|
||||
# Retrieves the current tab length.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getTabLength: ->
|
||||
@tokenizedBuffer.getTabLength()
|
||||
|
||||
# Public: Specifies the tab length.
|
||||
# Specifies the tab length.
|
||||
#
|
||||
# tabLength - A {Number} that defines the new tab length.
|
||||
setTabLength: (tabLength) ->
|
||||
@tokenizedBuffer.setTabLength(tabLength)
|
||||
|
||||
# Retrieves the grammar for the buffer.
|
||||
getGrammar: ->
|
||||
@tokenizedBuffer.grammar
|
||||
|
||||
# Sets the grammar for the buffer.
|
||||
#
|
||||
# grammar - Sets the new grammar rules
|
||||
setGrammar: (grammar) ->
|
||||
@tokenizedBuffer.setGrammar(grammar)
|
||||
|
||||
# Reloads the current grammar.
|
||||
reloadGrammar: ->
|
||||
@tokenizedBuffer.reloadGrammar()
|
||||
|
||||
# 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
|
||||
@@ -296,17 +302,181 @@ class DisplayBuffer
|
||||
#
|
||||
# position - The {Point} to clip
|
||||
# options - A hash with the following values:
|
||||
# :wrapBeyondNewlines - if `true`, continues wrapping past newlines
|
||||
# :wrapAtSoftNewlines - if `true`, continues wrapping past soft newlines
|
||||
# :screenLine - if `true`, indicates that you're using a line number, not a row number
|
||||
# wrapBeyondNewlines: if `true`, continues wrapping past newlines
|
||||
# wrapAtSoftNewlines: if `true`, continues wrapping past soft newlines
|
||||
# screenLine: if `true`, indicates that you're using a line number, not a row number
|
||||
#
|
||||
# Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed.
|
||||
clipScreenPosition: (position, options) ->
|
||||
@lineMap.clipScreenPosition(position, options)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Given a line, finds the point where it would wrap.
|
||||
#
|
||||
# line - The {String} to check
|
||||
# softWrapColumn - The {Number} where you want soft wrapping to occur
|
||||
#
|
||||
# Returns a {Number} representing the `line` position where the wrap would take place.
|
||||
# Returns `null` if a wrap wouldn't occur.
|
||||
findWrapColumn: (line, softWrapColumn) ->
|
||||
return unless line.length > softWrapColumn
|
||||
|
||||
if /\s/.test(line[softWrapColumn])
|
||||
# search forward for the start of a word past the boundary
|
||||
for column in [softWrapColumn..line.length]
|
||||
return column if /\S/.test(line[column])
|
||||
return line.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [softWrapColumn..0]
|
||||
return column + 1 if /\s/.test(line[column])
|
||||
return softWrapColumn
|
||||
|
||||
# Given a range in screen coordinates, this expands it to the start and end of a line
|
||||
#
|
||||
# screenRange - The {Range} to expand
|
||||
#
|
||||
# Returns a new {Range}.
|
||||
expandScreenRangeToLineEnds: (screenRange) ->
|
||||
screenRange = Range.fromObject(screenRange)
|
||||
{ start, end } = screenRange
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForScreenRow(end.row).text.length])
|
||||
|
||||
# Given a range in buffer coordinates, this expands it to the start and end of a line
|
||||
#
|
||||
# screenRange - The {Range} to expand
|
||||
#
|
||||
# Returns a new {Range}.
|
||||
expandBufferRangeToLineEnds: (bufferRange) ->
|
||||
bufferRange = Range.fromObject(bufferRange)
|
||||
{ start, end } = bufferRange
|
||||
new Range([start.row, 0], [end.row, Infinity])
|
||||
|
||||
# Calculates a {Range} representing the start of the {Buffer} until the end.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
rangeForAllLines: ->
|
||||
new Range([0, 0], @clipScreenPosition([Infinity, Infinity]))
|
||||
|
||||
# Retrieves a {DisplayBufferMarker} based on its id.
|
||||
#
|
||||
# id - A {Number} representing a marker id
|
||||
#
|
||||
# Returns the {DisplayBufferMarker} (if it exists).
|
||||
getMarker: (id) ->
|
||||
@markers[id] ?= do =>
|
||||
if bufferMarker = @buffer.getMarker(id)
|
||||
new DisplayBufferMarker({bufferMarker, displayBuffer: this})
|
||||
|
||||
# Retrieves the active markers in the buffer.
|
||||
#
|
||||
# Returns an {Array} of existing {DisplayBufferMarker}s.
|
||||
getMarkers: ->
|
||||
_.values(@markers)
|
||||
|
||||
# Constructs a new marker at the given screen range.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markScreenRange: (args...) ->
|
||||
bufferRange = @bufferRangeForScreenRange(args.shift())
|
||||
@markBufferRange(bufferRange, args...)
|
||||
|
||||
# Constructs a new marker at the given buffer range.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markBufferRange: (args...) ->
|
||||
@getMarker(@buffer.markRange(args...).id)
|
||||
|
||||
# Constructs a new marker at the given screen position.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markScreenPosition: (screenPosition, options) ->
|
||||
@markBufferPosition(@bufferPositionForScreenPosition(screenPosition), options)
|
||||
|
||||
# Constructs a new marker at the given buffer position.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markBufferPosition: (bufferPosition, options) ->
|
||||
@getMarker(@buffer.markPosition(bufferPosition, options).id)
|
||||
|
||||
# Removes the marker with the given id.
|
||||
#
|
||||
# id - The {Number} of the ID to remove
|
||||
destroyMarker: (id) ->
|
||||
@buffer.destroyMarker(id)
|
||||
delete @markers[id]
|
||||
|
||||
# Finds the first marker satisfying the given attributes
|
||||
#
|
||||
# Refer to {DisplayBuffer.findMarkers} for details.
|
||||
#
|
||||
# Returns a {DisplayBufferMarker} or null
|
||||
findMarker: (attributes) ->
|
||||
@findMarkers(attributes)[0]
|
||||
|
||||
# Finds all valid markers satisfying the given attributes
|
||||
#
|
||||
# attributes - The attributes against which to compare the markers' attributes
|
||||
# There are some reserved keys that match against derived marker properties:
|
||||
# startBufferRow - The buffer row at which the marker starts
|
||||
# endBufferRow - The buffer row at which the marker ends
|
||||
#
|
||||
# Returns an {Array} of {DisplayBufferMarker}s
|
||||
findMarkers: (attributes) ->
|
||||
{ startBufferRow, endBufferRow, containsBufferRange, containsBufferRow } = attributes
|
||||
attributes.startRow = startBufferRow if startBufferRow?
|
||||
attributes.endRow = endBufferRow if endBufferRow?
|
||||
attributes.containsRange = containsBufferRange if containsBufferRange?
|
||||
attributes.containsRow = containsBufferRow if containsBufferRow?
|
||||
attributes = _.omit(attributes, ['startBufferRow', 'endBufferRow', 'containsBufferRange', 'containsBufferRow'])
|
||||
@buffer.findMarkers(attributes).map ({id}) => @getMarker(id)
|
||||
|
||||
findFoldMarker: (attributes) ->
|
||||
@findFoldMarkers(attributes)[0]
|
||||
|
||||
findFoldMarkers: (attributes) ->
|
||||
@buffer.findMarkers(@foldMarkerAttributes(attributes))
|
||||
|
||||
foldMarkerAttributes: (attributes={}) ->
|
||||
_.extend(attributes, class: 'fold', displayBufferId: @id)
|
||||
|
||||
pauseMarkerObservers: ->
|
||||
marker.pauseEvents() for marker in @getMarkers()
|
||||
|
||||
resumeMarkerObservers: ->
|
||||
marker.resumeEvents() for marker in @getMarkers()
|
||||
|
||||
refreshMarkerScreenPositions: ->
|
||||
for marker in @getMarkers()
|
||||
marker.notifyObservers(bufferChanged: false)
|
||||
|
||||
destroy: ->
|
||||
@tokenizedBuffer.destroy()
|
||||
@unsubscribe()
|
||||
|
||||
logLines: (start, end) ->
|
||||
@lineMap.logLines(start, end)
|
||||
|
||||
getDebugSnapshot: ->
|
||||
lines = ["Display Buffer:"]
|
||||
for screenLine, row in @lineMap.linesForScreenRows(0, @getLastRow())
|
||||
lines.push "#{row}: #{screenLine.text}"
|
||||
lines.join('\n')
|
||||
|
||||
### Internal ###
|
||||
|
||||
handleTokenizedBufferChange: (tokenizedBufferChange) =>
|
||||
{start, end, delta, bufferChange} = tokenizedBufferChange
|
||||
@@ -381,177 +551,6 @@ class DisplayBuffer
|
||||
foldForMarker: (marker) ->
|
||||
@foldsByMarkerId[marker.id]
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
|
||||
# Public: Given a line, finds the point where it would wrap.
|
||||
#
|
||||
# line - The {String} to check
|
||||
# softWrapColumn - The {Number} where you want soft wrapping to occur
|
||||
#
|
||||
# Returns a {Number} representing the `line` position where the wrap would take place.
|
||||
# Returns `null` if a wrap wouldn't occur.
|
||||
findWrapColumn: (line, softWrapColumn) ->
|
||||
return unless line.length > softWrapColumn
|
||||
|
||||
if /\s/.test(line[softWrapColumn])
|
||||
# search forward for the start of a word past the boundary
|
||||
for column in [softWrapColumn..line.length]
|
||||
return column if /\S/.test(line[column])
|
||||
return line.length
|
||||
else
|
||||
# search backward for the start of the word on the boundary
|
||||
for column in [softWrapColumn..0]
|
||||
return column + 1 if /\s/.test(line[column])
|
||||
return softWrapColumn
|
||||
|
||||
# Public: Given a range in screen coordinates, this expands it to the start and end of a line
|
||||
#
|
||||
# screenRange - The {Range} to expand
|
||||
#
|
||||
# Returns a new {Range}.
|
||||
expandScreenRangeToLineEnds: (screenRange) ->
|
||||
screenRange = Range.fromObject(screenRange)
|
||||
{ start, end } = screenRange
|
||||
new Range([start.row, 0], [end.row, @lineMap.lineForScreenRow(end.row).text.length])
|
||||
|
||||
# Public: Given a range in buffer coordinates, this expands it to the start and end of a line
|
||||
#
|
||||
# screenRange - The {Range} to expand
|
||||
#
|
||||
# Returns a new {Range}.
|
||||
expandBufferRangeToLineEnds: (bufferRange) ->
|
||||
bufferRange = Range.fromObject(bufferRange)
|
||||
{ start, end } = bufferRange
|
||||
new Range([start.row, 0], [end.row, Infinity])
|
||||
|
||||
# Public: Calculates a {Range} representing the start of the {Buffer} until the end.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
rangeForAllLines: ->
|
||||
new Range([0, 0], @clipScreenPosition([Infinity, Infinity]))
|
||||
|
||||
# Public: Retrieves a {DisplayBufferMarker} based on its id.
|
||||
#
|
||||
# id - A {Number} representing a marker id
|
||||
#
|
||||
# Returns the {DisplayBufferMarker} (if it exists).
|
||||
getMarker: (id) ->
|
||||
@markers[id] ?= do =>
|
||||
if bufferMarker = @buffer.getMarker(id)
|
||||
new DisplayBufferMarker({bufferMarker, displayBuffer: this})
|
||||
|
||||
# Public: Retrieves the active markers in the buffer.
|
||||
#
|
||||
# Returns an {Array} of existing {DisplayBufferMarker}s.
|
||||
getMarkers: ->
|
||||
_.values(@markers)
|
||||
|
||||
# Public: Constructs a new marker at the given screen range.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markScreenRange: (args...) ->
|
||||
bufferRange = @bufferRangeForScreenRange(args.shift())
|
||||
@markBufferRange(bufferRange, args...)
|
||||
|
||||
# Public: Constructs a new marker at the given buffer range.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markBufferRange: (args...) ->
|
||||
@getMarker(@buffer.markRange(args...).id)
|
||||
|
||||
# Public: Constructs a new marker at the given screen position.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markScreenPosition: (screenPosition, options) ->
|
||||
@markBufferPosition(@bufferPositionForScreenPosition(screenPosition), options)
|
||||
|
||||
# Public: Constructs a new marker at the given buffer position.
|
||||
#
|
||||
# range - The marker {Range} (representing the distance between the head and tail)
|
||||
# options - Options to pass to the {BufferMarker} constructor
|
||||
#
|
||||
# Returns a {Number} representing the new marker's ID.
|
||||
markBufferPosition: (bufferPosition, options) ->
|
||||
@getMarker(@buffer.markPosition(bufferPosition, options).id)
|
||||
|
||||
# Public: Removes the marker with the given id.
|
||||
#
|
||||
# id - The {Number} of the ID to remove
|
||||
destroyMarker: (id) ->
|
||||
@buffer.destroyMarker(id)
|
||||
delete @markers[id]
|
||||
|
||||
# Finds the first marker satisfying the given attributes
|
||||
#
|
||||
# Refer to {DisplayBuffer.findMarkers} for details.
|
||||
#
|
||||
# Returns a {DisplayBufferMarker} or null
|
||||
findMarker: (attributes) ->
|
||||
@findMarkers(attributes)[0]
|
||||
|
||||
# Finds all valid markers satisfying the given attributes
|
||||
#
|
||||
# attributes - The attributes against which to compare the markers' attributes
|
||||
# There are some reserved keys that match against derived marker properties:
|
||||
# startBufferRow - The buffer row at which the marker starts
|
||||
# endBufferRow - The buffer row at which the marker ends
|
||||
#
|
||||
# Returns an {Array} of {DisplayBufferMarker}s
|
||||
findMarkers: (attributes) ->
|
||||
{ startBufferRow, endBufferRow, containsBufferRange, containsBufferRow } = attributes
|
||||
attributes.startRow = startBufferRow if startBufferRow?
|
||||
attributes.endRow = endBufferRow if endBufferRow?
|
||||
attributes.containsRange = containsBufferRange if containsBufferRange?
|
||||
attributes.containsRow = containsBufferRow if containsBufferRow?
|
||||
attributes = _.omit(attributes, ['startBufferRow', 'endBufferRow', 'containsBufferRange', 'containsBufferRow'])
|
||||
@buffer.findMarkers(attributes).map ({id}) => @getMarker(id)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
findFoldMarker: (attributes) ->
|
||||
@findFoldMarkers(attributes)[0]
|
||||
|
||||
findFoldMarkers: (attributes) ->
|
||||
@buffer.findMarkers(@foldMarkerAttributes(attributes))
|
||||
|
||||
foldMarkerAttributes: (attributes={}) ->
|
||||
_.extend(attributes, class: 'fold', displayBufferId: @id)
|
||||
|
||||
pauseMarkerObservers: ->
|
||||
marker.pauseEvents() for marker in @getMarkers()
|
||||
|
||||
resumeMarkerObservers: ->
|
||||
marker.resumeEvents() for marker in @getMarkers()
|
||||
|
||||
refreshMarkerScreenPositions: ->
|
||||
for marker in @getMarkers()
|
||||
marker.notifyObservers(bufferChanged: false)
|
||||
|
||||
destroy: ->
|
||||
@tokenizedBuffer.destroy()
|
||||
@unsubscribe()
|
||||
|
||||
logLines: (start, end) ->
|
||||
@lineMap.logLines(start, end)
|
||||
|
||||
getDebugSnapshot: ->
|
||||
lines = ["Display Buffer:"]
|
||||
for screenLine, row in @lineMap.linesForScreenRows(0, @getLastRow())
|
||||
lines.push "#{row}: #{screenLine.text}"
|
||||
lines.join('\n')
|
||||
|
||||
_.extend DisplayBuffer.prototype, EventEmitter
|
||||
_.extend DisplayBuffer.prototype, Subscriber
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,7 @@ class EditorConfigPanel extends ConfigPanel
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', "Font Size:"
|
||||
@div class: 'controls', =>
|
||||
@subview "fontSizeEditor", new Editor(mini: true, attributes: {id: 'editor.fontSize', type: 'int', style: 'width: 40px'})
|
||||
@subview "fontSizeEditor", new Editor(mini: true, attributes: {id: 'editor.fontSize', type: 'int', style: 'width: 4em'})
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', "Font Family:"
|
||||
@@ -56,7 +56,7 @@ class EditorConfigPanel extends ConfigPanel
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', for: 'editor.preferredLineLength', "Preferred Line Length:"
|
||||
@div class: 'controls', =>
|
||||
@subview "preferredLineLengthEditor", new Editor(mini: true, attributes: {id: 'editor.preferredLineLength', type: 'int', style: 'width: 40px'})
|
||||
@subview "preferredLineLengthEditor", new Editor(mini: true, attributes: {id: 'editor.preferredLineLength', type: 'int', style: 'width: 4em'})
|
||||
|
||||
@div class: 'control-group', =>
|
||||
@label class: 'control-label', for: 'editor.nonWordCharacters', "Non-Word Characters:"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@ _ = require 'underscore'
|
||||
#
|
||||
# Each event can have more than one handler; that is, an event can trigger multiple functions.
|
||||
module.exports =
|
||||
# Public: Associates an event name with a function to perform.
|
||||
# Associates an event name with a function to perform.
|
||||
#
|
||||
# This is called endlessly, until the event is turned {.off}.
|
||||
#
|
||||
@@ -27,7 +27,7 @@ module.exports =
|
||||
@afterSubscribe?()
|
||||
|
||||
|
||||
# Public: Associates an event name with a function to perform only once.
|
||||
# Associates an event name with a function to perform only once.
|
||||
#
|
||||
# eventName - A {String} name identifying an event
|
||||
# handler - A {Function} that's executed when the event is triggered
|
||||
@@ -38,7 +38,7 @@ module.exports =
|
||||
|
||||
@on eventName, oneShotHandler
|
||||
|
||||
# Public: Triggers a registered event.
|
||||
# Triggers a registered event.
|
||||
#
|
||||
# eventName - A {String} name identifying an event
|
||||
# args - Any additional arguments to pass over to the event `handler`
|
||||
@@ -55,7 +55,7 @@ module.exports =
|
||||
if handlers = @eventHandlersByEventName?[eventName]
|
||||
handlers.forEach (handler) -> handler(args...)
|
||||
|
||||
# Public: Stops executing handlers for a registered event.
|
||||
# Stops executing handlers for a registered event.
|
||||
#
|
||||
# eventNames - A {String} containing one or more space-separated events.
|
||||
# handler - The {Function} to remove from the event. If not provided, all handlers are removed.
|
||||
@@ -90,20 +90,20 @@ module.exports =
|
||||
@eventHandlersByNamespace = {}
|
||||
@afterUnsubscribe?() if @subscriptionCount() < subscriptionCountBefore
|
||||
|
||||
# Public: When called, stops triggering any events.
|
||||
# When called, stops triggering any events.
|
||||
pauseEvents: ->
|
||||
@pauseCount ?= 0
|
||||
if @pauseCount++ == 0
|
||||
@queuedEvents ?= []
|
||||
|
||||
# Public: When called, resumes triggering events.
|
||||
# When called, resumes triggering events.
|
||||
resumeEvents: ->
|
||||
if --@pauseCount == 0
|
||||
queuedEvents = @queuedEvents
|
||||
@queuedEvents = null
|
||||
@trigger(event...) for event in queuedEvents
|
||||
|
||||
# Public: Identifies how many events are registered.
|
||||
# Identifies how many events are registered.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
subscriptionCount: ->
|
||||
|
||||
@@ -7,7 +7,7 @@ _ = require 'underscore'
|
||||
|
||||
# Public: Represents an individual file in the editor.
|
||||
#
|
||||
# The entry point for this class is in two locations:
|
||||
# The entry point for this class is in two locations:
|
||||
# * {Buffer}, which associates text contents with a file
|
||||
# * {Directory}, which associcates the children of a directory as files
|
||||
module.exports =
|
||||
@@ -15,7 +15,7 @@ class File
|
||||
path: null
|
||||
cachedContents: null
|
||||
|
||||
# Public: Creates a new file.
|
||||
# Creates a new file.
|
||||
#
|
||||
# path - A {String} representing the file path
|
||||
# symlink - A {Boolean} indicating if the path is a symlink (default: false)
|
||||
@@ -24,23 +24,23 @@ class File
|
||||
if fs.statSync(@path).isDirectory()
|
||||
throw new Error("#{@path} is a directory")
|
||||
|
||||
# Public: Sets the path for the file.
|
||||
# Sets the path for the file.
|
||||
#
|
||||
# path - A {String} representing the new file path
|
||||
setPath: (@path) ->
|
||||
|
||||
# Public: Retrieves the path for the file.
|
||||
# Retrieves the path for the file.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: -> @path
|
||||
|
||||
# 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: ->
|
||||
fsUtils.base(@path)
|
||||
|
||||
# Public: Writes (and saves) new contents to the file.
|
||||
# Writes (and saves) new contents to the file.
|
||||
#
|
||||
# text - A {String} representing the new contents.
|
||||
write: (text) ->
|
||||
@@ -49,7 +49,7 @@ class File
|
||||
fsUtils.write(@getPath(), text)
|
||||
@subscribeToNativeChangeEvents() if not previouslyExisted and @subscriptionCount() > 0
|
||||
|
||||
# Public: Reads the file.
|
||||
# Reads the file.
|
||||
#
|
||||
# flushCache - A {Boolean} indicating if the cache should be erased--_i.e._, a force read is performed
|
||||
#
|
||||
@@ -62,19 +62,17 @@ class File
|
||||
else
|
||||
@cachedContents
|
||||
|
||||
# Public: Checks to see if a file exists.
|
||||
# Checks to see if a file exists.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
exists: ->
|
||||
fsUtils.exists(@getPath())
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
afterSubscribe: ->
|
||||
@subscribeToNativeChangeEvents() if @exists() and @subscriptionCount() == 1
|
||||
|
||||
|
||||
afterUnsubscribe: ->
|
||||
@unsubscribeFromNativeChangeEvents() if @subscriptionCount() == 0
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@ class Fold
|
||||
displayBuffer: null
|
||||
marker: null
|
||||
|
||||
# Internal
|
||||
### Internal ###
|
||||
|
||||
constructor: (@displayBuffer, @marker) ->
|
||||
@displayBuffer.foldsByMarkerId[@marker.id] = this
|
||||
@updateDisplayBuffer()
|
||||
@@ -25,6 +26,10 @@ class Fold
|
||||
@marker.destroy()
|
||||
|
||||
# Returns the fold's {Range} in buffer coordinates
|
||||
#
|
||||
# includeNewline - A {Boolean} which, if `true`, includes the trailing newline
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBufferRange: ({includeNewline}={}) ->
|
||||
range = @marker.getRange()
|
||||
if includeNewline
|
||||
@@ -36,6 +41,12 @@ class Fold
|
||||
getStartRow: ->
|
||||
@getBufferRange().start.row
|
||||
|
||||
# Retrieves the number of buffer rows a fold occupies.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getBufferRowCount: ->
|
||||
@endRow - @startRow + 1
|
||||
|
||||
# Returns the fold's end row as a {Number}.
|
||||
getEndRow: ->
|
||||
@getBufferRange().end.row
|
||||
@@ -50,7 +61,13 @@ class Fold
|
||||
getBufferRowCount: ->
|
||||
@getEndRow() - @getStartRow() + 1
|
||||
|
||||
## Internal ##
|
||||
# Identifies if a fold is nested within a fold.
|
||||
#
|
||||
# fold - A {Fold} to check
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isContainedByFold: (fold) ->
|
||||
@isContainedByRange(fold.getBufferRange())
|
||||
|
||||
updateDisplayBuffer: ->
|
||||
unless @isInsideLargerFold()
|
||||
|
||||
@@ -11,33 +11,17 @@ GitUtils = require 'git-utils'
|
||||
module.exports =
|
||||
class Git
|
||||
|
||||
# Public: Creates a new `Git` instance.
|
||||
#
|
||||
# path - The git repository to open
|
||||
# options - A hash with one key:
|
||||
# :refreshOnWindowFocus - A {Boolean} that identifies if the windows should refresh
|
||||
#
|
||||
# Returns a new {Git} object.
|
||||
@open: (path, options) ->
|
||||
return null unless path
|
||||
try
|
||||
new Git(path, options)
|
||||
catch e
|
||||
null
|
||||
|
||||
statuses: null
|
||||
upstream: null
|
||||
statusTask: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
# Internal: Creates a new `Git` object.
|
||||
# Creates a new `Git` object.
|
||||
#
|
||||
# path - The {String} representing the path to your git working directory
|
||||
# options - A hash with the following keys:
|
||||
# :refreshOnWindowFocus - If `true`, {#refreshIndex} and {#refreshStatus} are called on focus
|
||||
# refreshOnWindowFocus: If `true`, {#refreshIndex} and {#refreshStatus} are called on focus
|
||||
constructor: (path, options={}) ->
|
||||
@repo = GitUtils.open(path)
|
||||
unless @repo?
|
||||
@@ -72,11 +56,23 @@ class Git
|
||||
|
||||
@unsubscribe()
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Retrieves the git repository.
|
||||
# Creates a new `Git` instance.
|
||||
#
|
||||
# path - The git repository to open
|
||||
# options - A hash with one key:
|
||||
# refreshOnWindowFocus: A {Boolean} that identifies if the windows should refresh
|
||||
#
|
||||
# Returns a new {Git} object.
|
||||
@open: (path, options) ->
|
||||
return null unless path
|
||||
try
|
||||
new Git(path, options)
|
||||
catch e
|
||||
null
|
||||
|
||||
# Retrieves the git repository.
|
||||
#
|
||||
# Returns a new `Repository`.
|
||||
getRepo: ->
|
||||
@@ -84,22 +80,22 @@ class Git
|
||||
throw new Error("Repository has been destroyed")
|
||||
@repo
|
||||
|
||||
# Public: Reread the index to update any values that have changed since the last time the index was read.
|
||||
# Reread the index to update any values that have changed since the last time the index was read.
|
||||
refreshIndex: -> @getRepo().refreshIndex()
|
||||
|
||||
# Public: Retrieves the path of the repository.
|
||||
# Retrieves the path of the repository.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: ->
|
||||
@path ?= fsUtils.absolute(@getRepo().getPath())
|
||||
|
||||
# Public: Retrieves the working directory of the repository.
|
||||
# Retrieves the working directory of the repository.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getWorkingDirectory: ->
|
||||
@getRepo().getWorkingDirectory()
|
||||
|
||||
# Public: Retrieves the reference or SHA-1 that `HEAD` points to.
|
||||
# Retrieves the reference or SHA-1 that `HEAD` points to.
|
||||
#
|
||||
# This can be `refs/heads/master`, or a full SHA-1 if the repository is in a detached `HEAD` state.
|
||||
#
|
||||
@@ -107,7 +103,7 @@ class Git
|
||||
getHead: ->
|
||||
@getRepo().getHead() ? ''
|
||||
|
||||
# Public: Retrieves the status of a single path in the repository.
|
||||
# Retrieves the status of a single path in the repository.
|
||||
#
|
||||
# path - An {String} defining a relative path
|
||||
#
|
||||
@@ -123,7 +119,7 @@ class Git
|
||||
@trigger 'status-changed', path, pathStatus
|
||||
pathStatus
|
||||
|
||||
# Public: Identifies if a path is ignored.
|
||||
# Identifies if a path is ignored.
|
||||
#
|
||||
# path - The {String} path to check
|
||||
#
|
||||
@@ -131,7 +127,7 @@ class Git
|
||||
isPathIgnored: (path) ->
|
||||
@getRepo().isIgnored(@relativize(path))
|
||||
|
||||
# Public: Identifies if a value represents a status code.
|
||||
# Identifies if a value represents a status code.
|
||||
#
|
||||
# status - The code {Number} to check
|
||||
#
|
||||
@@ -139,7 +135,7 @@ class Git
|
||||
isStatusModified: (status) ->
|
||||
@getRepo().isStatusModified(status)
|
||||
|
||||
# Public: Identifies if a path was modified.
|
||||
# Identifies if a path was modified.
|
||||
#
|
||||
# path - The {String} path to check
|
||||
#
|
||||
@@ -147,7 +143,7 @@ class Git
|
||||
isPathModified: (path) ->
|
||||
@isStatusModified(@getPathStatus(path))
|
||||
|
||||
# Public: Identifies if a status code represents a new path.
|
||||
# Identifies if a status code represents a new path.
|
||||
#
|
||||
# status - The code {Number} to check
|
||||
#
|
||||
@@ -155,7 +151,7 @@ class Git
|
||||
isStatusNew: (status) ->
|
||||
@getRepo().isStatusNew(status)
|
||||
|
||||
# Public: Identifies if a path is new.
|
||||
# Identifies if a path is new.
|
||||
#
|
||||
# path - The {String} path to check
|
||||
#
|
||||
@@ -163,7 +159,7 @@ class Git
|
||||
isPathNew: (path) ->
|
||||
@isStatusNew(@getPathStatus(path))
|
||||
|
||||
# Public: Makes a path relative to the repository's working directory.
|
||||
# Makes a path relative to the repository's working directory.
|
||||
#
|
||||
# path - The {String} path to convert
|
||||
#
|
||||
@@ -171,7 +167,7 @@ class Git
|
||||
relativize: (path) ->
|
||||
@getRepo().relativize(path)
|
||||
|
||||
# Public: Retrieves a shortened version of {.getHead}.
|
||||
# Retrieves a shortened version of {.getHead}.
|
||||
#
|
||||
# This removes the leading segments of `refs/heads`, `refs/tags`, or `refs/remotes`.
|
||||
# It also shortenes the SHA-1 of a detached `HEAD` to 7 characters.
|
||||
@@ -180,7 +176,7 @@ class Git
|
||||
getShortHead: ->
|
||||
@getRepo().getShortHead()
|
||||
|
||||
# Public: Restore the contents of a path in the working directory and index to the version at `HEAD`.
|
||||
# Restore the contents of a path in the working directory and index to the version at `HEAD`.
|
||||
#
|
||||
# This is essentially the same as running:
|
||||
# ```
|
||||
@@ -196,7 +192,7 @@ class Git
|
||||
@getPathStatus(path) if headCheckedOut
|
||||
headCheckedOut
|
||||
|
||||
# Public: Retrieves the number of lines added and removed to a path.
|
||||
# Retrieves the number of lines added and removed to a path.
|
||||
#
|
||||
# This compares the working directory contents of the path to the `HEAD` version.
|
||||
#
|
||||
@@ -206,7 +202,7 @@ class Git
|
||||
getDiffStats: (path) ->
|
||||
@getRepo().getDiffStats(@relativize(path))
|
||||
|
||||
# Public: Identifies if a path is a submodule.
|
||||
# Identifies if a path is a submodule.
|
||||
#
|
||||
# path - The {String} path to check
|
||||
#
|
||||
@@ -214,7 +210,7 @@ class Git
|
||||
isSubmodule: (path) ->
|
||||
@getRepo().isSubmodule(@relativize(path))
|
||||
|
||||
# Public: Retrieves the status of a directory.
|
||||
# Retrieves the status of a directory.
|
||||
#
|
||||
# path - The {String} path to check
|
||||
#
|
||||
@@ -226,7 +222,7 @@ class Git
|
||||
directoryStatus |= status if path.indexOf(directoryPath) is 0
|
||||
directoryStatus
|
||||
|
||||
# Public: Retrieves the number of commits the `HEAD` branch is ahead/behind the remote branch it is tracking.
|
||||
# Retrieves the number of commits the `HEAD` branch is ahead/behind the remote branch it is tracking.
|
||||
#
|
||||
# This is similar to the commit numbers reported by `git status` when a remote tracking branch exists.
|
||||
#
|
||||
@@ -234,7 +230,7 @@ class Git
|
||||
getAheadBehindCounts: ->
|
||||
@getRepo().getAheadBehindCount()
|
||||
|
||||
# Public: Retrieves the line diffs comparing the `HEAD` version of the given path and the given text.
|
||||
# Retrieves the line diffs comparing the `HEAD` version of the given path and the given text.
|
||||
#
|
||||
# This is similar to the commit numbers reported by `git status` when a remote tracking branch exists.
|
||||
#
|
||||
@@ -245,9 +241,7 @@ class Git
|
||||
getLineDiffs: (path, text) ->
|
||||
@getRepo().getLineDiffs(@relativize(path), text)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
refreshStatus: ->
|
||||
if @statusTask?
|
||||
|
||||
@@ -9,9 +9,7 @@ _ = require 'underscore'
|
||||
module.exports =
|
||||
class Gutter extends View
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
@content: ->
|
||||
@div class: 'gutter', =>
|
||||
@@ -50,25 +48,21 @@ class Gutter extends View
|
||||
$(document).on "mousemove.gutter-#{@getEditor().id}", moveHandler
|
||||
$(document).one "mouseup.gutter-#{@getEditor().id}", => $(document).off 'mousemove', moveHandler
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Retrieves the containing {Editor}.
|
||||
# Retrieves the containing {Editor}.
|
||||
#
|
||||
# Returns an {Editor}.
|
||||
getEditor: ->
|
||||
@parentView
|
||||
|
||||
# Public: Defines whether to show the gutter or not.
|
||||
# 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 #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
updateLineNumbers: (changes, renderFrom, renderTo) ->
|
||||
if renderFrom < @firstScreenRow or renderTo > @lastScreenRow
|
||||
@@ -82,7 +76,7 @@ class Gutter extends View
|
||||
break
|
||||
|
||||
@renderLineNumbers(renderFrom, renderTo) if performUpdate
|
||||
|
||||
|
||||
renderLineNumbers: (startScreenRow, endScreenRow) ->
|
||||
editor = @getEditor()
|
||||
maxDigits = editor.getLineCount().toString().length
|
||||
|
||||
@@ -8,23 +8,8 @@ module.exports=
|
||||
class ImageEditSession
|
||||
registerDeserializer(this)
|
||||
|
||||
# Public: Identifies if a path can be opened by the image viewer.
|
||||
#
|
||||
# path - The {String} name of the path to check
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
@canOpen: (path) ->
|
||||
_.indexOf([
|
||||
'.gif'
|
||||
'.jpeg'
|
||||
'.jpg'
|
||||
'.png'
|
||||
], fsUtils.extension(path), true) >= 0
|
||||
### Internal ###
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
@deserialize: (state) ->
|
||||
if fsUtils.exists(state.path)
|
||||
project.buildEditSession(state.path)
|
||||
@@ -40,10 +25,25 @@ class ImageEditSession
|
||||
getViewClass: ->
|
||||
require 'image-view'
|
||||
|
||||
# Public: Retrieves the filename of the open file.
|
||||
### Public ###
|
||||
|
||||
# Identifies if a path can be opened by the image viewer.
|
||||
#
|
||||
# path - The {String} name of the path to check
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
@canOpen: (path) ->
|
||||
_.indexOf([
|
||||
'.gif'
|
||||
'.jpeg'
|
||||
'.jpg'
|
||||
'.png'
|
||||
], fsUtils.extension(path), true) >= 0
|
||||
|
||||
# Retrieves the filename of the open file.
|
||||
#
|
||||
# This is `'untitled'` if the file is new and not saved to the disk.
|
||||
#
|
||||
#
|
||||
# Returns a {String}.
|
||||
getTitle: ->
|
||||
if path = @getPath()
|
||||
@@ -51,17 +51,17 @@ class ImageEditSession
|
||||
else
|
||||
'untitled'
|
||||
|
||||
# Public: Retrieves the URI of the current image.
|
||||
# Retrieves the URI of the current image.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getUri: -> @path
|
||||
|
||||
# Public: Retrieves the path of the current image.
|
||||
# Retrieves the path of the current image.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: -> @path
|
||||
|
||||
# Public: Compares two `ImageEditSession`s to determine equality.
|
||||
# Compares two `ImageEditSession`s to determine equality.
|
||||
#
|
||||
# Equality is based on the condition that the two URIs are the same.
|
||||
#
|
||||
|
||||
@@ -6,12 +6,12 @@ $ = require 'jquery'
|
||||
module.exports =
|
||||
class ImageView extends ScrollView
|
||||
|
||||
# Internal:
|
||||
### Internal ###
|
||||
|
||||
@content: ->
|
||||
@div class: 'image-view', tabindex: -1, =>
|
||||
@img outlet: 'image'
|
||||
|
||||
# Internal:
|
||||
initialize: (imageEditSession) ->
|
||||
super
|
||||
|
||||
@@ -29,7 +29,6 @@ class ImageView extends ScrollView
|
||||
@command 'image-view:zoom-out', => @zoomOut()
|
||||
@command 'image-view:reset-zoom', => @resetZoom()
|
||||
|
||||
# Internal:
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
|
||||
@@ -40,7 +39,9 @@ class ImageView extends ScrollView
|
||||
@active = @is(pane.activeView)
|
||||
@centerImage() if @active and not wasActive
|
||||
|
||||
# Public: Places the image in the center of the {Editor}.
|
||||
### Public ###
|
||||
|
||||
# Places the image in the center of the {Editor}.
|
||||
centerImage: ->
|
||||
return unless @loaded and @isVisible()
|
||||
|
||||
@@ -49,7 +50,7 @@ class ImageView extends ScrollView
|
||||
'left': Math.max((@width() - @image.outerWidth()) / 2, 0)
|
||||
@image.show()
|
||||
|
||||
# Public: Indicates the path of the image.
|
||||
# Indicates the path of the image.
|
||||
#
|
||||
# path - A {String} for the new image path.
|
||||
setPath: (path) ->
|
||||
@@ -60,25 +61,25 @@ class ImageView extends ScrollView
|
||||
else
|
||||
@image.hide()
|
||||
|
||||
# Public: Retrieve's the {Editor}'s pane.
|
||||
# Retrieve's the {Editor}'s pane.
|
||||
#
|
||||
# Returns a {Pane}.
|
||||
getPane: ->
|
||||
@parent('.item-views').parent('.pane').view()
|
||||
|
||||
# Public: Zooms the image out.
|
||||
# Zooms the image out.
|
||||
#
|
||||
# This is done by a factor of `0.9`.
|
||||
zoomOut: ->
|
||||
@adjustSize(0.9)
|
||||
|
||||
# Public: Zooms the image in.
|
||||
# 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.
|
||||
# Zooms the image to its normal width and height.
|
||||
resetZoom: ->
|
||||
return unless @loaded and @isVisible()
|
||||
|
||||
@@ -86,9 +87,7 @@ class ImageView extends ScrollView
|
||||
@image.height(@originalHeight)
|
||||
@centerImage()
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
adjustSize: (factor) ->
|
||||
return unless @loaded and @isVisible()
|
||||
@@ -100,4 +99,4 @@ class ImageView extends ScrollView
|
||||
@centerImage()
|
||||
|
||||
setModel: (imageEditSession) ->
|
||||
@setPath(imageEditSession?.getPath())
|
||||
@setPath(imageEditSession?.getPath())
|
||||
|
||||
@@ -5,9 +5,7 @@ require 'underscore-extensions'
|
||||
EventEmitter = require 'event-emitter'
|
||||
Subscriber = require 'subscriber'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class LanguageMode
|
||||
@@ -16,18 +14,20 @@ class LanguageMode
|
||||
editSession: null
|
||||
currentGrammarScore: null
|
||||
|
||||
# Public: Sets up a `LanguageMode` for the given {EditSession}.
|
||||
### Internal ###
|
||||
|
||||
destroy: ->
|
||||
@unsubscribe()
|
||||
|
||||
### Public ###
|
||||
|
||||
# Sets up a `LanguageMode` for the given {EditSession}.
|
||||
#
|
||||
# editSession - The {EditSession} to associate with
|
||||
constructor: (@editSession) ->
|
||||
@buffer = @editSession.buffer
|
||||
|
||||
# Internal:
|
||||
destroy: ->
|
||||
@unsubscribe()
|
||||
|
||||
|
||||
# Public: Wraps the lines between two rows in comments.
|
||||
# Wraps the lines between two rows in comments.
|
||||
#
|
||||
# If the language doesn't have comment, nothing happens.
|
||||
#
|
||||
@@ -74,7 +74,7 @@ class LanguageMode
|
||||
for row in [start..end]
|
||||
buffer.insert([row, 0], commentStartString)
|
||||
|
||||
# Public: Folds all the foldable lines in the buffer.
|
||||
# Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
for currentRow in [0..@buffer.getLastRow()]
|
||||
[startRow, endRow] = @rowRangeForFoldAtBufferRow(currentRow) ? []
|
||||
@@ -82,11 +82,16 @@ class LanguageMode
|
||||
|
||||
@editSession.createFold(startRow, endRow)
|
||||
|
||||
# Public: Unfolds all the foldable lines in the buffer.
|
||||
# Unfolds all the foldable lines in the buffer.
|
||||
unfoldAll: ->
|
||||
for row in [@buffer.getLastRow()..0]
|
||||
fold.destroy() for fold in @editSession.displayBuffer.foldsStartingAtBufferRow(row)
|
||||
|
||||
# Given a buffer row, creates a fold at it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
#
|
||||
# Returns the new {Fold}.
|
||||
foldBufferRow: (bufferRow) ->
|
||||
for currentRow in [bufferRow..0]
|
||||
rowRange = @rowRangeForCommentAtBufferRow(currentRow)
|
||||
@@ -96,7 +101,7 @@ class LanguageMode
|
||||
fold = @editSession.displayBuffer.largestFoldStartingAtBufferRow(startRow)
|
||||
return @editSession.createFold(startRow, endRow) unless fold
|
||||
|
||||
# Public: Given a buffer row, this unfolds it.
|
||||
# Given a buffer row, this unfolds it.
|
||||
#
|
||||
# bufferRow - A {Number} indicating the buffer row
|
||||
unfoldBufferRow: (bufferRow) ->
|
||||
@@ -140,7 +145,7 @@ class LanguageMode
|
||||
endRow = currentRow
|
||||
return [startRow, endRow] if startRow isnt endRow
|
||||
|
||||
# Public: Given a buffer row, this returns a suggested indentation level.
|
||||
# Given a buffer row, this returns a suggested indentation level.
|
||||
#
|
||||
# The indentation level provided is based on the current {LanguageMode}.
|
||||
#
|
||||
@@ -166,21 +171,21 @@ class LanguageMode
|
||||
|
||||
Math.max(desiredIndentLevel, currentIndentLevel)
|
||||
|
||||
# Public: Indents all the rows between two buffer row numbers.
|
||||
# Indents all the rows between two buffer row numbers.
|
||||
#
|
||||
# startRow - The row {Number} to start at
|
||||
# endRow - The row {Number} to end at
|
||||
autoIndentBufferRows: (startRow, endRow) ->
|
||||
@autoIndentBufferRow(row) for row in [startRow..endRow]
|
||||
|
||||
# Public: Given a buffer row, this indents it.
|
||||
# Given a buffer row, this indents it.
|
||||
#
|
||||
# bufferRow - The row {Number}
|
||||
autoIndentBufferRow: (bufferRow) ->
|
||||
@autoIncreaseIndentForBufferRow(bufferRow)
|
||||
@autoDecreaseIndentForBufferRow(bufferRow)
|
||||
|
||||
# Public: Given a buffer row, this increases the indentation.
|
||||
# Given a buffer row, this increases the indentation.
|
||||
#
|
||||
# bufferRow - The row {Number}
|
||||
autoIncreaseIndentForBufferRow: (bufferRow) ->
|
||||
@@ -198,7 +203,7 @@ class LanguageMode
|
||||
if desiredIndentLevel > currentIndentLevel
|
||||
@editSession.setIndentationForBufferRow(bufferRow, desiredIndentLevel)
|
||||
|
||||
# Public: Given a buffer row, this decreases the indentation.
|
||||
# Given a buffer row, this decreases the indentation.
|
||||
#
|
||||
# bufferRow - The row {Number}
|
||||
autoDecreaseIndentForBufferRow: (bufferRow) ->
|
||||
|
||||
@@ -28,7 +28,9 @@ class LineMap
|
||||
for screenLine in maxLengthCandidates
|
||||
@maxScreenLineLength = Math.max(@maxScreenLineLength, screenLine.text.length)
|
||||
|
||||
# Public: Gets the line for the given screen row.
|
||||
### Public ###
|
||||
|
||||
# Gets the line for the given screen row.
|
||||
#
|
||||
# screenRow - A {Number} indicating the screen row.
|
||||
#
|
||||
@@ -36,7 +38,7 @@ class LineMap
|
||||
lineForScreenRow: (row) ->
|
||||
@screenLines[row]
|
||||
|
||||
# Public: Gets the lines for the given screen row boundaries.
|
||||
# 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.
|
||||
@@ -45,7 +47,7 @@ class LineMap
|
||||
linesForScreenRows: (startRow, endRow) ->
|
||||
@screenLines[startRow..endRow]
|
||||
|
||||
# Public: Given starting and ending screen rows, this returns an array of the
|
||||
# Given starting and ending screen rows, this returns an array of the
|
||||
# buffer rows corresponding to every screen row in the range
|
||||
#
|
||||
# startRow - The screen row {Number} to start at
|
||||
@@ -100,7 +102,7 @@ class LineMap
|
||||
column = screenLine.clipScreenColumn(column, options)
|
||||
new Point(row, column)
|
||||
|
||||
# Public: Given a buffer position, this converts it into a screen position.
|
||||
# Given a buffer position, this converts it into a screen position.
|
||||
#
|
||||
# bufferPosition - An object that represents a buffer position. It can be either
|
||||
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
|
||||
@@ -140,7 +142,7 @@ class LineMap
|
||||
|
||||
[screenRow, screenLines]
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen position.
|
||||
# Given a buffer range, this converts it into a screen position.
|
||||
#
|
||||
# screenPosition - An object that represents a buffer position. It can be either
|
||||
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point}
|
||||
@@ -163,7 +165,7 @@ class LineMap
|
||||
|
||||
[bufferRow, screenLine]
|
||||
|
||||
# Public: Given a buffer range, this converts it into a screen position.
|
||||
# Given a buffer range, this converts it into a screen position.
|
||||
#
|
||||
# bufferRange - The {Range} to convert
|
||||
#
|
||||
@@ -174,7 +176,7 @@ class LineMap
|
||||
end = @screenPositionForBufferPosition(bufferRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
# Public: Given a screen range, this converts it into a buffer position.
|
||||
# Given a screen range, this converts it into a buffer position.
|
||||
#
|
||||
# screenRange - The {Range} to convert
|
||||
#
|
||||
@@ -185,7 +187,8 @@ class LineMap
|
||||
end = @bufferPositionForScreenPosition(screenRange.end)
|
||||
new Range(start, end)
|
||||
|
||||
# Internal:
|
||||
### Internal ###
|
||||
|
||||
logLines: (start=0, end=@getScreenLineCount() - 1)->
|
||||
for row in [start..end]
|
||||
line = @lineForScreenRow(row).text
|
||||
|
||||
@@ -2,9 +2,7 @@ Token = require 'token'
|
||||
EventEmitter = require 'event-emitter'
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
module.exports =
|
||||
class NullGrammar
|
||||
name: 'Null Grammar'
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
module.exports =
|
||||
class Package
|
||||
@build: (path) ->
|
||||
|
||||
@@ -6,9 +6,7 @@ module.exports =
|
||||
class PaneContainer extends View
|
||||
registerDeserializer(this)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
@deserialize: ({root}) ->
|
||||
container = new PaneContainer
|
||||
@@ -26,9 +24,7 @@ class PaneContainer extends View
|
||||
deserializer: 'PaneContainer'
|
||||
root: @getRoot()?.serialize()
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
focusNextPane: ->
|
||||
panes = @getPanes()
|
||||
|
||||
@@ -2,9 +2,7 @@ $ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
PaneAxis = require 'pane-axis'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class PaneRow extends PaneAxis
|
||||
|
||||
@@ -7,9 +7,7 @@ PaneColumn = require 'pane-column'
|
||||
module.exports =
|
||||
class Pane extends View
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
@content: (wrappedView) ->
|
||||
@div class: 'pane', =>
|
||||
@@ -65,9 +63,7 @@ class Pane extends View
|
||||
@attached = true
|
||||
@trigger 'pane:attached', [this]
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
makeActive: ->
|
||||
for pane in @getContainer().getPanes() when pane isnt this
|
||||
@@ -186,7 +182,7 @@ class Pane extends View
|
||||
|
||||
saveItem: (item, nextAction) ->
|
||||
if item.getUri?()
|
||||
item.save()
|
||||
item.save?()
|
||||
nextAction?()
|
||||
else
|
||||
@saveItemAs(item, nextAction)
|
||||
|
||||
@@ -5,7 +5,7 @@ module.exports =
|
||||
class Pasteboard
|
||||
signatureForMetadata: null
|
||||
|
||||
# Internal: Creates an `md5` hash of some text.
|
||||
# Creates an `md5` hash of some text.
|
||||
#
|
||||
# text - A {String} to encrypt.
|
||||
#
|
||||
|
||||
@@ -6,7 +6,7 @@ _ = require 'underscore'
|
||||
module.exports =
|
||||
class Point
|
||||
|
||||
# Public: Constructs a `Point` from a given object.
|
||||
# Constructs a `Point` from a given object.
|
||||
#
|
||||
# object - This can be an {Array} (`[startRow, startColumn, endRow, endColumn]`) or an object `{row, column}`
|
||||
#
|
||||
@@ -22,7 +22,7 @@ class Point
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
# Public: Identifies which `Point` is smaller.
|
||||
# Identifies which `Point` is smaller.
|
||||
#
|
||||
# "Smaller" means that both the `row` and `column` values of one `Point` are less than or equal
|
||||
# to the other.
|
||||
@@ -39,7 +39,7 @@ class Point
|
||||
else
|
||||
point2
|
||||
|
||||
# Public: Creates a new `Point` object.
|
||||
# Creates a new `Point` object.
|
||||
#
|
||||
# row - A {Number} indicating the row (default: 0)
|
||||
# column - A {Number} indicating the column (default: 0)
|
||||
@@ -47,13 +47,13 @@ class Point
|
||||
# Returns a {Point},
|
||||
constructor: (@row=0, @column=0) ->
|
||||
|
||||
# Public: Creates an identical copy of the `Point`.
|
||||
# Creates an identical copy of the `Point`.
|
||||
#
|
||||
# Returns a duplicate {Point}.
|
||||
copy: ->
|
||||
new Point(@row, @column)
|
||||
|
||||
# Public: Adds the `column`s of two `Point`s together.
|
||||
# Adds the `column`s of two `Point`s together.
|
||||
#
|
||||
# other - The {Point} to add with
|
||||
#
|
||||
@@ -68,7 +68,7 @@ class Point
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
# Public: Moves a `Point`.
|
||||
# Moves a `Point`.
|
||||
#
|
||||
# In other words, the `row` values and `column` values are added to each other.
|
||||
#
|
||||
@@ -79,7 +79,7 @@ class Point
|
||||
other = Point.fromObject(other)
|
||||
new Point(@row + other.row, @column + other.column)
|
||||
|
||||
# Public: Creates two new `Point`s, split down a `column` value.
|
||||
# Creates two new `Point`s, split down a `column` value.
|
||||
#
|
||||
# In other words, given a point, this creates `Point(0, column)` and `Point(row, column)`.
|
||||
#
|
||||
@@ -94,7 +94,7 @@ class Point
|
||||
|
||||
[new Point(0, column), new Point(@row, rightColumn)]
|
||||
|
||||
# Internal: Compares two `Point`s.
|
||||
# Compares two `Point`s.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -103,7 +103,7 @@ class Point
|
||||
# * If the first `row` is less than `other.row`, returns `-1`.
|
||||
# * If the first `column` is greater than `other.column`, returns `1`.
|
||||
# * If the first `column` is less than `other.column`, returns `-1`.
|
||||
#
|
||||
#
|
||||
# Otherwise, returns `0`.
|
||||
compare: (other) ->
|
||||
if @row > other.row
|
||||
@@ -118,7 +118,7 @@ class Point
|
||||
else
|
||||
0
|
||||
|
||||
# Public: Identifies if two `Point`s are equal.
|
||||
# Identifies if two `Point`s are equal.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -128,7 +128,7 @@ class Point
|
||||
other = Point.fromObject(other)
|
||||
@row == other.row and @column == other.column
|
||||
|
||||
# Public: Identifies if one `Point` is less than another.
|
||||
# Identifies if one `Point` is less than another.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -136,7 +136,7 @@ class Point
|
||||
isLessThan: (other) ->
|
||||
@compare(other) < 0
|
||||
|
||||
# Public: Identifies if one `Point` is less than or equal to another.
|
||||
# Identifies if one `Point` is less than or equal to another.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -144,7 +144,7 @@ class Point
|
||||
isLessThanOrEqual: (other) ->
|
||||
@compare(other) <= 0
|
||||
|
||||
# Public: Identifies if one `Point` is greater than another.
|
||||
# Identifies if one `Point` is greater than another.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -152,7 +152,7 @@ class Point
|
||||
isGreaterThan: (other) ->
|
||||
@compare(other) > 0
|
||||
|
||||
# Public: Identifies if one `Point` is greater than or equal to another.
|
||||
# Identifies if one `Point` is greater than or equal to another.
|
||||
#
|
||||
# other - The {Point} to compare against
|
||||
#
|
||||
@@ -160,25 +160,23 @@ class Point
|
||||
isGreaterThanOrEqual: (other) ->
|
||||
@compare(other) >= 0
|
||||
|
||||
# Public: Converts the {Point} to a String.
|
||||
# Converts the {Point} to a String.
|
||||
#
|
||||
# Returns a {String}.
|
||||
toString: ->
|
||||
"#{@row},#{@column}"
|
||||
|
||||
# Public: Converts the {Point} to an Array.
|
||||
# Converts the {Point} to an Array.
|
||||
#
|
||||
# Returns an {Array}.
|
||||
toArray: ->
|
||||
[@row, @column]
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
|
||||
### Internal ###
|
||||
|
||||
inspect: ->
|
||||
"(#{@row}, #{@column})"
|
||||
|
||||
|
||||
# Internal:
|
||||
serialize: ->
|
||||
@toArray()
|
||||
|
||||
@@ -24,17 +24,7 @@ class Project
|
||||
editSessions: null
|
||||
ignoredPathRegexes: null
|
||||
|
||||
# Public: Establishes a new project at a given path.
|
||||
#
|
||||
# path - The {String} name of the path
|
||||
constructor: (path) ->
|
||||
@setPath(path)
|
||||
@editSessions = []
|
||||
@buffers = []
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
serialize: ->
|
||||
deserializer: 'Project'
|
||||
@@ -46,17 +36,23 @@ class Project
|
||||
destroy: ->
|
||||
editSession.destroy() for editSession in @getEditSessions()
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Retrieves the project path.
|
||||
# Establishes a new project at a given path.
|
||||
#
|
||||
# path - The {String} name of the path
|
||||
constructor: (path) ->
|
||||
@setPath(path)
|
||||
@editSessions = []
|
||||
@buffers = []
|
||||
|
||||
# Retrieves the project path.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getPath: ->
|
||||
@rootDirectory?.path
|
||||
|
||||
# Public: Sets the project path.
|
||||
# Sets the project path.
|
||||
#
|
||||
# path - A {String} representing the new path
|
||||
setPath: (path) ->
|
||||
@@ -70,13 +66,13 @@ class Project
|
||||
|
||||
@trigger "path-changed"
|
||||
|
||||
# Public: Retrieves the name of the root directory.
|
||||
# Retrieves the name of the root directory.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getRootDirectory: ->
|
||||
@rootDirectory
|
||||
|
||||
# Public: Retrieves the names of every file (that's not `git ignore`d) in the project.
|
||||
# Retrieves the names of every file (that's not `git ignore`d) in the project.
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
getFilePaths: ->
|
||||
@@ -88,7 +84,7 @@ class Project
|
||||
deferred.resolve(paths)
|
||||
deferred.promise()
|
||||
|
||||
# Public: Identifies if a path is ignored.
|
||||
# Identifies if a path is ignored.
|
||||
#
|
||||
# path - The {String} name of the path to check
|
||||
#
|
||||
@@ -100,7 +96,7 @@ class Project
|
||||
|
||||
@ignoreRepositoryPath(path)
|
||||
|
||||
# Public: Identifies if a path is ignored.
|
||||
# Identifies if a path is ignored.
|
||||
#
|
||||
# path - The {String} name of the path to check
|
||||
#
|
||||
@@ -108,7 +104,7 @@ class Project
|
||||
ignoreRepositoryPath: (path) ->
|
||||
config.get("core.hideGitIgnoredFiles") and git?.isPathIgnored(fsUtils.join(@getPath(), path))
|
||||
|
||||
# Public: Given a path, this resolves it relative to the project directory.
|
||||
# Given a path, this resolves it relative to the project directory.
|
||||
#
|
||||
# filePath - The {String} name of the path to convert
|
||||
#
|
||||
@@ -117,7 +113,7 @@ class Project
|
||||
filePath = fsUtils.join(@getPath(), filePath) unless filePath[0] == '/'
|
||||
fsUtils.absolute filePath
|
||||
|
||||
# Public: Given a path, this makes it relative to the project directory.
|
||||
# Given a path, this makes it relative to the project directory.
|
||||
#
|
||||
# filePath - The {String} name of the path to convert
|
||||
#
|
||||
@@ -126,27 +122,27 @@ class Project
|
||||
return fullPath unless fullPath.lastIndexOf(@getPath()) is 0
|
||||
fullPath.replace(@getPath(), "").replace(/^\//, '')
|
||||
|
||||
# Public: Identifies if the project is using soft tabs.
|
||||
# Identifies if the project is using soft tabs.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
getSoftTabs: -> @softTabs
|
||||
|
||||
# Public: Sets the project to use soft tabs.
|
||||
# Sets the project to use soft tabs.
|
||||
#
|
||||
# softTabs - A {Boolean} which, if `true`, sets soft tabs
|
||||
setSoftTabs: (@softTabs) ->
|
||||
|
||||
# Public: Identifies if the project is using soft wrapping.
|
||||
# Identifies if the project is using soft wrapping.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
getSoftWrap: -> @softWrap
|
||||
|
||||
# Public: Sets the project to use soft wrapping.
|
||||
# Sets the project to use soft wrapping.
|
||||
#
|
||||
# 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`, showing the file.
|
||||
# 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
|
||||
@@ -158,55 +154,21 @@ class Project
|
||||
else
|
||||
@buildEditSessionForBuffer(@bufferForPath(filePath), editSessionOptions)
|
||||
|
||||
# Public: Retrieves all the {EditSession}s in the project; that is, the `EditSession`s for all open files.
|
||||
# Retrieves all the {EditSession}s in the project; that is, the `EditSession`s for all open files.
|
||||
#
|
||||
# Returns an {Array} of {EditSession}s.
|
||||
getEditSessions: ->
|
||||
new Array(@editSessions...)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
buildEditSessionForBuffer: (buffer, editSessionOptions) ->
|
||||
options = _.extend(@defaultEditSessionOptions(), editSessionOptions)
|
||||
options.project = this
|
||||
options.buffer = buffer
|
||||
editSession = new EditSession(options)
|
||||
@editSessions.push editSession
|
||||
@trigger 'edit-session-created', editSession
|
||||
editSession
|
||||
|
||||
defaultEditSessionOptions: ->
|
||||
tabLength: @tabLength
|
||||
softTabs: @getSoftTabs()
|
||||
softWrap: @getSoftWrap()
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
callback(editSession) for editSession in @getEditSessions()
|
||||
@on 'edit-session-created', (editSession) -> callback(editSession)
|
||||
|
||||
eachBuffer: (args...) ->
|
||||
subscriber = args.shift() if args.length > 1
|
||||
callback = args.shift()
|
||||
|
||||
callback(buffer) for buffer in @getBuffers()
|
||||
if subscriber
|
||||
subscriber.subscribe this, 'buffer-created', (buffer) -> callback(buffer)
|
||||
else
|
||||
@on 'buffer-created', (buffer) -> callback(buffer)
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
|
||||
# Public: Removes an {EditSession} association from the project.
|
||||
# Removes an {EditSession} association from the project.
|
||||
#
|
||||
# Returns the removed {EditSession}.
|
||||
removeEditSession: (editSession) ->
|
||||
_.remove(@editSessions, editSession)
|
||||
|
||||
# Public: Retrieves all the {Buffer}s in the project; that is, the buffers for all open files.
|
||||
|
||||
# Retrieves all the {Buffer}s in the project; that is, the buffers for all open files.
|
||||
#
|
||||
# Returns an {Array} of {Buffer}s.
|
||||
getBuffers: ->
|
||||
@@ -215,7 +177,7 @@ class Project
|
||||
buffers.push editSession.buffer
|
||||
buffers
|
||||
|
||||
# Public: Given a file path, this retrieves or creates a new {Buffer}.
|
||||
# Given a file path, this retrieves or creates a new {Buffer}.
|
||||
#
|
||||
# If the `filePath` already has a `buffer`, that value is used instead. Otherwise,
|
||||
# `text` is used as the contents of the new buffer.
|
||||
@@ -233,7 +195,7 @@ class Project
|
||||
else
|
||||
@buildBuffer(null, text)
|
||||
|
||||
# Public: Given a file path, this sets its {Buffer}.
|
||||
# Given a file path, this sets its {Buffer}.
|
||||
#
|
||||
# filePath - A {String} representing a path
|
||||
# text - The {String} text to use as a buffer
|
||||
@@ -245,13 +207,13 @@ class Project
|
||||
@trigger 'buffer-created', buffer
|
||||
buffer
|
||||
|
||||
# Public: Removes a {Buffer} association from the project.
|
||||
# Removes a {Buffer} association from the project.
|
||||
#
|
||||
# Returns the removed {Buffer}.
|
||||
removeBuffer: (buffer) ->
|
||||
_.remove(@buffers, buffer)
|
||||
|
||||
# Public: Performs a search across all the files in the project.
|
||||
# Performs a search across all the files in the project.
|
||||
#
|
||||
# regex - A {RegExp} to search with
|
||||
# iterator - A {Function} callback on each file found
|
||||
@@ -307,4 +269,34 @@ class Project
|
||||
new BufferedProcess({command, args, stdout, exit})
|
||||
deferred
|
||||
|
||||
### Internal ###
|
||||
|
||||
buildEditSessionForBuffer: (buffer, editSessionOptions) ->
|
||||
options = _.extend(@defaultEditSessionOptions(), editSessionOptions)
|
||||
options.project = this
|
||||
options.buffer = buffer
|
||||
editSession = new EditSession(options)
|
||||
@editSessions.push editSession
|
||||
@trigger 'edit-session-created', editSession
|
||||
editSession
|
||||
|
||||
defaultEditSessionOptions: ->
|
||||
tabLength: @tabLength
|
||||
softTabs: @getSoftTabs()
|
||||
softWrap: @getSoftWrap()
|
||||
|
||||
eachEditSession: (callback) ->
|
||||
callback(editSession) for editSession in @getEditSessions()
|
||||
@on 'edit-session-created', (editSession) -> callback(editSession)
|
||||
|
||||
eachBuffer: (args...) ->
|
||||
subscriber = args.shift() if args.length > 1
|
||||
callback = args.shift()
|
||||
|
||||
callback(buffer) for buffer in @getBuffers()
|
||||
if subscriber
|
||||
subscriber.subscribe this, 'buffer-created', (buffer) -> callback(buffer)
|
||||
else
|
||||
@on 'buffer-created', (buffer) -> callback(buffer)
|
||||
|
||||
_.extend Project.prototype, EventEmitter
|
||||
|
||||
@@ -11,7 +11,7 @@ _ = require 'underscore'
|
||||
module.exports =
|
||||
class Range
|
||||
|
||||
# Public: Constructs a `Range` from a given object.
|
||||
# Constructs a `Range` from a given object.
|
||||
#
|
||||
# object - This can be an {Array} (`[startRow, startColumn, endRow, endColumn]`) or an object `{start: Point, end: Point}`
|
||||
#
|
||||
@@ -24,7 +24,7 @@ class Range
|
||||
else
|
||||
new Range(object.start, object.end)
|
||||
|
||||
# Public: Constructs a `Range` from a {Point}, and the delta values beyond that point.
|
||||
# Constructs a `Range` from a {Point}, and the delta values beyond that point.
|
||||
#
|
||||
# point - A {Point} to start with
|
||||
# rowDelta - A {Number} indicating how far from the starting {Point} the range's row should be
|
||||
@@ -36,7 +36,7 @@ class Range
|
||||
pointB = new Point(point.row + rowDelta, point.column + columnDelta)
|
||||
new Range(pointA, pointB)
|
||||
|
||||
# Public: Creates a new `Range` object based on two {Point}s.
|
||||
# Creates a new `Range` object based on two {Point}s.
|
||||
#
|
||||
# pointA - The first {Point} (default: `0, 0`)
|
||||
# pointB - The second {Point} (default: `0, 0`)
|
||||
@@ -51,13 +51,13 @@ class Range
|
||||
@start = pointB
|
||||
@end = pointA
|
||||
|
||||
# Public: Creates an identical copy of the `Range`.
|
||||
# Creates an identical copy of the `Range`.
|
||||
#
|
||||
# Returns a duplicate {Range}.
|
||||
copy: ->
|
||||
new Range(@start.copy(), @end.copy())
|
||||
|
||||
# Public: Identifies if two `Range`s are equal.
|
||||
# Identifies if two `Range`s are equal.
|
||||
#
|
||||
# All four points (`start.row`, `start.column`, `end.row`, `end.column`) must be
|
||||
# equal for this method to return `true`.
|
||||
@@ -88,7 +88,7 @@ class Range
|
||||
else
|
||||
other.end.compare(@end)
|
||||
|
||||
# Public: Identifies if the `Range` is on the same line.
|
||||
# Identifies if the `Range` is on the same line.
|
||||
#
|
||||
# In other words, if `start.row` is equal to `end.row`.
|
||||
#
|
||||
@@ -96,7 +96,7 @@ class Range
|
||||
isSingleLine: ->
|
||||
@start.row == @end.row
|
||||
|
||||
# Public: Identifies if two `Range`s are on the same line.
|
||||
# Identifies if two `Range`s are on the same line.
|
||||
#
|
||||
# other - A different {Range} to check against
|
||||
#
|
||||
@@ -104,11 +104,7 @@ class Range
|
||||
coversSameRows: (other) ->
|
||||
@start.row == other.start.row && @end.row == other.end.row
|
||||
|
||||
# Internal:
|
||||
inspect: ->
|
||||
"[#{@start.inspect()} - #{@end.inspect()}]"
|
||||
|
||||
# Public: Adds a new point to the `Range`s `start` and `end`.
|
||||
# Adds a new point to the `Range`s `start` and `end`.
|
||||
#
|
||||
# point - A new {Point} to add
|
||||
#
|
||||
@@ -116,7 +112,7 @@ class Range
|
||||
add: (point) ->
|
||||
new Range(@start.add(point), @end.add(point))
|
||||
|
||||
# Public: Moves a `Range`.
|
||||
# Moves a `Range`.
|
||||
#
|
||||
# In other words, the starting and ending `row` values, and the starting and ending
|
||||
# `column` values, are added to each other.
|
||||
@@ -128,7 +124,7 @@ class Range
|
||||
translate: (startPoint, endPoint=startPoint) ->
|
||||
new Range(@start.translate(startPoint), @end.translate(endPoint))
|
||||
|
||||
# Public: Identifies if two `Range`s intersect each other.
|
||||
# Identifies if two `Range`s intersect each other.
|
||||
#
|
||||
# otherRange - A different {Range} to check against
|
||||
#
|
||||
@@ -139,22 +135,22 @@ class Range
|
||||
else
|
||||
otherRange.intersectsWith(this)
|
||||
|
||||
# Public: Identifies if a second `Range` is contained within a first.
|
||||
# Identifies if a second `Range` is contained within a first.
|
||||
#
|
||||
# otherRange - A different {Range} to check against
|
||||
# options - A hash with a single option:
|
||||
# :exclusive - A {Boolean} which, if `true`, indicates that no {Point}s in the `Range` can be equal
|
||||
# exclusive: A {Boolean} which, if `true`, indicates that no {Point}s in the `Range` can be equal
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
containsRange: (otherRange, {exclusive} = {}) ->
|
||||
{ start, end } = Range.fromObject(otherRange)
|
||||
@containsPoint(start, {exclusive}) and @containsPoint(end, {exclusive})
|
||||
|
||||
# Public: Identifies if a `Range` contains a {Point}.
|
||||
# Identifies if a `Range` contains a {Point}.
|
||||
#
|
||||
# point - A {Point} to check against
|
||||
# options - A hash with a single option:
|
||||
# :exclusive - A {Boolean} which, if `true`, indicates that no {Point}s in the `Range` can be equal
|
||||
# exclusive: A {Boolean} which, if `true`, indicates that no {Point}s in the `Range` can be equal
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
containsPoint: (point, {exclusive} = {}) ->
|
||||
@@ -164,7 +160,7 @@ class Range
|
||||
else
|
||||
point.isGreaterThanOrEqual(@start) and point.isLessThanOrEqual(@end)
|
||||
|
||||
# Public: Identifies if a `Range` contains a row.
|
||||
# Identifies if a `Range` contains a row.
|
||||
#
|
||||
# row - A row {Number} to check against
|
||||
# options - A hash with a single option:
|
||||
@@ -173,7 +169,7 @@ class Range
|
||||
containsRow: (row) ->
|
||||
@start.row <= row <= @end.row
|
||||
|
||||
# Public: Constructs a union between two `Range`s.
|
||||
# Constructs a union between two `Range`s.
|
||||
#
|
||||
# otherRange - A different {Range} to unionize with
|
||||
#
|
||||
@@ -183,7 +179,7 @@ class Range
|
||||
end = if @end.isGreaterThan(otherRange.end) then @end else otherRange.end
|
||||
new Range(start, end)
|
||||
|
||||
# Public: Identifies if a `Range` is empty.
|
||||
# Identifies if a `Range` is empty.
|
||||
#
|
||||
# A `Range` is empty if its start {Point} matches its end.
|
||||
#
|
||||
@@ -191,7 +187,7 @@ class Range
|
||||
isEmpty: ->
|
||||
@start.isEqual(@end)
|
||||
|
||||
# Public: Calculates the difference between a `Range`s `start` and `end` points.
|
||||
# Calculates the difference between a `Range`s `start` and `end` points.
|
||||
#
|
||||
# Returns a {Point}.
|
||||
toDelta: ->
|
||||
@@ -202,8 +198,13 @@ class Range
|
||||
columns = @end.column
|
||||
new Point(rows, columns)
|
||||
|
||||
# Public: Calculates the number of rows a `Range`s contains.
|
||||
# Calculates the number of rows a `Range`s contains.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getRowCount: ->
|
||||
@end.row - @start.row + 1
|
||||
|
||||
### Internal ###
|
||||
|
||||
inspect: ->
|
||||
"[#{@start.inspect()} - #{@end.inspect()}]"
|
||||
|
||||
@@ -25,9 +25,7 @@ class RootView extends View
|
||||
disabledPackages: []
|
||||
themes: ['atom-dark-ui', 'atom-dark-syntax']
|
||||
|
||||
###
|
||||
# Internal:
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
@content: ({panes}={}) ->
|
||||
@div id: 'root-view', =>
|
||||
@@ -98,15 +96,13 @@ class RootView extends View
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Shows a dialog asking if the pane was _really_ meant to be closed.
|
||||
# Shows a dialog asking if the pane was _really_ meant to be closed.
|
||||
confirmClose: ->
|
||||
@panes.confirmClose()
|
||||
|
||||
# Public: Given a filepath, this opens it in Atom.
|
||||
# Given a filepath, this opens it in Atom.
|
||||
#
|
||||
# Returns the `EditSession` for the file URI.
|
||||
open: (path, options = {}) ->
|
||||
@@ -123,7 +119,7 @@ class RootView extends View
|
||||
activePane.focus() if changeFocus
|
||||
editSession
|
||||
|
||||
# Public: Updates the application's title, based on whichever file is open.
|
||||
# Updates the application's title, based on whichever file is open.
|
||||
updateTitle: ->
|
||||
if projectPath = project.getPath()
|
||||
if item = @getActivePaneItem()
|
||||
@@ -133,19 +129,19 @@ class RootView extends View
|
||||
else
|
||||
@setTitle('untitled')
|
||||
|
||||
# Public: Sets the application's title.
|
||||
# Sets the application's title.
|
||||
#
|
||||
# Returns a {String}.
|
||||
setTitle: (title) ->
|
||||
document.title = title
|
||||
|
||||
# Public: Retrieves all of the application's {Editor}s.
|
||||
# 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.
|
||||
# Retrieves all of the modified buffers that are open and unsaved.
|
||||
#
|
||||
# Returns an {Array} of {Buffer}s.
|
||||
getModifiedBuffers: ->
|
||||
@@ -155,13 +151,13 @@ class RootView extends View
|
||||
modifiedBuffers.push item.buffer if item.buffer.isModified()
|
||||
modifiedBuffers
|
||||
|
||||
# Public: Retrieves all of the paths to open files.
|
||||
# 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.
|
||||
# Retrieves the pane that's currently open.
|
||||
#
|
||||
# Returns an {Pane}.
|
||||
getActivePane: ->
|
||||
@@ -177,29 +173,23 @@ 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.
|
||||
# Saves all of the open buffers.
|
||||
saveAll: ->
|
||||
@panes.saveAll()
|
||||
|
||||
# Public: Fires a callback on each open {Pane}.
|
||||
# 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.
|
||||
# Retrieves all of the open {Pane}s.
|
||||
#
|
||||
# Returns an {Array} of {Pane}.
|
||||
getPanes: ->
|
||||
@panes.getPanes()
|
||||
|
||||
# Public: Given a {Pane}, this fetches its ID.
|
||||
# Given a {Pane}, this fetches its ID.
|
||||
#
|
||||
# pane - An open {Pane}
|
||||
#
|
||||
@@ -207,21 +197,29 @@ class RootView extends View
|
||||
indexOfPane: (pane) ->
|
||||
@panes.indexOfPane(pane)
|
||||
|
||||
# Public: Fires a callback on each open {Editor}.
|
||||
# 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}.
|
||||
# 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}.
|
||||
# Fires a callback on each open {Buffer}.
|
||||
#
|
||||
# callback - A {Function} to call
|
||||
eachBuffer: (callback) ->
|
||||
project.eachBuffer(callback)
|
||||
|
||||
### Internal ###
|
||||
|
||||
# Destroys everything.
|
||||
remove: ->
|
||||
editor.remove() for editor in @getEditors()
|
||||
project.destroy()
|
||||
super
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class ScreenLine
|
||||
@@ -108,9 +106,6 @@ class ScreenLine
|
||||
breakOutLeadingWhitespace = token.isOnlyWhitespace() if breakOutLeadingWhitespace
|
||||
outputTokens
|
||||
|
||||
# Public: Determins if the current line is commented.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isComment: ->
|
||||
for token in @tokens
|
||||
continue if token.scopes.length is 1
|
||||
|
||||
@@ -6,9 +6,7 @@ fuzzyFilter = require 'fuzzy-filter'
|
||||
module.exports =
|
||||
class SelectList extends View
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
@content: ->
|
||||
@div class: @viewClass(), =>
|
||||
|
||||
@@ -2,10 +2,10 @@ Point = require 'point'
|
||||
Range = require 'range'
|
||||
{View, $$} = require 'space-pen'
|
||||
|
||||
# Internal:
|
||||
module.exports =
|
||||
class SelectionView extends View
|
||||
|
||||
# Internal: Establishes the DOM for the selection view.
|
||||
@content: ->
|
||||
@div class: 'selection'
|
||||
|
||||
|
||||
@@ -13,9 +13,7 @@ class Selection
|
||||
wordwise: false
|
||||
needsAutoscroll: null
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
constructor: ({@cursor, @marker, @editSession, @goalBufferRange}) ->
|
||||
@cursor.selection = this
|
||||
@@ -40,53 +38,53 @@ class Selection
|
||||
clearAutoscroll: ->
|
||||
@needsAutoscroll = null
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### Public ###
|
||||
|
||||
# Public: Identifies if the selection is highlighting anything.
|
||||
# Identifies if the selection is highlighting anything.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isEmpty: ->
|
||||
@getBufferRange().isEmpty()
|
||||
|
||||
# Public: Identifies if the selection is reversed, that is, it is highlighting "up."
|
||||
# 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}.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isReversed: ->
|
||||
@marker.isReversed()
|
||||
|
||||
# Public: Identifies if the selection is a single line.
|
||||
# Identifies if the selection is a single line.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isSingleScreenLine: ->
|
||||
@getScreenRange().isSingleLine()
|
||||
|
||||
# Public: Retrieves the screen range for the selection.
|
||||
# Retrieves the screen range for the selection.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getScreenRange: ->
|
||||
@marker.getScreenRange()
|
||||
|
||||
# Public: Modifies the screen range for the selection.
|
||||
# Modifies the screen range for the selection.
|
||||
#
|
||||
# screenRange - The new {Range} to use
|
||||
# options - A hash of options matching those found in {.setBufferRange}
|
||||
setScreenRange: (screenRange, options) ->
|
||||
@setBufferRange(@editSession.bufferRangeForScreenRange(screenRange), options)
|
||||
|
||||
# Public: Retrieves the buffer range for the selection.
|
||||
# Retrieves the buffer range for the selection.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
getBufferRange: ->
|
||||
@marker.getBufferRange()
|
||||
|
||||
# Public: Modifies the buffer range for the selection.
|
||||
# Modifies the buffer range for the selection.
|
||||
#
|
||||
# screenRange - The new {Range} to select
|
||||
# options - A hash of options with the following keys:
|
||||
# :preserveFolds - if `true`, the fold settings are preserved after the selection moves
|
||||
# :autoscroll - if `true`, the {EditSession} scrolls to the new selection
|
||||
# preserveFolds: if `true`, the fold settings are preserved after the selection moves
|
||||
# autoscroll: if `true`, the {EditSession} scrolls to the new selection
|
||||
setBufferRange: (bufferRange, options={}) ->
|
||||
bufferRange = Range.fromObject(bufferRange)
|
||||
@needsAutoscroll = options.autoscroll
|
||||
@@ -96,7 +94,7 @@ class Selection
|
||||
@cursor.needsAutoscroll = false if options.autoscroll?
|
||||
@marker.setBufferRange(bufferRange, options)
|
||||
|
||||
# Public: Retrieves the starting and ending buffer rows the selection is highlighting.
|
||||
# Retrieves the starting and ending buffer rows the selection is highlighting.
|
||||
#
|
||||
# Returns an {Array} of two {Number}s: the starting row, and the ending row.
|
||||
getBufferRowRange: ->
|
||||
@@ -106,22 +104,17 @@ class Selection
|
||||
end = Math.max(start, end - 1) if range.end.column == 0
|
||||
[start, end]
|
||||
|
||||
# Internal:
|
||||
screenRangeChanged: ->
|
||||
screenRange = @getScreenRange()
|
||||
@trigger 'screen-range-changed', screenRange
|
||||
|
||||
# Public: Retrieves the text in the selection.
|
||||
# Retrieves the text in the selection.
|
||||
#
|
||||
# Returns a {String}.
|
||||
getText: ->
|
||||
@editSession.buffer.getTextInRange(@getBufferRange())
|
||||
|
||||
# Public: Clears the selection, moving the marker to move to the head.
|
||||
# Clears the selection, moving the marker to move to the head.
|
||||
clear: ->
|
||||
@marker.clearTail()
|
||||
|
||||
# Public: Modifies the selection to mark the current word.
|
||||
# Modifies the selection to mark the current word.
|
||||
#
|
||||
# Returns a {Range}.
|
||||
selectWord: ->
|
||||
@@ -135,7 +128,7 @@ class Selection
|
||||
expandOverWord: ->
|
||||
@setBufferRange(@getBufferRange().union(@cursor.getCurrentWordBufferRange()))
|
||||
|
||||
# Public: Selects an entire line in the {Buffer}.
|
||||
# Selects an entire line in the {Buffer}.
|
||||
#
|
||||
# row - The line {Number} to select (default: the row of the cursor)
|
||||
selectLine: (row=@cursor.getBufferPosition().row) ->
|
||||
@@ -149,7 +142,7 @@ class Selection
|
||||
range = @getBufferRange().union(@cursor.getCurrentLineBufferRange(includeNewline: true))
|
||||
@setBufferRange(range)
|
||||
|
||||
# Public: Selects the text from the current cursor position to a given screen position.
|
||||
# Selects the text from the current cursor position to a given screen position.
|
||||
#
|
||||
# position - An instance of {Point}, with a given `row` and `column`.
|
||||
selectToScreenPosition: (position) ->
|
||||
@@ -167,61 +160,61 @@ class Selection
|
||||
else if @wordwise
|
||||
@expandOverWord()
|
||||
|
||||
# Public: Selects the text from the current cursor position to a given buffer position.
|
||||
# Selects the text from the current cursor position to a given buffer position.
|
||||
#
|
||||
# position - An instance of {Point}, with a given `row` and `column`.
|
||||
selectToBufferPosition: (position) ->
|
||||
@modifySelection => @cursor.setBufferPosition(position)
|
||||
|
||||
# Public: Selects the text one position right of the cursor.
|
||||
# Selects the text one position right of the cursor.
|
||||
selectRight: ->
|
||||
@modifySelection => @cursor.moveRight()
|
||||
|
||||
# Public: Selects the text one position left of the cursor.
|
||||
# Selects the text one position left of the cursor.
|
||||
selectLeft: ->
|
||||
@modifySelection => @cursor.moveLeft()
|
||||
|
||||
# Public: Selects all the text one position above the cursor.
|
||||
# Selects all the text one position above the cursor.
|
||||
selectUp: ->
|
||||
@modifySelection => @cursor.moveUp()
|
||||
|
||||
# Public: Selects all the text one position below the cursor.
|
||||
# Selects all the text one position below the cursor.
|
||||
selectDown: ->
|
||||
@modifySelection => @cursor.moveDown()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the top of the buffer.
|
||||
# Selects all the text from the current cursor position to the top of the buffer.
|
||||
selectToTop: ->
|
||||
@modifySelection => @cursor.moveToTop()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the bottom of the buffer.
|
||||
# Selects all the text from the current cursor position to the bottom of the buffer.
|
||||
selectToBottom: ->
|
||||
@modifySelection => @cursor.moveToBottom()
|
||||
|
||||
# Public: Selects all the text in the buffer.
|
||||
# Selects all the text in the buffer.
|
||||
selectAll: ->
|
||||
@setBufferRange(@editSession.buffer.getRange(), autoscroll: false)
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the line.
|
||||
# Selects all the text from the current cursor position to the beginning of the line.
|
||||
selectToBeginningOfLine: ->
|
||||
@modifySelection => @cursor.moveToBeginningOfLine()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the end of the line.
|
||||
# Selects all the text from the current cursor position to the end of the line.
|
||||
selectToEndOfLine: ->
|
||||
@modifySelection => @cursor.moveToEndOfLine()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the word.
|
||||
# Selects all the text from the current cursor position to the beginning of the word.
|
||||
selectToBeginningOfWord: ->
|
||||
@modifySelection => @cursor.moveToBeginningOfWord()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the end of the word.
|
||||
# Selects all the text from the current cursor position to the end of the word.
|
||||
selectToEndOfWord: ->
|
||||
@modifySelection => @cursor.moveToEndOfWord()
|
||||
|
||||
# Public: Selects all the text from the current cursor position to the beginning of the next word.
|
||||
# Selects all the text from the current cursor position to the beginning of the next word.
|
||||
selectToBeginningOfNextWord: ->
|
||||
@modifySelection => @cursor.moveToBeginningOfNextWord()
|
||||
|
||||
# Public: Moves the selection down one row.
|
||||
# Moves the selection down one row.
|
||||
addSelectionBelow: ->
|
||||
range = (@goalBufferRange ? @getBufferRange()).copy()
|
||||
nextRow = range.end.row + 1
|
||||
@@ -239,7 +232,7 @@ class Selection
|
||||
@editSession.addSelectionForBufferRange(range, goalBufferRange: range, suppressMerge: true)
|
||||
break
|
||||
|
||||
# Public: Moves the selection up one row.
|
||||
# Moves the selection up one row.
|
||||
addSelectionAbove: ->
|
||||
range = (@goalBufferRange ? @getBufferRange()).copy()
|
||||
previousRow = range.end.row - 1
|
||||
@@ -257,13 +250,13 @@ class Selection
|
||||
@editSession.addSelectionForBufferRange(range, goalBufferRange: range, suppressMerge: true)
|
||||
break
|
||||
|
||||
# Public: Replaces text at the current selection.
|
||||
# Replaces text at the current selection.
|
||||
#
|
||||
# text - A {String} representing the text to add
|
||||
# options - A hash containing the following options:
|
||||
# :normalizeIndent - TODO
|
||||
# :select - if `true`, selects the newly added text
|
||||
# :autoIndent - if `true`, indents the newly added text appropriately
|
||||
# normalizeIndent: TODO
|
||||
# select: if `true`, selects the newly added text
|
||||
# autoIndent: if `true`, indents the newly added text appropriately
|
||||
insertText: (text, options={}) ->
|
||||
oldBufferRange = @getBufferRange()
|
||||
@editSession.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
|
||||
@@ -271,6 +264,7 @@ class Selection
|
||||
text = @normalizeIndent(text, options) if options.normalizeIndent
|
||||
@clear()
|
||||
@cursor.needsAutoscroll = @cursor.isLastCursor()
|
||||
|
||||
newBufferRange = @editSession.buffer.change(oldBufferRange, text)
|
||||
if options.select
|
||||
@setBufferRange(newBufferRange, reverse: wasReversed)
|
||||
@@ -285,7 +279,7 @@ class Selection
|
||||
|
||||
newBufferRange
|
||||
|
||||
# Public: Indents the selection.
|
||||
# Indents the selection.
|
||||
#
|
||||
# options - A hash with one key, `autoIndent`. If `true`, the indentation is
|
||||
# performed appropriately. Otherwise, {EditSession.getTabText} is used
|
||||
@@ -304,7 +298,7 @@ class Selection
|
||||
else
|
||||
@indentSelectedRows()
|
||||
|
||||
# Public: If the selection spans multiple rows, indents all of them.
|
||||
# If the selection spans multiple rows, indents all of them.
|
||||
indentSelectedRows: ->
|
||||
[start, end] = @getBufferRowRange()
|
||||
for row in [start..end]
|
||||
@@ -350,17 +344,17 @@ class Selection
|
||||
desiredIndentString = @editSession.buildIndentString(desiredIndentLevel)
|
||||
line.replace(/^[\t ]*/, desiredIndentString)
|
||||
|
||||
# Public: Performs a backspace, removing the character found behind the selection.
|
||||
# Performs a backspace, removing the character found behind the selection.
|
||||
backspace: ->
|
||||
@selectLeft() if @isEmpty() and not @editSession.isFoldedAtScreenRow(@cursor.getScreenRow())
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Performs a backspace to the beginning of the current word, removing characters found there.
|
||||
# Performs a backspace to the beginning of the current word, removing characters found there.
|
||||
backspaceToBeginningOfWord: ->
|
||||
@selectToBeginningOfWord() if @isEmpty()
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Performs a backspace to the beginning of the current line, removing characters found there.
|
||||
# Performs a backspace to the beginning of the current line, removing characters found there.
|
||||
backspaceToBeginningOfLine: ->
|
||||
if @isEmpty() and @cursor.isAtBeginningOfLine()
|
||||
@selectLeft()
|
||||
@@ -368,7 +362,7 @@ class Selection
|
||||
@selectToBeginningOfLine()
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Performs a delete, removing the character found ahead of the cursor position.
|
||||
# Performs a delete, removing the character found ahead of the cursor position.
|
||||
delete: ->
|
||||
if @isEmpty()
|
||||
if @cursor.isAtEndOfLine() and fold = @editSession.largestFoldStartingAtScreenRow(@cursor.getScreenRow() + 1)
|
||||
@@ -377,12 +371,12 @@ class Selection
|
||||
@selectRight()
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Performs a delete to the end of the current word, removing characters found there.
|
||||
# Performs a delete to the end of the current word, removing characters found there.
|
||||
deleteToEndOfWord: ->
|
||||
@selectToEndOfWord() if @isEmpty()
|
||||
@deleteSelectedText()
|
||||
|
||||
# Public: Deletes the selected text.
|
||||
# Deletes the selected text.
|
||||
deleteSelectedText: ->
|
||||
bufferRange = @getBufferRange()
|
||||
if bufferRange.isEmpty() and fold = @editSession.largestFoldContainingBufferRow(bufferRange.start.row)
|
||||
@@ -390,7 +384,7 @@ class Selection
|
||||
@editSession.buffer.delete(bufferRange) unless bufferRange.isEmpty()
|
||||
@cursor?.setBufferPosition(bufferRange.start)
|
||||
|
||||
# Public: Deletes the line.
|
||||
# Deletes the line.
|
||||
deleteLine: ->
|
||||
if @isEmpty()
|
||||
start = @cursor.getScreenRow()
|
||||
@@ -407,7 +401,7 @@ class Selection
|
||||
end--
|
||||
@editSession.buffer.deleteRows(start, end)
|
||||
|
||||
# Public: Joins the current line with the one below it.
|
||||
# Joins the current line with the one below it.
|
||||
#
|
||||
# If there selection spans more than one line, all the lines are joined together.
|
||||
joinLine: ->
|
||||
@@ -447,27 +441,27 @@ class Selection
|
||||
[start, end] = @getBufferRowRange()
|
||||
@editSession.autoIndentBufferRows(start, end)
|
||||
|
||||
# Public: Wraps the selected lines in comments.
|
||||
# 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.
|
||||
# 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.
|
||||
# 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.
|
||||
# Performs a copy operation on the selection.
|
||||
#
|
||||
# maintainPasteboard - A {Boolean} indicating TODO
|
||||
copy: (maintainPasteboard=false) ->
|
||||
@@ -481,7 +475,7 @@ class Selection
|
||||
|
||||
pasteboard.write(text, metadata)
|
||||
|
||||
# Public: Folds the selection.
|
||||
# Folds the selection.
|
||||
fold: ->
|
||||
range = @getBufferRange()
|
||||
@editSession.createFold(range.start.row, range.end.row)
|
||||
@@ -499,10 +493,15 @@ class Selection
|
||||
fn()
|
||||
@retainSelection = false
|
||||
|
||||
# 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.
|
||||
#
|
||||
# Returns a {Point} representing the new tail position.
|
||||
placeTail: ->
|
||||
@marker.placeTail()
|
||||
|
||||
# Public: Identifies if a selection intersects with a given buffer range.
|
||||
# Identifies if a selection intersects with a given buffer range.
|
||||
#
|
||||
# bufferRange - A {Range} to check against
|
||||
#
|
||||
@@ -510,7 +509,7 @@ class Selection
|
||||
intersectsBufferRange: (bufferRange) ->
|
||||
@getBufferRange().intersectsWith(bufferRange)
|
||||
|
||||
# Public: Identifies if a selection intersects with another selection.
|
||||
# Identifies if a selection intersects with another selection.
|
||||
#
|
||||
# otherSelection - A `Selection` to check against
|
||||
#
|
||||
@@ -518,7 +517,7 @@ class Selection
|
||||
intersectsWith: (otherSelection) ->
|
||||
@getBufferRange().intersectsWith(otherSelection.getBufferRange())
|
||||
|
||||
# Public: Merges two selections together.
|
||||
# Merges two selections together.
|
||||
#
|
||||
# otherSelection - A `Selection` to merge with
|
||||
# options - A hash of options matching those found in {.setBufferRange}
|
||||
@@ -530,4 +529,10 @@ class Selection
|
||||
@goalBufferRange = otherSelection.goalBufferRange
|
||||
otherSelection.destroy()
|
||||
|
||||
### Internal ###
|
||||
|
||||
screenRangeChanged: ->
|
||||
screenRange = @getScreenRange()
|
||||
@trigger 'screen-range-changed', screenRange
|
||||
|
||||
_.extend Selection.prototype, EventEmitter
|
||||
|
||||
@@ -6,9 +6,7 @@ fsUtils = require 'fs-utils'
|
||||
EventEmitter = require 'event-emitter'
|
||||
NullGrammar = require 'null-grammar'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class Syntax
|
||||
|
||||
@@ -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
|
||||
@@ -55,9 +55,7 @@ class Buffer
|
||||
|
||||
@undoManager = new UndoManager(this)
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
destroy: ->
|
||||
throw new Error("Destroying buffer twice with path '#{@getPath()}'") if @destroyed
|
||||
@@ -98,18 +96,16 @@ class Buffer
|
||||
@file.on "moved", =>
|
||||
@trigger "path-changed", this
|
||||
|
||||
###
|
||||
# Public #
|
||||
###
|
||||
### 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}.
|
||||
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: ->
|
||||
@@ -119,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) ->
|
||||
@@ -150,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: ->
|
||||
@@ -159,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
|
||||
#
|
||||
@@ -197,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.
|
||||
#
|
||||
@@ -211,13 +207,18 @@ class Buffer
|
||||
lineForRow: (row) ->
|
||||
@lines[row]
|
||||
|
||||
# Given a row, returns its line ending.
|
||||
#
|
||||
# row - A {Number} indicating the row.
|
||||
#
|
||||
# Returns a {String}, or `undefined` if `row` is the final row.
|
||||
lineEndingForRow: (row) ->
|
||||
@lineEndings[row] unless row is @getLastRow()
|
||||
|
||||
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.
|
||||
#
|
||||
@@ -225,10 +226,15 @@ class Buffer
|
||||
lineLengthForRow: (row) ->
|
||||
@lines[row].length
|
||||
|
||||
# Given a row, returns the length of the line ending
|
||||
#
|
||||
# row - A {Number} indicating the row.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
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
|
||||
@@ -241,25 +247,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: ->
|
||||
@@ -282,13 +288,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
|
||||
@@ -307,33 +313,26 @@ 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
|
||||
@@ -351,7 +350,7 @@ class Buffer
|
||||
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
|
||||
@@ -368,44 +367,21 @@ 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) ->
|
||||
if isNewTransaction = @undoManager.transact()
|
||||
@pushOperation(new BufferChangeOperation(buffer: this)) # restores markers on undo
|
||||
if fn
|
||||
try
|
||||
fn()
|
||||
finally
|
||||
@commit() if isNewTransaction
|
||||
|
||||
commit: ->
|
||||
@pushOperation(new BufferChangeOperation(buffer: this)) # restores markers on redo
|
||||
@undoManager.commit()
|
||||
|
||||
abort: -> @undoManager.abort()
|
||||
|
||||
# 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)
|
||||
|
||||
# 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) ->
|
||||
@@ -418,7 +394,7 @@ class Buffer
|
||||
@triggerModifiedStatusChanged(false)
|
||||
@trigger 'saved'
|
||||
|
||||
# Public: Identifies if the buffer was modified.
|
||||
# Identifies if the buffer was modified.
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
isModified: ->
|
||||
@@ -427,12 +403,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
|
||||
@@ -467,13 +443,13 @@ class Buffer
|
||||
markers = @getMarkers().filter (marker) -> marker.matchesAttributes(attributes)
|
||||
markers.sort (a, b) -> a.getRange().compare(b.getRange())
|
||||
|
||||
# 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)
|
||||
# attributes - An optional hash of serializable attributes
|
||||
@@ -498,7 +474,7 @@ class Buffer
|
||||
@trigger 'marker-created', marker
|
||||
marker
|
||||
|
||||
# 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
|
||||
@@ -507,7 +483,7 @@ class Buffer
|
||||
markPosition: (position, options) ->
|
||||
@markRange([position, position], _.defaults({noTail: true}, options))
|
||||
|
||||
# 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
|
||||
#
|
||||
@@ -516,7 +492,7 @@ class Buffer
|
||||
position = Point.fromObject(position)
|
||||
@getMarkers().filter (marker) -> marker.containsPoint(position)
|
||||
|
||||
# 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}
|
||||
@@ -546,14 +522,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
|
||||
@@ -596,7 +572,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
|
||||
@@ -604,7 +580,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
|
||||
#
|
||||
@@ -612,7 +588,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
|
||||
#
|
||||
@@ -626,7 +602,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
|
||||
#
|
||||
@@ -639,7 +615,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: ->
|
||||
@@ -648,22 +624,46 @@ 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 ###
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
pushOperation: (operation, editSession) ->
|
||||
if @undoManager
|
||||
@undoManager.pushOperation(operation, editSession)
|
||||
else
|
||||
operation.do()
|
||||
|
||||
transact: (fn) ->
|
||||
if isNewTransaction = @undoManager.transact()
|
||||
@pushOperation(new BufferChangeOperation(buffer: this)) # restores markers on undo
|
||||
if fn
|
||||
try
|
||||
fn()
|
||||
finally
|
||||
@commit() if isNewTransaction
|
||||
|
||||
commit: ->
|
||||
@pushOperation(new BufferChangeOperation(buffer: this)) # restores markers on redo
|
||||
@undoManager.commit()
|
||||
|
||||
abort: -> @undoManager.abort()
|
||||
|
||||
change: (oldRange, newText, options) ->
|
||||
oldRange = Range.fromObject(oldRange)
|
||||
operation = new BufferChangeOperation({buffer: this, oldRange, newText, options})
|
||||
range = @pushOperation(operation)
|
||||
range
|
||||
|
||||
destroyMarker: (id) ->
|
||||
if marker = @validMarkers[id] ? @invalidMarkers[id]
|
||||
|
||||
@@ -8,9 +8,7 @@ EventEmitter = require 'event-emitter'
|
||||
pathSplitRegex = new RegExp("[#{nodePath.sep}.]")
|
||||
TextMateScopeSelector = require 'text-mate-scope-selector'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class TextMateGrammar
|
||||
@@ -502,9 +500,7 @@ class Pattern
|
||||
|
||||
tokens
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
shiftCapture = (captureIndices) ->
|
||||
[captureIndices.shift(), captureIndices.shift(), captureIndices.shift()]
|
||||
|
||||
@@ -5,9 +5,7 @@ _ = require 'underscore'
|
||||
TextMateGrammar = require 'text-mate-grammar'
|
||||
async = require 'async'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class TextMatePackage extends Package
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
class SegmentMatcher
|
||||
constructor: (segment) ->
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
PEG = require 'pegjs'
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
# Public: Test a stack of scopes to see if they match a scope selector.
|
||||
# Internal: Test a stack of scopes to see if they match a scope selector.
|
||||
module.exports =
|
||||
class TextMateScopeSelector
|
||||
@parser: null
|
||||
@@ -15,13 +15,13 @@ class TextMateScopeSelector
|
||||
source: null
|
||||
matcher: null
|
||||
|
||||
# Public: Create a new scope selector.
|
||||
# Create a new scope selector.
|
||||
#
|
||||
# source - A {String} to parse as a scope selector.
|
||||
constructor: (@source) ->
|
||||
@matcher = TextMateScopeSelector.createParser().parse(@source)
|
||||
|
||||
# Public: Check if this scope selector matches the scopes.
|
||||
# Check if this scope selector matches the scopes.
|
||||
#
|
||||
# scopes - An {Array} of {String}s.
|
||||
#
|
||||
|
||||
@@ -3,9 +3,7 @@ fsUtils = require 'fs-utils'
|
||||
plist = require 'plist'
|
||||
Theme = require 'theme'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class TextMateTheme extends Theme
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class Theme
|
||||
|
||||
@@ -7,10 +7,14 @@ class Token
|
||||
isAtomic: null
|
||||
isHardTab: null
|
||||
|
||||
### Internal ###
|
||||
|
||||
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab}) ->
|
||||
@screenDelta = @value.length
|
||||
@bufferDelta ?= @screenDelta
|
||||
|
||||
### Public ###
|
||||
|
||||
isEqual: (other) ->
|
||||
@value == other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic == !!other.isAtomic
|
||||
|
||||
@@ -92,7 +96,7 @@ class Token
|
||||
"<span class='#{classes}'>#{match}</span>"
|
||||
if hasTrailingWhitespace
|
||||
classes = []
|
||||
classes.push('indent-guide') if hasIndentGuide
|
||||
classes.push('indent-guide') if hasIndentGuide and not hasLeadingWhitespace
|
||||
classes.push('invisible-character') if invisibles.space
|
||||
classes.push('trailing-whitespace')
|
||||
classes = classes.join(' ')
|
||||
|
||||
@@ -6,9 +6,7 @@ Token = require 'token'
|
||||
Range = require 'range'
|
||||
Point = require 'point'
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
module.exports =
|
||||
class TokenizedBuffer
|
||||
@@ -69,13 +67,13 @@ class TokenizedBuffer
|
||||
setVisible: (@visible) ->
|
||||
@tokenizeInBackground() if @visible
|
||||
|
||||
# Public: Retrieves the current tab length.
|
||||
# Retrieves the current tab length.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getTabLength: ->
|
||||
@tabLength
|
||||
|
||||
# Public: Specifies the tab length.
|
||||
# Specifies the tab length.
|
||||
#
|
||||
# tabLength - A {Number} that defines the new tab length.
|
||||
setTabLength: (@tabLength) ->
|
||||
@@ -265,7 +263,7 @@ class TokenizedBuffer
|
||||
stop()
|
||||
position
|
||||
|
||||
# Public: Gets the row number of the last line.
|
||||
# Gets the row number of the last line.
|
||||
#
|
||||
# Returns a {Number}.
|
||||
getLastRow: ->
|
||||
|
||||
@@ -10,9 +10,7 @@ require 'space-pen-extensions'
|
||||
deserializers = {}
|
||||
deferredDeserializers = {}
|
||||
|
||||
###
|
||||
# Internal #
|
||||
###
|
||||
### Internal ###
|
||||
|
||||
# This method is called in any window needing a general environment, including specs
|
||||
window.setUpEnvironment = ->
|
||||
@@ -27,6 +25,7 @@ window.setUpEnvironment = ->
|
||||
window.pasteboard = new Pasteboard
|
||||
window.keymap = new Keymap()
|
||||
$(document).on 'keydown', keymap.handleKeyEvent
|
||||
|
||||
keymap.bindDefaultKeys()
|
||||
|
||||
requireStylesheet 'atom'
|
||||
@@ -43,7 +42,7 @@ window.startEditorWindow = ->
|
||||
console.warn "Failed to install `atom` binary"
|
||||
|
||||
atom.windowMode = 'editor'
|
||||
handleWindowEvents()
|
||||
handleEvents()
|
||||
handleDragDrop()
|
||||
config.load()
|
||||
keymap.loadBundledKeymaps()
|
||||
@@ -58,7 +57,7 @@ window.startEditorWindow = ->
|
||||
|
||||
window.startConfigWindow = ->
|
||||
atom.windowMode = 'config'
|
||||
handleWindowEvents()
|
||||
handleEvents()
|
||||
config.load()
|
||||
keymap.loadBundledKeymaps()
|
||||
atom.loadThemes()
|
||||
@@ -110,13 +109,22 @@ window.unloadConfigWindow = ->
|
||||
window.configView = null
|
||||
$(window).off('focus blur before')
|
||||
|
||||
window.handleWindowEvents = ->
|
||||
window.handleEvents = ->
|
||||
$(window).command 'window:toggle-full-screen', => atom.toggleFullScreen()
|
||||
$(window).on 'focus', -> $("body").removeClass('is-blurred')
|
||||
$(window).on 'blur', -> $("body").addClass('is-blurred')
|
||||
$(window).command 'window:close', => confirmClose()
|
||||
$(window).command 'window:reload', => reload()
|
||||
|
||||
$(document).on 'click', 'a', (e) ->
|
||||
location = $(e.target).attr('href')
|
||||
return unless location
|
||||
return if location[0] is '#'
|
||||
|
||||
if location.indexOf('https://') is 0 or location.indexOf('http://') is 0
|
||||
require('child_process').spawn('open', [location])
|
||||
false
|
||||
|
||||
window.handleDragDrop = ->
|
||||
$(document).on 'dragover', (e) ->
|
||||
e.preventDefault()
|
||||
@@ -263,4 +271,7 @@ window.profile = (description, fn) ->
|
||||
|
||||
# Public: Shows a dialog asking if the window was _really_ meant to be closed.
|
||||
confirmClose = ->
|
||||
rootView.confirmClose().done -> window.close()
|
||||
if rootView?
|
||||
rootView.confirmClose().done -> window.close()
|
||||
else
|
||||
window.close()
|
||||
|
||||
@@ -8,7 +8,7 @@ module.exports =
|
||||
editor.getBuffer().change(range, @reflow(editor.getTextInRange(range)))
|
||||
|
||||
reflow: (text) ->
|
||||
wrapColumn = config.get('editor.preferredLineLength') ? 80
|
||||
wrapColumn = config.getPositiveInt('editor.preferredLineLength', 80)
|
||||
lines = []
|
||||
|
||||
currentLine = []
|
||||
|
||||
@@ -37,7 +37,7 @@ class FuzzyFinderView extends SelectList
|
||||
|
||||
itemForElement: (path) ->
|
||||
$$ ->
|
||||
@li =>
|
||||
@li class: 'two-lines', =>
|
||||
if git?
|
||||
status = git.statuses[path]
|
||||
if git.isStatusNew(status)
|
||||
@@ -59,9 +59,8 @@ class FuzzyFinderView extends SelectList
|
||||
else
|
||||
typeClass = 'text-name'
|
||||
|
||||
@span fsUtils.base(path), class: "file #{typeClass}"
|
||||
if folder = project.relativize(fsUtils.directory(path))
|
||||
@span " - #{folder}/", class: 'directory'
|
||||
@div fsUtils.base(path), class: "primary-line file #{typeClass}"
|
||||
@div project.relativize(path), class: 'secondary-line path'
|
||||
|
||||
openPath: (path) ->
|
||||
rootView.open(path, {@allowActiveEditorChange}) if path
|
||||
|
||||
@@ -137,13 +137,13 @@ describe 'FuzzyFinder', ->
|
||||
rootView.attachToDom()
|
||||
rootView.open 'sample-with-tabs.coffee'
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample.txt', 'sample.js', 'sample-with-tabs.coffee']
|
||||
expect(_.pluck(finderView.list.find('li > div.file'), 'outerText')).toEqual ['sample.txt', 'sample.js', 'sample-with-tabs.coffee']
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
|
||||
rootView.open 'sample.txt'
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
|
||||
expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample-with-tabs.coffee', 'sample.js', 'sample.txt']
|
||||
expect(_.pluck(finderView.list.find('li > div.file'), 'outerText')).toEqual ['sample-with-tabs.coffee', 'sample.js', 'sample.txt']
|
||||
expect(finderView.list.children().first()).toHaveClass 'selected'
|
||||
|
||||
it "serializes the list of paths and their last opened time", ->
|
||||
@@ -182,7 +182,7 @@ describe 'FuzzyFinder', ->
|
||||
rootView.open 'sample.js'
|
||||
rootView.getActivePane().splitRight()
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
expect(_.pluck(finderView.list.children('li'), 'outerText')).toEqual ['sample.js']
|
||||
expect(_.pluck(finderView.list.find('li > div.file'), 'outerText')).toEqual ['sample.js']
|
||||
|
||||
describe "when a path selection is confirmed", ->
|
||||
[editor1, editor2] = []
|
||||
|
||||
@@ -1,64 +1,72 @@
|
||||
.fuzzy-finder .directory {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
word-break: break-word;
|
||||
margin-left: 5px;
|
||||
line-height: 150%;
|
||||
}
|
||||
.fuzzy-finder {
|
||||
|
||||
.fuzzy-finder .file:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
}
|
||||
&.select-list li {
|
||||
padding: 5px 10px 5px 10px;
|
||||
}
|
||||
|
||||
.fuzzy-finder .status {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
float: right;
|
||||
}
|
||||
.path {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
margin-left: 26px;
|
||||
font-size: .9em;
|
||||
}
|
||||
|
||||
.fuzzy-finder .status.new:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06b";
|
||||
}
|
||||
.status {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
float: right;
|
||||
|
||||
.fuzzy-finder .status.modified:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06d";
|
||||
}
|
||||
&new:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06b";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.text-name:before {
|
||||
content: "\f011";
|
||||
}
|
||||
&:before {
|
||||
position: relative;
|
||||
top: 3px;
|
||||
content: "\f06d";
|
||||
}
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.image-name:before {
|
||||
content: "\f012";
|
||||
}
|
||||
.file {
|
||||
&:before {
|
||||
font-family: 'Octicons Regular';
|
||||
font-size: 16px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 5px;
|
||||
margin-left: 5px;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
color: #9d9d9d;
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.compressed-name:before {
|
||||
content: "\f013";
|
||||
}
|
||||
&.text-name:before {
|
||||
content: "\f011";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.pdf-name:before {
|
||||
content: "\f014";
|
||||
}
|
||||
&.image-name:before {
|
||||
content: "\f012";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.readme-name:before {
|
||||
content: "\f007";
|
||||
}
|
||||
&.compressed-name:before {
|
||||
content: "\f013";
|
||||
}
|
||||
|
||||
.fuzzy-finder .file.binary-name:before {
|
||||
content: "\f094";
|
||||
&.pdf-name:before {
|
||||
content: "\f014";
|
||||
}
|
||||
|
||||
&.readme-name:before {
|
||||
content: "\f007";
|
||||
}
|
||||
|
||||
&.binary-name:before {
|
||||
content: "\f094";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,8 +30,12 @@
|
||||
'1': 'name': 'markup.italic.gfm'
|
||||
}
|
||||
{
|
||||
'match': '^#{1,6}\\s+.+$'
|
||||
'begin': '^#{1,6}\\s+'
|
||||
'end': '$'
|
||||
'name': 'markup.heading.gfm'
|
||||
'patterns': [
|
||||
'include': '$self'
|
||||
]
|
||||
}
|
||||
{
|
||||
'match': '(\\:)([^\\:\\s]+)(\\:)'
|
||||
|
||||
@@ -71,9 +71,20 @@ describe "GitHub Flavored Markdown grammar", ->
|
||||
|
||||
it "tokenizes a ## Heading", ->
|
||||
{tokens} = grammar.tokenizeLine("# Heading 1")
|
||||
expect(tokens[0]).toEqual value: "# Heading 1", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[0]).toEqual value: "# ", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[1]).toEqual value: "Heading 1", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
|
||||
{tokens} = grammar.tokenizeLine("### Heading 3")
|
||||
expect(tokens[0]).toEqual value: "### Heading 3", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[0]).toEqual value: "### ", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[1]).toEqual value: "Heading 3", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
|
||||
it "tokenzies matches inside of headers", ->
|
||||
{tokens} = grammar.tokenizeLine("# Heading :one:")
|
||||
expect(tokens[0]).toEqual value: "# ", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[1]).toEqual value: "Heading ", scopes: ["source.gfm", "markup.heading.gfm"]
|
||||
expect(tokens[2]).toEqual value: ":", scopes: ["source.gfm", "markup.heading.gfm", "string.emoji.gfm", "string.emoji.start.gfm"]
|
||||
expect(tokens[3]).toEqual value: "one", scopes: ["source.gfm", "markup.heading.gfm", "string.emoji.gfm", "string.emoji.word.gfm"]
|
||||
expect(tokens[4]).toEqual value: ":", scopes: ["source.gfm", "markup.heading.gfm", "string.emoji.gfm", "string.emoji.end.gfm"]
|
||||
|
||||
it "tokenizies an :emoji:", ->
|
||||
{tokens} = grammar.tokenizeLine("this is :no_good:")
|
||||
|
||||
@@ -5,7 +5,7 @@ _ = require 'underscore'
|
||||
|
||||
module.exports =
|
||||
class GrammarSelector extends SelectList
|
||||
@viewClass: -> "#{super} grammar-selector from-top overlay mini"
|
||||
@viewClass: -> "#{super} grammar-selector from-top overlay"
|
||||
|
||||
@activate: ->
|
||||
rootView.command 'grammar-selector:show', '.editor', => new GrammarSelector()
|
||||
|
||||
@@ -25,13 +25,13 @@ class SymbolsView extends SelectList
|
||||
|
||||
itemForElement: ({position, name, file}) ->
|
||||
$$ ->
|
||||
@li =>
|
||||
@span name
|
||||
@li class: 'two-lines', =>
|
||||
@div name, class: 'primary-line'
|
||||
if position
|
||||
text = "Line #{position.row + 1}"
|
||||
else
|
||||
text = fsUtils.base(file)
|
||||
@div text, class: 'right function-details'
|
||||
@div text, class: 'secondary-line'
|
||||
|
||||
toggleFileSymbols: ->
|
||||
if @hasParent()
|
||||
|
||||
@@ -30,10 +30,10 @@ describe "SymbolsView", ->
|
||||
expect(symbolsView.find('.loading')).toBeEmpty()
|
||||
expect(rootView.find('.symbols-view')).toExist()
|
||||
expect(symbolsView.list.children('li').length).toBe 2
|
||||
expect(symbolsView.list.children('li:first').find('span')).toHaveText 'quicksort'
|
||||
expect(symbolsView.list.children('li:first').find('.function-details')).toHaveText 'Line 1'
|
||||
expect(symbolsView.list.children('li:last').find('span')).toHaveText 'quicksort.sort'
|
||||
expect(symbolsView.list.children('li:last').find('.function-details')).toHaveText 'Line 2'
|
||||
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'quicksort'
|
||||
expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText 'Line 1'
|
||||
expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText 'quicksort.sort'
|
||||
expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText 'Line 2'
|
||||
expect(symbolsView).not.toHaveClass "error"
|
||||
expect(symbolsView.error).not.toBeVisible()
|
||||
|
||||
@@ -175,7 +175,7 @@ describe "SymbolsView", ->
|
||||
editor.trigger 'symbols-view:go-to-declaration'
|
||||
symbolsView = rootView.find('.symbols-view').view()
|
||||
expect(symbolsView.list.children('li').length).toBe 1
|
||||
expect(symbolsView.list.children('li:first').find('span')).toHaveText 'tagged.js'
|
||||
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'tagged.js'
|
||||
|
||||
describe "project symbols", ->
|
||||
it "displays all tags", ->
|
||||
@@ -192,10 +192,10 @@ describe "SymbolsView", ->
|
||||
expect(symbolsView.find('.loading')).toBeEmpty()
|
||||
expect(rootView.find('.symbols-view')).toExist()
|
||||
expect(symbolsView.list.children('li').length).toBe 4
|
||||
expect(symbolsView.list.children('li:first').find('span')).toHaveText 'callMeMaybe'
|
||||
expect(symbolsView.list.children('li:first').find('.function-details')).toHaveText 'tagged.js'
|
||||
expect(symbolsView.list.children('li:last').find('span')).toHaveText 'thisIsCrazy'
|
||||
expect(symbolsView.list.children('li:last').find('.function-details')).toHaveText 'tagged.js'
|
||||
expect(symbolsView.list.children('li:first').find('.primary-line')).toHaveText 'callMeMaybe'
|
||||
expect(symbolsView.list.children('li:first').find('.secondary-line')).toHaveText 'tagged.js'
|
||||
expect(symbolsView.list.children('li:last').find('.primary-line')).toHaveText 'thisIsCrazy'
|
||||
expect(symbolsView.list.children('li:last').find('.secondary-line')).toHaveText 'tagged.js'
|
||||
expect(symbolsView).not.toHaveClass "error"
|
||||
expect(symbolsView.error).not.toBeVisible()
|
||||
|
||||
|
||||
@@ -95,8 +95,7 @@ class TabBarView extends View
|
||||
|
||||
onDragEnd: (event) =>
|
||||
@find(".is-dragging").removeClass 'is-dragging'
|
||||
@children('.is-drop-target').removeClass 'is-drop-target'
|
||||
@children('.drop-target-is-after').removeClass 'drop-target-is-after'
|
||||
@removeDropTargetClasses()
|
||||
|
||||
onDragOver: (event) =>
|
||||
unless event.originalEvent.dataTransfer.getData('atom-event') is 'true'
|
||||
@@ -104,18 +103,16 @@ class TabBarView extends View
|
||||
event.stopPropagation()
|
||||
return
|
||||
|
||||
@removeDropTargetClasses()
|
||||
|
||||
event.preventDefault()
|
||||
currentDropTargetIndex = @find(".is-drop-target").index()
|
||||
newDropTargetIndex = @getDropTargetIndex(event)
|
||||
|
||||
if newDropTargetIndex != currentDropTargetIndex
|
||||
@children().removeClass 'is-drop-target drop-target-is-after'
|
||||
sortableObjects = @find(".sortable")
|
||||
if newDropTargetIndex < sortableObjects.length
|
||||
sortableObjects.eq(newDropTargetIndex).addClass 'is-drop-target'
|
||||
else
|
||||
sortableObjects.eq(newDropTargetIndex - 1).addClass 'drop-target-is-after'
|
||||
|
||||
sortableObjects = @find(".sortable")
|
||||
if newDropTargetIndex < sortableObjects.length
|
||||
sortableObjects.eq(newDropTargetIndex).addClass 'is-drop-target'
|
||||
else
|
||||
sortableObjects.eq(newDropTargetIndex - 1).addClass 'drop-target-is-after'
|
||||
|
||||
onDrop: (event) =>
|
||||
unless event.originalEvent.dataTransfer.getData('atom-event') is 'true'
|
||||
@@ -123,6 +120,9 @@ class TabBarView extends View
|
||||
event.stopPropagation()
|
||||
return
|
||||
|
||||
@find(".is-dragging").removeClass 'is-dragging'
|
||||
@removeDropTargetClasses()
|
||||
|
||||
event.stopPropagation()
|
||||
|
||||
dataTransfer = event.originalEvent.dataTransfer
|
||||
@@ -142,6 +142,11 @@ class TabBarView extends View
|
||||
toPane.showItem(item)
|
||||
toPane.focus()
|
||||
|
||||
removeDropTargetClasses: ->
|
||||
console.log rootView.find('.tabs .is-drop-target').length
|
||||
rootView.find('.tabs .is-drop-target').removeClass 'is-drop-target'
|
||||
rootView.find('.tabs .drop-target-is-after').removeClass 'drop-target-is-after'
|
||||
|
||||
getDropTargetIndex: (event) ->
|
||||
el = $(event.target).closest('.sortable')
|
||||
el = $(event.target).find('.sortable').last() if el.length == 0
|
||||
|
||||
@@ -32,6 +32,7 @@ describe "TabBarView", ->
|
||||
serialize: -> { deserializer: 'TestView', @title, @longTitle }
|
||||
|
||||
beforeEach ->
|
||||
window.rootView = new RootView
|
||||
registerDeserializer(TestView)
|
||||
item1 = new TestView('Item 1')
|
||||
item2 = new TestView('Item 2')
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
FileView = require './file-view'
|
||||
Directory = require 'directory'
|
||||
$ = require 'jquery'
|
||||
Git = require 'git'
|
||||
|
||||
module.exports =
|
||||
class DirectoryView extends View
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{View} = require 'space-pen'
|
||||
$ = require 'jquery'
|
||||
Git = require 'git'
|
||||
fsUtils = require 'fs-utils'
|
||||
|
||||
module.exports =
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
.tree-view-scroller {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
overflow: scroll;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.tree-view {
|
||||
|
||||
@@ -19,7 +19,7 @@ class WrapGuideView extends View
|
||||
@subscribe $(window), 'resize', => @updateGuide()
|
||||
|
||||
getDefaultColumn: ->
|
||||
config.get('editor.preferredLineLength') ? 80
|
||||
config.getPositiveInt('editor.preferredLineLength', 80)
|
||||
|
||||
getGuideColumn: (path) ->
|
||||
customColumns = config.get('wrapGuide.columns')
|
||||
|
||||
@@ -94,7 +94,10 @@ module.exports =
|
||||
else if _.isArray(value)
|
||||
cson += " #{@stringifyArray(value, indentLevel)}"
|
||||
else if _.isObject(value)
|
||||
cson += "\n#{@stringifyObject(value, indentLevel + 2)}"
|
||||
if _.isEmpty(value)
|
||||
cson += ' {}'
|
||||
else
|
||||
cson += "\n#{@stringifyObject(value, indentLevel + 2)}"
|
||||
else
|
||||
throw new Error("Unrecognized value type for key: #{key} with value: #{value}")
|
||||
prefix = '\n'
|
||||
|
||||
@@ -81,13 +81,11 @@
|
||||
}
|
||||
|
||||
.editor .invisible-character {
|
||||
opacity: 0.2;
|
||||
font-weight: normal !important;
|
||||
font-style: normal !important;
|
||||
}
|
||||
|
||||
.editor .indent-guide {
|
||||
opacity: 0.2;
|
||||
display: inline-block;
|
||||
box-shadow: inset 1px 0px;
|
||||
}
|
||||
@@ -120,12 +118,12 @@
|
||||
|
||||
.editor .underlayer, .editor .lines, .editor .overlayer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.editor .underlayer {
|
||||
z-index: 0;
|
||||
position: absolute;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.editor .lines {
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
line-height: 1;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,4 +40,4 @@
|
||||
border-bottom: none;
|
||||
border-bottom-left-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
li {
|
||||
padding: 10px;
|
||||
display: block;
|
||||
|
||||
&.two-lines {
|
||||
padding: 5px 10px 5px 10px;
|
||||
}
|
||||
|
||||
.primary-line, .secondary-line {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
li:last-child {
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
color: #c5c8c6;
|
||||
}
|
||||
|
||||
.editor .invisible-character,
|
||||
.editor .indent-guide {
|
||||
color: rgba(197, 200, 198, .2);
|
||||
}
|
||||
|
||||
.editor .gutter .line-number.fold,
|
||||
.editor .gutter .line-number:after,
|
||||
.editor .fold-marker:after {
|
||||
|
||||
@@ -32,11 +32,11 @@
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-image: -webkit-linear-gradient(#7e7e7e, #737373);
|
||||
background-color: #373A3c;
|
||||
}
|
||||
|
||||
.right,
|
||||
.directory {
|
||||
.secondary-line {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
}
|
||||
|
||||
.selected .right,
|
||||
.selected .directory {
|
||||
color: #ccc;
|
||||
.selected .secondary-line {
|
||||
color: #828282;
|
||||
}
|
||||
|
||||
.modified {
|
||||
|
||||
@@ -3,6 +3,11 @@
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.editor .invisible-character,
|
||||
.editor .indent-guide {
|
||||
color: rgba(85, 85, 85, .2);
|
||||
}
|
||||
|
||||
.editor .gutter .line-number.fold,
|
||||
.editor .gutter .line-number:after,
|
||||
.editor .fold-marker:after {
|
||||
|
||||
@@ -26,16 +26,16 @@
|
||||
}
|
||||
|
||||
.selected {
|
||||
background-color: #e0e0e0;
|
||||
background-color: #e2e2e2;
|
||||
}
|
||||
|
||||
.selected .right,
|
||||
.selected .directory {
|
||||
color: #333;
|
||||
.selected .secondary-line {
|
||||
color: #757575;
|
||||
}
|
||||
|
||||
.right,
|
||||
.directory {
|
||||
.secondary-line {
|
||||
color: #777;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user