diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b06c16ca..763af5145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 diff --git a/docs/getting-started.md b/docs/getting-started.md index 59104b772..92b31f50e 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -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. diff --git a/native/atom_application.mm b/native/atom_application.mm index f3117f94f..659c4adaf 100644 --- a/native/atom_application.mm +++ b/native/atom_application.mm @@ -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 diff --git a/native/atom_cef_client.cpp b/native/atom_cef_client.cpp index 4b39da42d..b25cee48e 100644 --- a/native/atom_cef_client.cpp +++ b/native/atom_cef_client.cpp @@ -171,11 +171,10 @@ bool AtomCefClient::OnKeyEvent(CefRefPtr browser, } void AtomCefClient::OnBeforeClose(CefRefPtr browser) { -// REQUIRE_UI_THREAD(); // When uncommented this fails when app is terminated m_Browser = NULL; numberOfOpenBrowsers--; if (numberOfOpenBrowsers == 0) { - CefQuitMessageLoop(); + Terminate(); } } diff --git a/native/atom_cef_client.h b/native/atom_cef_client.h index 83c07ec12..8f93c384c 100644 --- a/native/atom_cef_client.h +++ b/native/atom_cef_client.h @@ -127,6 +127,7 @@ class AtomCefClient : public CefClient, void ShowSaveDialog(int replyId, CefRefPtr browser); CefRefPtr CreateReplyDescriptor(int replyId, int callbackIndex); void Exit(int status); + void Terminate(); void Log(const char *message); void Show(CefRefPtr browser); void ToggleFullScreen(CefRefPtr browser); diff --git a/native/atom_cef_client_mac.mm b/native/atom_cef_client_mac.mm index 72573ebb2..bb7acb242 100644 --- a/native/atom_cef_client_mac.mm +++ b/native/atom_cef_client_mac.mm @@ -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); } diff --git a/native/mac/atom.icns b/native/mac/atom.icns index d438c6be9..0a8747abe 100644 Binary files a/native/mac/atom.icns and b/native/mac/atom.icns differ diff --git a/package.json b/package.json index 379f1eb11..85dec3096 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "devDependencies" : { - "biscotto" : "0.0.9" + "biscotto" : "0.0.11" }, "private": true, diff --git a/spec/app/config-panel-spec.coffee b/spec/app/config-panel-spec.coffee index a1f9dabed..c8995a7b1 100644 --- a/spec/app/config-panel-spec.coffee +++ b/spec/app/config-panel-spec.coffee @@ -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() diff --git a/spec/app/config-spec.coffee b/spec/app/config-spec.coffee index 7bfe22e2f..ec8a81d52 100644 --- a/spec/app/config-spec.coffee +++ b/spec/app/config-spec.coffee @@ -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') diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 8e9c97cf7..0aca4b840 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -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]] diff --git a/spec/app/pane-spec.coffee b/spec/app/pane-spec.coffee index a55650699..ca5ded3dd 100644 --- a/spec/app/pane-spec.coffee +++ b/spec/app/pane-spec.coffee @@ -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' diff --git a/spec/app/window-spec.coffee b/spec/app/window-spec.coffee index 82a146871..989face89 100644 --- a/spec/app/window-spec.coffee +++ b/spec/app/window-spec.coffee @@ -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') + + $("the website").appendTo(document.body).click().remove() + expect(ChildProcess.spawn).toHaveBeenCalled() + expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe "http://github.com" + + ChildProcess.spawn.reset() + $("the website").appendTo(document.body).click().remove() + expect(ChildProcess.spawn).toHaveBeenCalled() + expect(ChildProcess.spawn.argsForCall[0][1][0]).toBe "https://github.com" + + ChildProcess.spawn.reset() + $("the website").appendTo(document.body).click().remove() + expect(ChildProcess.spawn).not.toHaveBeenCalled() + + ChildProcess.spawn.reset() + $("link").appendTo(document.body).click().remove() + expect(ChildProcess.spawn).not.toHaveBeenCalled() diff --git a/spec/stdlib/cson-spec.coffee b/spec/stdlib/cson-spec.coffee index bee9e2032..6ec3ec12a 100644 --- a/spec/stdlib/cson-spec.coffee +++ b/spec/stdlib/cson-spec.coffee @@ -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", -> diff --git a/src/app/atom-package.coffee b/src/app/atom-package.coffee index 10fa6b874..698a7c988 100644 --- a/src/app/atom-package.coffee +++ b/src/app/atom-package.coffee @@ -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 diff --git a/src/app/atom-theme.coffee b/src/app/atom-theme.coffee index 832bbf0ab..10015a1eb 100644 --- a/src/app/atom-theme.coffee +++ b/src/app/atom-theme.coffee @@ -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) diff --git a/src/app/binding-set.coffee b/src/app/binding-set.coffee index a13c564c1..547de99c7 100644 --- a/src/app/binding-set.coffee +++ b/src/app/binding-set.coffee @@ -5,9 +5,7 @@ fsUtils = require 'fs-utils' Specificity = require 'specificity' PEG = require 'pegjs' -### -# Internal # -### +### Internal ### module.exports = class BindingSet diff --git a/src/app/buffer-change-operation.coffee b/src/app/buffer-change-operation.coffee index 2de448992..4a65730f3 100644 --- a/src/app/buffer-change-operation.coffee +++ b/src/app/buffer-change-operation.coffee @@ -1,9 +1,7 @@ Range = require 'range' _ = require 'underscore' -### -# Internal # -### +### Internal ### module.exports = class BufferChangeOperation diff --git a/src/app/buffer-marker.coffee b/src/app/buffer-marker.coffee index 8063214e4..83636e42d 100644 --- a/src/app/buffer-marker.coffee +++ b/src/app/buffer-marker.coffee @@ -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() diff --git a/src/app/config-panel.coffee b/src/app/config-panel.coffee index 16aa17ab9..403f70faf 100644 --- a/src/app/config-panel.coffee +++ b/src/app/config-panel.coffee @@ -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 diff --git a/src/app/config.coffee b/src/app/config.coffee index 067f3d0cb..c47b1e4cf 100644 --- a/src/app/config.coffee +++ b/src/app/config.coffee @@ -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() diff --git a/src/app/cursor-view.coffee b/src/app/cursor-view.coffee index 6e4c96686..64b9851dd 100644 --- a/src/app/cursor-view.coffee +++ b/src/app/cursor-view.coffee @@ -3,7 +3,7 @@ Point = require 'point' Range = require 'range' _ = require 'underscore' -# Internal: +### Internal ### module.exports = class CursorView extends View @content: -> diff --git a/src/app/cursor.coffee b/src/app/cursor.coffee index e47411624..6db87b6e3 100644 --- a/src/app/cursor.coffee +++ b/src/app/cursor.coffee @@ -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: -> diff --git a/src/app/directory.coffee b/src/app/directory.coffee index 8ec45eba3..2cce2db80 100644 --- a/src/app/directory.coffee +++ b/src/app/directory.coffee @@ -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 diff --git a/src/app/display-buffer-marker.coffee b/src/app/display-buffer-marker.coffee index 053d63fbc..3a87916f2 100644 --- a/src/app/display-buffer-marker.coffee +++ b/src/app/display-buffer-marker.coffee @@ -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] diff --git a/src/app/display-buffer.coffee b/src/app/display-buffer.coffee index 2903b0ad0..5ef05e016 100644 --- a/src/app/display-buffer.coffee +++ b/src/app/display-buffer.coffee @@ -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 diff --git a/src/app/edit-session.coffee b/src/app/edit-session.coffee index 3a88e83fa..2ce935186 100644 --- a/src/app/edit-session.coffee +++ b/src/app/edit-session.coffee @@ -10,14 +10,12 @@ Range = require 'range' _ = require 'underscore' fsUtils = require 'fs-utils' -# Public: An `EditSession` manages the states between {Editor}s, {Buffer}s, and the project as a whole. +# An `EditSession` manages the states between {Editor}s, {Buffer}s, and the project as a whole. module.exports = class EditSession registerDeserializer(this) - ### - # Internal # - ### + ### Internal ### @version: 1 @@ -87,17 +85,13 @@ class EditSession scrollLeft: @getScrollLeft() cursorScreenPosition: @getCursorScreenPosition().serialize() - # Internal: Creates a copy of the current {EditSession}. - # - # Returns an identical `EditSession`. + # Creates a copy of the current {EditSession}.Returns an identical `EditSession`. copy: -> EditSession.deserialize(@serialize(), @project) - ### - # Public # - ### + ### Public ### - # Public: Retrieves the filename of the open file. + # Retrieves the filename of the open file. # # This is `'untitled'` if the file is new and not saved to the disk. # @@ -108,7 +102,7 @@ class EditSession else 'untitled' - # Public: Retrieves the filename of the open file, followed by a dash, then the file's directory. + # Retrieves the filename of the open file, followed by a dash, then the file's directory. # # If the file is brand new, the title is `untitled`. # @@ -121,7 +115,7 @@ class EditSession else 'untitled' - # Public: Compares two `EditSession`s to determine equality. + # Compares two `EditSession`s to determine equality. # # Equality is based on the condition that: # @@ -140,45 +134,47 @@ class EditSession setVisible: (visible) -> @displayBuffer.setVisible(visible) - # Public: Defines the value of the `EditSession`'s `scrollTop` property. + # Defines the value of the `EditSession`'s `scrollTop` property. # # scrollTop - A {Number} defining the `scrollTop`, in pixels. setScrollTop: (@scrollTop) -> - # Public: Gets the value of the `EditSession`'s `scrollTop` property. + + # Gets the value of the `EditSession`'s `scrollTop` property. # # Returns a {Number} defining the `scrollTop`, in pixels. getScrollTop: -> @scrollTop - # Public: Defines the value of the `EditSession`'s `scrollLeft` property. + # Defines the value of the `EditSession`'s `scrollLeft` property. # # scrollLeft - A {Number} defining the `scrollLeft`, in pixels. setScrollLeft: (@scrollLeft) -> - # Public: Gets the value of the `EditSession`'s `scrollLeft` property. + + # Gets the value of the `EditSession`'s `scrollLeft` property. # # Returns a {Number} defining the `scrollLeft`, in pixels. getScrollLeft: -> @scrollLeft - # 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) -> @displayBuffer.setSoftWrapColumn(@softWrapColumn) - # Public: Defines whether to use soft tabs. + # Defines whether to use soft tabs. # # softTabs - A {Boolean} which, if `true`, indicates that you want soft tabs. setSoftTabs: (@softTabs) -> - # Public: Retrieves whether soft tabs are enabled. + # Retrieves whether soft tabs are enabled. # # Returns a {Boolean}. getSoftWrap: -> @softWrap - # Public: Defines whether to use soft wrapping of text. + # Defines whether to use soft wrapping of text. # # softTabs - A {Boolean} which, if `true`, indicates that you want soft wraps. setSoftWrap: (@softWrap) -> - # Public: Retrieves that character used to indicate a tab. + # Retrieves that character used to indicate a tab. # # If soft tabs are enabled, this is a space (`" "`) times the {.getTabLength} value. # Otherwise, it's a tab (`\t`). @@ -186,17 +182,17 @@ class EditSession # Returns a {String}. getTabText: -> @buildIndentString(1) - # Public: Retrieves the current tab length. + # Retrieves the current tab length. # # Returns a {Number}. getTabLength: -> @displayBuffer.getTabLength() - # Public: Specifies the tab length. + # Specifies the tab length. # # tabLength - A {Number} that defines the new tab length. setTabLength: (tabLength) -> @displayBuffer.setTabLength(tabLength) - # 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 @@ -207,7 +203,7 @@ class EditSession # Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed. clipBufferPosition: (bufferPosition) -> @buffer.clipPosition(bufferPosition) - # 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 @@ -218,7 +214,7 @@ class EditSession # Returns the new, clipped {Point}. Note that this could be the same as `range` if no clipping was performed. clipBufferRange: (range) -> @buffer.clipRange(range) - # Public: Given a buffer row, this retrieves the indentation level. + # Given a buffer row, this retrieves the indentation level. # # bufferRow - A {Number} indicating the buffer row. # @@ -226,7 +222,7 @@ class EditSession indentationForBufferRow: (bufferRow) -> @indentLevelForLine(@lineForBufferRow(bufferRow)) - # Public: This specifies the new indentation level for a buffer row. + # This specifies the new indentation level for a buffer row. # # bufferRow - A {Number} indicating the buffer row. # newLevel - A {Number} indicating the new indentation level. @@ -236,7 +232,7 @@ class EditSession newIndentString = @buildIndentString(newLevel) @buffer.change([[bufferRow, 0], [bufferRow, currentIndentString.length]], newIndentString) - # Internal: Given a line, this gets the indentation level. + # Given a line, this retrieves the indentation level. # # line - A {String} in the current {Buffer}. # @@ -250,242 +246,134 @@ class EditSession else 0 - # Internal: Constructs the string used for tabs. + # Constructs the string used for tabs. buildIndentString: (number) -> if @softTabs _.multiplyString(" ", number * @getTabLength()) else _.multiplyString("\t", Math.floor(number)) - # Public: Saves the buffer. + # {Delegates to: Buffer.save} save: -> @buffer.save() - # Public: Saves the buffer at a specific path. - # - # path - The path to save at. + # {Delegates to: Buffer.saveAs} saveAs: (path) -> @buffer.saveAs(path) - # Public: Retrieves the current buffer's file extension. - # - # Returns a {String}. + # {Delegates to: Buffer.getExtension} getFileExtension: -> @buffer.getExtension() - # Public: Retrieves the current buffer's file path. - # - # Returns a {String}. + # {Delegates to: Buffer.getPath} getPath: -> @buffer.getPath() - # Public: Retrieves the current buffer's text. - # - # Return a {String}. + # {Delegates to: Buffer.getText} getText: -> @buffer.getText() - # Public: Set the current buffer's text content. - # - # Return a {String}. + # {Delegates to: Buffer.setText} setText: (text) -> @buffer.setText(text) - # Public: Retrieves the current buffer. + # Retrieves the current buffer. # - # Returns a {String}. + # Returns a {Buffer}. getBuffer: -> @buffer - # Public: Retrieves the current buffer's URI. + # Retrieves the current buffer's URI. # # Returns a {String}. getUri: -> @getPath() - # Public: Given a buffer row, identifies if it is blank. - # - # bufferRow - A buffer row {Number} to check - # - # Returns a {Boolean}. + # {Delegates to: Buffer.isRowBlank} isBufferRowBlank: (bufferRow) -> @buffer.isRowBlank(bufferRow) - # Public: Given a buffer row, this finds the next row that's blank. - # - # bufferRow - A buffer row {Number} to check - # - # Returns a {Number}, or `null` if there's no other blank row. + # {Delegates to: Buffer.nextNonBlankRow} nextNonBlankBufferRow: (bufferRow) -> @buffer.nextNonBlankRow(bufferRow) - # Public: Finds the last point in the current buffer. - # - # Returns a {Point} representing the last position. + # {Delegates to: Buffer.getEofPosition} getEofBufferPosition: -> @buffer.getEofPosition() - # Public: Finds the last line in the current buffer. - # - # Returns a {Number}. + # {Delegates to: Buffer.getLastRow} getLastBufferRow: -> @buffer.getLastRow() - # Public: 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 - # want to include the trailing newline - # - # Returns a {Range}. + # {Delegates to: Buffer.rangeForRow} bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options) - # Public: Given a buffer row, this retrieves that line. - # - # row - A {Number} identifying the row - # - # Returns a {String}. + # {Delegates to: Buffer.lineForRow} lineForBufferRow: (row) -> @buffer.lineForRow(row) - # Public: Given a buffer row, this retrieves that line's length. - # - # row - A {Number} identifying the row - # - # Returns a {Number}. + # {Delegates to: Buffer.lineLengthForRow} lineLengthForBufferRow: (row) -> @buffer.lineLengthForRow(row) - # Public: Scans for text in the buffer, calling a function on each match. - # - # regex - A {RegExp} representing the text to find - # range - A {Range} in the buffer to search within - # iterator - A {Function} that's called on each match + # {Delegates to: Buffer.scanInRange} scanInBufferRange: (args...) -> @buffer.scanInRange(args...) - # Public: Scans for text in the buffer _backwards_, calling a function on each match. - # - # regex - A {RegExp} representing the text to find - # range - A {Range} in the buffer to search within - # iterator - A {Function} that's called on each match + # {Delegates to: Buffer.backwardsScanInRange} backwardsScanInBufferRange: (args...) -> @buffer.backwardsScanInRange(args...) - # Public: Identifies if the {Buffer} is modified (and not saved). - # - # Returns a {Boolean}. + # {Delegates to: Buffer.isModified} isModified: -> @buffer.isModified() - # Public: Identifies if the modified buffer should let you know if it's closing + # Identifies if the modified buffer should let you know if it's closing # without being saved. # # Returns a {Boolean}. shouldPromptToSave: -> @isModified() and not @buffer.hasMultipleEditors() - # Public: 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 - The same options available to {DisplayBuffer.screenPositionForBufferPosition}. - # - # Returns a {Point}. + # {Delegates to: DisplayBuffer.screenPositionForBufferPosition} screenPositionForBufferPosition: (bufferPosition, options) -> @displayBuffer.screenPositionForBufferPosition(bufferPosition, options) - # Public: 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 - The same options available to {DisplayBuffer.bufferPositionForScreenPosition}. - # - # Returns a {Point}. + # {Delegates to: DisplayBuffer.bufferPositionForScreenPosition} bufferPositionForScreenPosition: (screenPosition, options) -> @displayBuffer.bufferPositionForScreenPosition(screenPosition, options) - # Public: Given a buffer range, this converts it into a screen position. - # - # bufferRange - The {Range} to convert - # - # Returns a {Range}. + # {Delegates to: DisplayBuffer.screenRangeForBufferRange} screenRangeForBufferRange: (bufferRange) -> @displayBuffer.screenRangeForBufferRange(bufferRange) - # Public: Given a screen range, this converts it into a buffer position. - # - # screenRange - The {Range} to convert - # - # Returns a {Range}. + # {Delegates to: DisplayBuffer.bufferRangeForScreenRange} bufferRangeForScreenRange: (screenRange) -> @displayBuffer.bufferRangeForScreenRange(screenRange) - # Public: 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 - # to a real position. - # - # 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 - # - # Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed. + + # {Delegates to: DisplayBuffer.clipScreenPosition} clipScreenPosition: (screenPosition, options) -> @displayBuffer.clipScreenPosition(screenPosition, options) - # Public: Gets the line for the given screen row. - # - # screenRow - A {Number} indicating the screen row. - # - # Returns a {String}. + # {Delegates to: DisplayBuffer.lineForRow} lineForScreenRow: (row) -> @displayBuffer.lineForRow(row) - # Public: Gets the lines for the given screen row boundaries. - # - # start - A {Number} indicating the beginning screen row. - # end - A {Number} indicating the ending screen row. - # - # Returns an {Array} of {String}s. + # {Delegates to: DisplayBuffer.linesForRows} linesForScreenRows: (start, end) -> @displayBuffer.linesForRows(start, end) - # Public: Gets the number of screen rows. - # - # Returns a {Number}. + # {Delegates to: DisplayBuffer.getLineCount} getScreenLineCount: -> @displayBuffer.getLineCount() - # Public: Gets the length of the longest screen line. - # - # Returns a {Number}. + # {Delegates to: DisplayBuffer.maxLineLength} maxScreenLineLength: -> @displayBuffer.maxLineLength() - # Public: Gets the number of the last row in the buffer. - # - # Returns a {Number}. + # {Delegates to: DisplayBuffer.getLastRow} getLastScreenRow: -> @displayBuffer.getLastRow() - # Public: Given a starting and ending row, this converts every row into a buffer position. - # - # startRow - The row {Number} to start at - # endRow - The row {Number} to end at (default: {.getLastScreenRow}) - # - # Returns an {Array} of {Range}s. + # {Delegates to: DisplayBuffer.bufferRowsForScreenRows} bufferRowsForScreenRows: (startRow, endRow) -> @displayBuffer.bufferRowsForScreenRows(startRow, endRow) - # Public: Retrieves the grammar's token scopes for a buffer position. - # - # bufferPosition - A {Point} in the {Buffer} - # - # Returns an {Array} of {String}s. + # {Delegates to: DisplayBuffer.bufferRowsForScreenRows} scopesForBufferPosition: (bufferPosition) -> @displayBuffer.scopesForBufferPosition(bufferPosition) - # Public: Retrieves the grammar's token for a buffer position. - # - # bufferPosition - A {Point} in the {Buffer} - # - # Returns a {Token}. + # {Delegates to: DisplayBuffer.tokenForBufferPosition} tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition) - # Public: Retrieves the grammar's token scopes for the line with the most recently added cursor. + # Retrieves the grammar's token scopes for the line with the most recently added cursor. # # Returns an {Array} of {String}s. getCursorScopes: -> @getCursor().getScopes() - # Internal: - logScreenLines: (start, end) -> @displayBuffer.logLines(start, end) - - # Public: Determines whether the {Editor} will auto indent rows. + # Determines whether the {Editor} will auto indent rows. # # Returns a {Boolean}. shouldAutoIndent: -> config.get("editor.autoIndent") - # Public: Determines whether the {Editor} will auto indent pasted text. + # Determines whether the {Editor} will auto indent pasted text. # # Returns a {Boolean}. shouldAutoIndentPastedText: -> config.get("editor.autoIndentOnPaste") - # Public: Inserts text at the current cursor positions + # Inserts text at the current cursor positions # # text - A {String} representing the text to insert. # options - A set of options equivalent to {Selection.insertText} @@ -493,17 +381,17 @@ class EditSession options.autoIndent ?= @shouldAutoIndent() @mutateSelectedText (selection) -> selection.insertText(text, options) - # Public: Inserts a new line at the current cursor positions. + # Inserts a new line at the current cursor positions. insertNewline: -> @insertText('\n') - # Public: Inserts a new line below the current cursor positions. + # Inserts a new line below the current cursor positions. insertNewlineBelow: -> @transact => @moveCursorToEndOfLine() @insertNewline() - # Public: Inserts a new line above the current cursor positions. + # Inserts a new line above the current cursor positions. insertNewlineAbove: -> @transact => onFirstLine = @getCursorBufferPosition().row is 0 @@ -512,46 +400,46 @@ class EditSession @insertNewline() @moveCursorUp() if onFirstLine - # Public: Indents the current line. + # Indents the current line. # # options - A set of options equivalent to {Selection.indent}. indent: (options={})-> options.autoIndent ?= @shouldAutoIndent() @mutateSelectedText (selection) -> selection.indent(options) - # Public: Performs a backspace, removing the character found behind the cursor position. + # Performs a backspace, removing the character found behind the cursor position. backspace: -> @mutateSelectedText (selection) -> selection.backspace() - # 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: -> @mutateSelectedText (selection) -> selection.backspaceToBeginningOfWord() - # 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: -> @mutateSelectedText (selection) -> selection.backspaceToBeginningOfLine() - # 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: -> @mutateSelectedText (selection) -> selection.delete() - # 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: -> @mutateSelectedText (selection) -> selection.deleteToEndOfWord() - # Public: Deletes the entire line. + # Deletes the entire line. deleteLine: -> @mutateSelectedText (selection) -> selection.deleteLine() - # Public: Indents the selected rows. + # Indents the selected rows. indentSelectedRows: -> @mutateSelectedText (selection) -> selection.indentSelectedRows() - # Public: Outdents the selected rows. + # Outdents the selected rows. outdentSelectedRows: -> @mutateSelectedText (selection) -> selection.outdentSelectedRows() - # Public: Wraps the lines within a selection in comments. + # Wraps the lines within a selection in comments. # # If the language doesn't have comments, nothing happens. # @@ -564,14 +452,14 @@ class EditSession autoIndentSelectedRows: -> @mutateSelectedText (selection) -> selection.autoIndentSelectedRows() - # Given a buffer range, this converts all `\t` characters to the appopriate {.getTabText} value. + # Given a buffer range, this converts all `\t` characters to the appropriate {.getTabText} value. # # bufferRange - The {Range} to perform the replace in normalizeTabsInBufferRange: (bufferRange) -> return unless @softTabs @scanInBufferRange /\t/, bufferRange, ({replace}) => replace(@getTabText()) - # Public: Performs a cut to the end of the current line. + # Performs a cut to the end of the current line. # # Characters are removed, but the text remains in the clipboard. cutToEndOfLine: -> @@ -580,21 +468,21 @@ class EditSession selection.cutToEndOfLine(maintainPasteboard) maintainPasteboard = true - # Public: Cuts the selected text. + # Cuts the selected text. cutSelectedText: -> maintainPasteboard = false @mutateSelectedText (selection) -> selection.cut(maintainPasteboard) maintainPasteboard = true - # Public: Copies the selected text. + # Copies the selected text. copySelectedText: -> maintainPasteboard = false for selection in @getSelections() selection.copy(maintainPasteboard) maintainPasteboard = true - # Public: Pastes the text in the clipboard. + # Pastes the text in the clipboard. # # options - A set of options equivalent to {Selection.insertText}. pasteText: (options={}) -> @@ -606,91 +494,70 @@ class EditSession @insertText(text, options) - # Public: Undos the last {Buffer} change. + # Undos the last {Buffer} change. undo: -> @buffer.undo(this) - # Public: Redos the last {Buffer} change. + # Redos the last {Buffer} change. redo: -> @buffer.redo(this) - ### - # Internal # - ### - - transact: (fn) -> @buffer.transact(fn) - - commit: -> @buffer.commit() - - abort: -> @buffer.abort() - - ### - # Public # - ### - - # Public: Folds all the rows. + # Folds all the rows. foldAll: -> @languageMode.foldAll() - # Public: Unfolds all the rows. + # Unfolds all the rows. unfoldAll: -> @languageMode.unfoldAll() - # Public: Folds the current row. + # Folds the current row. foldCurrentRow: -> bufferRow = @bufferPositionForScreenPosition(@getCursorScreenPosition()).row @foldBufferRow(bufferRow) - # Public: Given a buffer row, this folds it. + # Given a buffer row, this folds it. # # bufferRow - A {Number} indicating the buffer row foldBufferRow: (bufferRow) -> @languageMode.foldBufferRow(bufferRow) - # Public: Unfolds the current row. + # Unfolds the current row. unfoldCurrentRow: -> bufferRow = @bufferPositionForScreenPosition(@getCursorScreenPosition()).row @unfoldBufferRow(bufferRow) - # Public: Given a buffer row, this unfolds it. + # Given a buffer row, this unfolds it. # # bufferRow - A {Number} indicating the buffer row unfoldBufferRow: (bufferRow) -> @languageMode.unfoldBufferRow(bufferRow) - # Public: Folds all selections. + # Folds all selections. foldSelection: -> selection.fold() for selection in @getSelections() - # Public: Creates a new fold between two row numbers. - # - # startRow - The row {Number} to start folding at - # endRow - The row {Number} to end the fold - # - # Returns the new {Fold}. + # {Delegates to: DisplayBuffer.createFold} createFold: (startRow, endRow) -> @displayBuffer.createFold(startRow, endRow) - # Public: Removes any {Fold}s found that contain the given buffer row. - # - # bufferRow - The buffer row {Number} to check against + # {Delegates to: DisplayBuffer.destroyFoldsContainingBufferRow} destroyFoldsContainingBufferRow: (bufferRow) -> @displayBuffer.destroyFoldsContainingBufferRow(bufferRow) - # Public: Removes any {Fold}s found that intersect the given buffer row. + # Removes any {Fold}s found that intersect the given buffer row. # # bufferRow - The buffer row {Number} to check against destroyFoldsIntersectingBufferRange: (bufferRange) -> for row in [bufferRange.start.row..bufferRange.end.row] @destroyFoldsContainingBufferRow(row) - # Public: Determines if the given row that the cursor is at is folded. + # Determines if the given row that the cursor is at is folded. # # Returns `true` if the row is folded, `false` otherwise. isFoldedAtCursorRow: -> @isFoldedAtScreenRow(@getCursorScreenRow()) - # Public: Determines if the given buffer row is folded. + # Determines if the given buffer row is folded. # # bufferRow - A {Number} indicating the buffer row. # @@ -699,7 +566,7 @@ class EditSession screenRow = @screenPositionForBufferPosition([bufferRow]).row @isFoldedAtScreenRow(screenRow) - # Public: Determines if the given screen row is folded. + # Determines if the given screen row is folded. # # screenRow - A {Number} indicating the screen row. # @@ -707,29 +574,15 @@ class EditSession isFoldedAtScreenRow: (screenRow) -> @lineForScreenRow(screenRow)?.fold? - # Public: 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 points - # are the greatest. - # - # bufferRow - A {Number} indicating the buffer row - # - # Returns a {Fold}. + # {Delegates to: DisplayBuffer.largestFoldContainingBufferRow} largestFoldContainingBufferRow: (bufferRow) -> @displayBuffer.largestFoldContainingBufferRow(bufferRow) - # Public: 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. - # - # screenRow - A {Number} indicating the screen row - # - # Returns a {Fold}. + # {Delegates to: DisplayBuffer.largestFoldStartingAtScreenRow} largestFoldStartingAtScreenRow: (screenRow) -> @displayBuffer.largestFoldStartingAtScreenRow(screenRow) - # 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 language. # @@ -739,32 +592,32 @@ class EditSession suggestedIndentForBufferRow: (bufferRow) -> @languageMode.suggestedIndentForBufferRow(bufferRow) - # Public: Indents all the rows between two buffer rows. + # Indents all the rows between two buffer rows. # # startRow - The row {Number} to start at # endRow - The row {Number} to end at autoIndentBufferRows: (startRow, endRow) -> @languageMode.autoIndentBufferRows(startRow, endRow) - # Public: Given a buffer row, this indents it. + # Given a buffer row, this indents it. # # bufferRow - The row {Number} autoIndentBufferRow: (bufferRow) -> @languageMode.autoIndentBufferRow(bufferRow) - # Public: Given a buffer row, this increases the indentation. + # Given a buffer row, this increases the indentation. # # bufferRow - The row {Number} autoIncreaseIndentForBufferRow: (bufferRow) -> @languageMode.autoIncreaseIndentForBufferRow(bufferRow) - # Public: Given a buffer row, this decreases the indentation. + # Given a buffer row, this decreases the indentation. # # bufferRow - The row {Number} autoDecreaseIndentForRow: (bufferRow) -> @languageMode.autoDecreaseIndentForBufferRow(bufferRow) - # Public: Wraps the lines between two rows in comments. + # Wraps the lines between two rows in comments. # # If the language doesn't have comments, nothing happens. # @@ -775,7 +628,7 @@ class EditSession toggleLineCommentsForBufferRows: (start, end) -> @languageMode.toggleLineCommentsForBufferRows(start, end) - # Public: Moves the selected line up one row. + # Moves the selected line up one row. moveLineUp: -> selection = @getSelectedBufferRange() return if selection.start.row is 0 @@ -809,7 +662,7 @@ class EditSession @setSelectedBufferRange(selection.translate([-1]), preserveFolds: true) - # Public: Moves the selected line down one row. + # Moves the selected line down one row. moveLineDown: -> selection = @getSelectedBufferRange() lastRow = @buffer.getLastRow() @@ -847,7 +700,7 @@ class EditSession @setSelectedBufferRange(selection.translate([1]), preserveFolds: true) - # Public: Duplicates the current line. + # Duplicates the current line. # # If more than one cursor is present, only the most recently added one is considered. duplicateLine: -> @@ -873,10 +726,7 @@ class EditSession @setCursorScreenPosition(@getCursorScreenPosition().translate([1])) @foldCurrentRow() if cursorRowFolded - - ### - # Internal # - ### + ### Internal ### mutateSelectedText: (fn) -> @transact => fn(selection) for selection in @getSelections() @@ -895,96 +745,54 @@ class EditSession pushOperation: (operation) -> @buffer.pushOperation(operation, this) - ### - # Public # - ### + ### Public ### # Returns a valid {DisplayBufferMarker} object for the given id if one exists. getMarker: (id) -> @displayBuffer.getMarker(id) - # 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. + # {Delegates to: DisplayBuffer.markScreenRange} markScreenRange: (args...) -> @displayBuffer.markScreenRange(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. + # {Delegates to: DisplayBuffer.markBufferRange} markBufferRange: (args...) -> @displayBuffer.markBufferRange(args...) - # 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. + # {Delegates to: DisplayBuffer.markScreenPosition} markScreenPosition: (args...) -> @displayBuffer.markScreenPosition(args...) - # 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. + # {Delegates to: DisplayBuffer.markBufferPosition} markBufferPosition: (args...) -> @displayBuffer.markBufferPosition(args...) - # Public: Removes the marker with the given id. - # - # id - The {Number} of the ID to remove + # {Delegates to: DisplayBuffer.destroyMarker} destroyMarker: (args...) -> @displayBuffer.destroyMarker(args...) - # Public: Gets the number of markers in the buffer. - # - # Returns a {Number}. + # {Delegates to: Buffer.getMarkerCount} getMarkerCount: -> @buffer.getMarkerCount() - # Public: Gets the screen range of the display marker. - # - # id - The {Number} of the ID to check - # - # Returns a {Range}. - getMarkerScreenRange: (args...) -> - @displayBuffer.getMarkerScreenRange(args...) - - # Public: Modifies the screen range of the display marker. - # - # id - The {Number} of the ID to change - # screenRange - The new {Range} to use - # options - A hash of options matching those found in {BufferMarker.setRange} - setMarkerScreenRange: (args...) -> - @displayBuffer.setMarkerScreenRange(args...) - - # Public: Returns `true` if there are multiple cursors in the edit session. + # Returns `true` if there are multiple cursors in the edit session. # # Returns a {Boolean}. hasMultipleCursors: -> @getCursors().length > 1 - # Public: Retrieves all the cursors. + # Retrieves all the cursors. # # Returns an {Array} of {Cursor}s. getCursors: -> new Array(@cursors...) - # Public: Retrieves a single cursor + # Retrieves the most recently added cursor. # # Returns a {Cursor}. getCursor: -> _.last(@cursors) - # Public: Adds a cursor at the provided `screenPosition`. + # Adds a cursor at the provided `screenPosition`. # # screenPosition - An {Array} of two numbers: the screen row, and the screen column. # @@ -993,7 +801,7 @@ class EditSession marker = @markScreenPosition(screenPosition, invalidationStrategy: 'never') @addSelection(marker).cursor - # Public: Adds a cursor at the provided `bufferPosition`. + # Adds a cursor at the provided `bufferPosition`. # # bufferPosition - An {Array} of two numbers: the buffer row, and the buffer column. # @@ -1002,7 +810,7 @@ class EditSession marker = @markBufferPosition(bufferPosition, invalidationStrategy: 'never') @addSelection(marker).cursor - # Public: Adds a cursor to the `EditSession`. + # Adds a cursor to the `EditSession`. # # marker - The marker where the cursor should be added # @@ -1013,7 +821,7 @@ class EditSession @trigger 'cursor-added', cursor cursor - # Public: Removes a cursor from the `EditSession`. + # Removes a cursor from the `EditSession`. # # cursor - The cursor to remove # @@ -1021,7 +829,7 @@ class EditSession removeCursor: (cursor) -> _.remove(@cursors, cursor) - # Public: Creates a new selection at the given marker. + # Creates a new selection at the given marker. # # marker - The marker to highlight # options - A hash of options that pertain to the {Selection} constructor. @@ -1043,7 +851,7 @@ class EditSession @trigger 'selection-added', selection selection - # Public: Given a buffer range, this adds a new selection for it. + # Given a buffer range, this adds a new selection for it. # # bufferRange - A {Range} in the buffer # options - A hash of options @@ -1054,14 +862,14 @@ class EditSession marker = @markBufferRange(bufferRange, options) @addSelection(marker, options) - # Public: Given a buffer range, this removes all previous selections and creates a new selection for it. + # Given a buffer range, this removes all previous selections and creates a new selection for it. # # bufferRange - A {Range} in the buffer # options - A hash of options setSelectedBufferRange: (bufferRange, options) -> @setSelectedBufferRanges([bufferRange], options) - # Public: Given an array of buffer ranges, this removes all previous selections and creates new selections for them. + # Given an array of buffer ranges, this removes all previous selections and creates new selections for them. # # bufferRanges - An {Array} of {Range}s in the buffer # options - A hash of options @@ -1079,13 +887,13 @@ class EditSession @addSelectionForBufferRange(bufferRange, options) @mergeIntersectingSelections(options) - # Public: Unselects a given selection. + # Unselects a given selection. # # selection - The {Selection} to remove. removeSelection: (selection) -> _.remove(@selections, selection) - # Public: Clears every selection. TODO + # Clears every selection. TODO clearSelections: -> @consolidateSelections() @getSelection().clear() @@ -1098,12 +906,12 @@ class EditSession else false - # Public: Gets all the selections. + # Gets all the selections. # # Returns an {Array} of {Selection}s. getSelections: -> new Array(@selections...) - # Public: Gets the selection at the specified index. + # Gets the selection at the specified index. # # index - The id {Number} of the selection # @@ -1112,13 +920,13 @@ class EditSession index ?= @selections.length - 1 @selections[index] - # Public: Gets the last selection, _i.e._ the most recently added. + # Gets the last selection, _i.e._ the most recently added. # # Returns a {Selection}. getLastSelection: -> _.last(@selections) - # Public: Gets all selections, ordered by their position in the buffer. + # Gets all selections, ordered by their position in the buffer. # # Returns an {Array} of {Selection}s. getSelectionsOrderedByBufferPosition: -> @@ -1127,13 +935,13 @@ class EditSession bRange = b.getBufferRange() aRange.end.compare(bRange.end) - # Public: Gets the very last selection, as it's ordered in the buffer. + # Gets the very last selection, as it's ordered in the buffer. # # Returns a {Selection}. getLastSelectionInBuffer: -> _.last(@getSelectionsOrderedByBufferPosition()) - # Public: Determines if a given buffer range is included in a selection. + # Determines if a given buffer range is included in a {Selection}. # # bufferRange - The {Range} you're checking against # @@ -1142,7 +950,7 @@ class EditSession _.any @getSelections(), (selection) -> selection.intersectsBufferRange(bufferRange) - # Public: Moves every cursor to a given screen position. + # Moves every cursor to a given screen position. # # position - An {Array} of two numbers: the screen row, and the screen column. # options - An object with properties based on {Cursor.setScreenPosition} @@ -1150,19 +958,19 @@ class EditSession setCursorScreenPosition: (position, options) -> @moveCursors (cursor) -> cursor.setScreenPosition(position, options) - # Public: Gets the current screen position. + # Gets the current screen position of the most recently added {Cursor}. # # Returns an {Array} of two numbers: the screen row, and the screen column. getCursorScreenPosition: -> @getCursor().getScreenPosition() - # Public: Gets the current cursor's screen row. + # Gets the screen row of the most recently added {Cursor}. # - # Returns the screen row. + # Returns the screen row {Number}. getCursorScreenRow: -> @getCursor().getScreenRow() - # Public: Moves every cursor to a given buffer position. + # Moves every cursor to a given buffer position. # # position - An {Array} of two numbers: the buffer row, and the buffer column. # options - An object with properties based on {Cursor.setBufferPosition} @@ -1170,39 +978,39 @@ class EditSession setCursorBufferPosition: (position, options) -> @moveCursors (cursor) -> cursor.setBufferPosition(position, options) - # Public: Gets the current buffer position of the cursor. + # Gets the current buffer position of the most recently added {Cursor}. # # Returns an {Array} of two numbers: the buffer row, and the buffer column. getCursorBufferPosition: -> @getCursor().getBufferPosition() - # Public: Gets the screen range of the most recently added {Selection}. + # Gets the screen range of the most recently added {Selection}. # # Returns a {Range}. getSelectedScreenRange: -> @getLastSelection().getScreenRange() - # Public: Gets the buffer range of the most recently added {Selection}. + # Gets the buffer range of the most recently added {Selection}. # # Returns a {Range}. getSelectedBufferRange: -> @getLastSelection().getBufferRange() - # Public: Gets the buffer ranges of all the {Selection}s. + # Gets the buffer ranges of all the {Selection}s. # - # This is ordered by their buffer position. + # This is ordered by their position in the file itself. # # Returns an {Array} of {Range}s. getSelectedBufferRanges: -> selection.getBufferRange() for selection in @getSelectionsOrderedByBufferPosition() - # Public: Gets the currently selected text. + # Gets the selected text of the most recently added {Selection}. # # Returns a {String}. getSelectedText: -> @getLastSelection().getText() - # Public: Given a buffer range, this retrieves the text in that range. + # Given a buffer range, this retrieves the text in that range. # # range - The {Range} you're interested in # @@ -1210,7 +1018,7 @@ class EditSession getTextInBufferRange: (range) -> @buffer.getTextInRange(range) - # 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. # @@ -1218,7 +1026,7 @@ class EditSession getCurrentParagraphBufferRange: -> @getCursor().getCurrentParagraphBufferRange() - # Public: Gets the word located under the cursor. + # Gets the word located under the most recently added {Cursor}. # # options - An object with properties based on {Cursor.getBeginningOfCurrentWordBufferPosition}. # @@ -1226,51 +1034,51 @@ class EditSession getWordUnderCursor: (options) -> @getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options)) - # Public: Moves every cursor up one row. + # Moves every cursor up one row. moveCursorUp: (lineCount) -> @moveCursors (cursor) -> cursor.moveUp(lineCount) - # Public: Moves every cursor down one row. + # Moves every cursor down one row. moveCursorDown: (lineCount) -> @moveCursors (cursor) -> cursor.moveDown(lineCount) - # Public: Moves every cursor left one column. + # Moves every cursor left one column. moveCursorLeft: -> @moveCursors (cursor) -> cursor.moveLeft() - # Public: Moves every cursor right one column. + # Moves every cursor right one column. moveCursorRight: -> @moveCursors (cursor) -> cursor.moveRight() - # Public: Moves every cursor to the top of the buffer. + # Moves every cursor to the top of the buffer. moveCursorToTop: -> @moveCursors (cursor) -> cursor.moveToTop() - # Public: Moves every cursor to the bottom of the buffer. + # Moves every cursor to the bottom of the buffer. moveCursorToBottom: -> @moveCursors (cursor) -> cursor.moveToBottom() - # Public: Moves every cursor to the beginning of the line. + # Moves every cursor to the beginning of the line. moveCursorToBeginningOfLine: -> @moveCursors (cursor) -> cursor.moveToBeginningOfLine() - # Public: Moves every cursor to the first non-whitespace character of the line. + # Moves every cursor to the first non-whitespace character of the line. moveCursorToFirstCharacterOfLine: -> @moveCursors (cursor) -> cursor.moveToFirstCharacterOfLine() - # Public: Moves every cursor to the end of the line. + # Moves every cursor to the end of the line. moveCursorToEndOfLine: -> @moveCursors (cursor) -> cursor.moveToEndOfLine() - # Public: Moves every cursor to the beginning of the current word. + # Moves every cursor to the beginning of the current word. moveCursorToBeginningOfWord: -> @moveCursors (cursor) -> cursor.moveToBeginningOfWord() - # Public: Moves every cursor to the end of the current word. + # Moves every cursor to the end of the current word. moveCursorToEndOfWord: -> @moveCursors (cursor) -> cursor.moveToEndOfWord() - # Public: Moves every cursor to the beginning of the next word. + # Moves every cursor to the beginning of the next word. moveCursorToBeginningOfNextWord: -> @moveCursors (cursor) -> cursor.moveToBeginningOfNextWord() @@ -1279,7 +1087,7 @@ class EditSession fn(cursor) for cursor in @getCursors() @mergeCursors() - # 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) -> @@ -1287,55 +1095,55 @@ class EditSession lastSelection.selectToScreenPosition(position) @mergeIntersectingSelections(reverse: lastSelection.isReversed()) - # Public: Selects the text one position right of the cursor. + # Selects the text one position right of the cursor. selectRight: -> @expandSelectionsForward (selection) => selection.selectRight() - # Public: Selects the text one position left of the cursor. + # Selects the text one position left of the cursor. selectLeft: -> @expandSelectionsBackward (selection) => selection.selectLeft() - # Public: Selects all the text one position above the cursor. + # Selects all the text one position above the cursor. selectUp: -> @expandSelectionsBackward (selection) => selection.selectUp() - # Public: Selects all the text one position below the cursor. + # Selects all the text one position below the cursor. selectDown: -> @expandSelectionsForward (selection) => selection.selectDown() - # 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: -> @expandSelectionsBackward (selection) => selection.selectToTop() - # Public: Selects all the text in the buffer. + # Selects all the text in the buffer. selectAll: -> @expandSelectionsForward (selection) => selection.selectAll() - # 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: -> @expandSelectionsForward (selection) => selection.selectToBottom() - # 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: -> @expandSelectionsBackward (selection) => selection.selectToBeginningOfLine() - # 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: -> @expandSelectionsForward (selection) => selection.selectToEndOfLine() - # Public: Selects the current line. + # Selects the current line. selectLine: -> @expandSelectionsForward (selection) => selection.selectLine() - # Public: Moves the current selection down one row. + # Moves the current selection down one row. addSelectionBelow: -> @expandSelectionsForward (selection) => selection.addSelectionBelow() - # Public: Moves the current selection up one row. + # Moves the current selection up one row. addSelectionAbove: -> @expandSelectionsBackward (selection) => selection.addSelectionAbove() - # Public: Transposes the current text selections. + # Transposes the current text selections. # # This only works if there is more than one selection. Each selection is transferred # to the position of the selection after it. The last selection is transferred to the @@ -1351,15 +1159,15 @@ class EditSession else selection.insertText selection.getText().split('').reverse().join('') - # Public: Turns the current selection into upper case. + # Turns the current selection into upper case. upperCase: -> @replaceSelectedText selectWordIfEmpty:true, (text) => text.toUpperCase() - # Public: Turns the current selection into lower case. + # Turns the current selection into lower case. lowerCase: -> @replaceSelectedText selectWordIfEmpty:true, (text) => text.toLowerCase() - # Public: Joins the current line with the one below it. + # Joins the current line with the one below it. # # Multiple cursors are considered equally. If there's a selection in the editor, # all the lines are joined together. @@ -1369,19 +1177,19 @@ class EditSession expandLastSelectionOverLine: -> @getLastSelection().expandOverLine() - # 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: -> @expandSelectionsBackward (selection) => selection.selectToBeginningOfWord() - # 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: -> @expandSelectionsForward (selection) => selection.selectToEndOfWord() - # 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: -> @expandSelectionsForward (selection) => selection.selectToBeginningOfNextWord() - # Public: Selects the current word. + # Selects the current word. selectWord: -> @expandSelectionsForward (selection) => selection.selectWord() @@ -1397,7 +1205,7 @@ class EditSession @setSelectedBufferRange(range) range - # 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 # @@ -1447,28 +1255,32 @@ class EditSession @setCursorBufferPosition(cursorPosition) if cursorPosition cursorPosition = null - # Public: Retrieves the current {EditSession}'s grammar. - # - # Returns a {String} indicating the language's grammar rules. + # {Delegates to: DisplayBuffer.getGrammar} getGrammar: -> @displayBuffer.getGrammar() - # Public: Sets the current {EditSession}'s grammar. - # - # grammar - A {String} indicating the language's grammar rules. + # {Delegates to: DisplayBuffer.setGrammar} setGrammar: (grammar) -> @displayBuffer.setGrammar(grammar) - # Public: Reloads the current grammar. + # {Delegates to: DisplayBuffer.reloadGrammar} reloadGrammar: -> @displayBuffer.reloadGrammar() - # Internal: + ### Internal ### + + transact: (fn) -> @buffer.transact(fn) + + commit: -> @buffer.commit() + + abort: -> @buffer.abort() + + logScreenLines: (start, end) -> @displayBuffer.logLines(start, end) + handleGrammarChange: -> @unfoldAll() @trigger 'grammar-changed' - # Internal: getDebugSnapshot: -> [ @displayBuffer.getDebugSnapshot() diff --git a/src/app/editor-config-panel.coffee b/src/app/editor-config-panel.coffee index a350d41b5..ddebeac36 100644 --- a/src/app/editor-config-panel.coffee +++ b/src/app/editor-config-panel.coffee @@ -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:" diff --git a/src/app/editor.coffee b/src/app/editor.coffee index a718bcb85..b16c6a1d5 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -23,12 +23,11 @@ class Editor extends View autoIndent: true autoIndentOnPaste: false nonWordCharacters: "./\\()\"':,.;<>~!@#$%^&*|+=[]{}`~?-" + preferredLineLength: 80 @nextEditorId: 1 - ### - # Internal # - ### + ### Internal ### @content: (params) -> attributes = { class: @classes(params), tabindex: -1 } @@ -64,8 +63,11 @@ class Editor extends View newCursors: null newSelections: null redrawOnReattach: false + bottomPaddingInLines: 10 - # Public: The constructor for setting up an `Editor` instance. + ### Public ### + + # The constructor for setting up an `Editor` instance. # # editSessionOrOptions - Either an {EditSession}, or an object with one property, `mini`. # If `mini` is `true`, a "miniature" `EditSession` is constructed. @@ -190,484 +192,311 @@ class Editor extends View do (name, method) => @command name, (e) => method.call(this, e); false - ### - # Public # - ### - - # Public: Retrieves a single cursor - # - # Returns a {Cursor}. + # {Delegates to: EditSession.getCursor} getCursor: -> @activeEditSession.getCursor() - # Public: Retrieves an array of all the cursors. - # - # Returns a {[Cursor]}. + # {Delegates to: EditSession.getCursors} getCursors: -> @activeEditSession.getCursors() - # Public: Adds a cursor at the provided `screenPosition`. - # - # screenPosition - An {Array} of two numbers: the screen row, and the screen column. - # - # Returns the new {Cursor}. + # {Delegates to: EditSession.addCursorAtScreenPosition} addCursorAtScreenPosition: (screenPosition) -> @activeEditSession.addCursorAtScreenPosition(screenPosition) - # Public: Adds a cursor at the provided `bufferPosition`. - # - # bufferPosition - An {Array} of two numbers: the buffer row, and the buffer column. - # - # Returns the new {Cursor}. + # {Delegates to: EditSession.addCursorAtBufferPosition} addCursorAtBufferPosition: (bufferPosition) -> @activeEditSession.addCursorAtBufferPosition(bufferPosition) - # Public: Moves every cursor up one row. + # {Delegates to: EditSession.moveCursorUp} moveCursorUp: -> @activeEditSession.moveCursorUp() - # Public: Moves every cursor down one row. + # {Delegates to: EditSession.moveCursorDown} moveCursorDown: -> @activeEditSession.moveCursorDown() - # Public: Moves every cursor left one column. + # {Delegates to: EditSession.moveCursorLeft} moveCursorLeft: -> @activeEditSession.moveCursorLeft() - # Public: Moves every cursor right one column. + # {Delegates to: EditSession.moveCursorRight} moveCursorRight: -> @activeEditSession.moveCursorRight() - # Public: Moves every cursor to the beginning of the current word. + # {Delegates to: EditSession.moveCursorToBeginningOfWord} moveCursorToBeginningOfWord: -> @activeEditSession.moveCursorToBeginningOfWord() - # Public: Moves every cursor to the end of the current word. + # {Delegates to: EditSession.moveCursorToEndOfWord} moveCursorToEndOfWord: -> @activeEditSession.moveCursorToEndOfWord() - # Public: Moves the cursor to the beginning of the next word. + # {Delegates to: EditSession.moveCursorToBeginningOfNextWord} moveCursorToBeginningOfNextWord: -> @activeEditSession.moveCursorToBeginningOfNextWord() - # Public: Moves every cursor to the top of the buffer. + # {Delegates to: EditSession.moveCursorToTop} moveCursorToTop: -> @activeEditSession.moveCursorToTop() - # Public: Moves every cursor to the bottom of the buffer. + # {Delegates to: EditSession.moveCursorToBottom} moveCursorToBottom: -> @activeEditSession.moveCursorToBottom() - # Public: Moves every cursor to the beginning of the line. + # {Delegates to: EditSession.moveCursorToBeginningOfLine} moveCursorToBeginningOfLine: -> @activeEditSession.moveCursorToBeginningOfLine() - # Public: Moves every cursor to the first non-whitespace character of the line. + # {Delegates to: EditSession.moveCursorToFirstCharacterOfLine} moveCursorToFirstCharacterOfLine: -> @activeEditSession.moveCursorToFirstCharacterOfLine() - # Public: Moves every cursor to the end of the line. + # {Delegates to: EditSession.moveCursorToEndOfLine} moveCursorToEndOfLine: -> @activeEditSession.moveCursorToEndOfLine() - # Public: Moves the selected line up one row. + # {Delegates to: EditSession.moveLineUp} moveLineUp: -> @activeEditSession.moveLineUp() - # Public: Moves the selected line down one row. + # {Delegates to: EditSession.moveLineDown} moveLineDown: -> @activeEditSession.moveLineDown() - # Public: Sets the cursor based on a given screen position. - # - # position - An {Array} of two numbers: the screen row, and the screen column. - # options - An object with properties based on {Cursor.setScreenPosition}. - # + # {Delegates to: EditSession.setCursorScreenPosition} setCursorScreenPosition: (position, options) -> @activeEditSession.setCursorScreenPosition(position, options) - # Public: Duplicates the current line. - # - # If more than one cursor is present, only the most recently added one is considered. + # {Delegates to: EditSession.duplicateLine} duplicateLine: -> @activeEditSession.duplicateLine() - # Public: Joins the current line with the one below it. - # - # Multiple cursors are considered equally. If there's a selection in the editor, - # all the lines are joined together. + # {Delegates to: EditSession.joinLine} joinLine: -> @activeEditSession.joinLine() - # Public: Gets the current screen position. - # - # Returns an {Array} of two numbers: the screen row, and the screen column. + # {Delegates to: EditSession.getCursorScreenPosition} getCursorScreenPosition: -> @activeEditSession.getCursorScreenPosition() - # Public: Gets the current screen row. - # - # Returns a {Number}. + # {Delegates to: EditSession.getCursorScreenRow} getCursorScreenRow: -> @activeEditSession.getCursorScreenRow() - # Public: Sets the cursor based on a given buffer position. - # - # position - An {Array} of two numbers: the buffer row, and the buffer column. - # options - An object with properties based on {Cursor.setBufferPosition}. - # + # {Delegates to: EditSession.setCursorBufferPosition} setCursorBufferPosition: (position, options) -> @activeEditSession.setCursorBufferPosition(position, options) - # Public: Gets the current buffer position of the cursor. - # - # Returns an {Array} of two numbers: the buffer row, and the buffer column. + # {Delegates to: EditSession.getCursorBufferPosition} getCursorBufferPosition: -> @activeEditSession.getCursorBufferPosition() - # Public: Retrieves the range for the current paragraph. - # - # A paragraph is defined as a block of text surrounded by empty lines. - # - # Returns a {Range}. + # {Delegates to: EditSession.getCurrentParagraphBufferRange} getCurrentParagraphBufferRange: -> @activeEditSession.getCurrentParagraphBufferRange() - # Public: Gets the word located under the cursor. - # - # options - An object with properties based on {Cursor.getBeginningOfCurrentWordBufferPosition}. - # - # Returns a {String}. + # {Delegates to: EditSession.getWordUnderCursor} getWordUnderCursor: (options) -> @activeEditSession.getWordUnderCursor(options) - # Public: Gets the selection at the specified index. - # - # index - The id {Number} of the selection - # - # Returns a {Selection}. + # {Delegates to: EditSession.getSelection} getSelection: (index) -> @activeEditSession.getSelection(index) - # Public: Gets the last selection, _i.e._ the most recently added. - # - # Returns a {Selection}. + # {Delegates to: EditSession.getSelections} getSelections: -> @activeEditSession.getSelections() - # Public: Gets all selections, ordered by their position in the buffer. - # - # Returns an {Array} of {Selection}s. + # {Delegates to: EditSession.getSelectionsOrderedByBufferPosition} getSelectionsOrderedByBufferPosition: -> @activeEditSession.getSelectionsOrderedByBufferPosition() - # Public: Gets the very last selection, as it's ordered in the buffer. - # - # Returns a {Selection}. + # {Delegates to: EditSession.getLastSelectionInBuffer} getLastSelectionInBuffer: -> @activeEditSession.getLastSelectionInBuffer() - # Public: Gets the currently selected text. - # - # Returns a {String}. + # {Delegates to: EditSession.getSelectedText} getSelectedText: -> @activeEditSession.getSelectedText() - # Public: Gets the buffer ranges of all the {Selection}s. - # - # This is ordered by their buffer position. - # - # Returns an {Array} of {Range}s. + # {Delegates to: EditSession.getSelectedBufferRanges} getSelectedBufferRanges: -> @activeEditSession.getSelectedBufferRanges() - # Public: Gets the buffer range of the most recently added {Selection}. - # - # Returns a {Range}. + # {Delegates to: EditSession.getSelectedBufferRange} getSelectedBufferRange: -> @activeEditSession.getSelectedBufferRange() - # Public: Given a buffer range, this removes all previous selections and creates a new selection for it. - # - # bufferRange - A {Range} in the buffer - # options - A hash of options + # {Delegates to: EditSession.setSelectedBufferRange} setSelectedBufferRange: (bufferRange, options) -> @activeEditSession.setSelectedBufferRange(bufferRange, options) - # Public: Given an array of buffer ranges, this removes all previous selections and creates new selections for them. - # - # bufferRanges - An {Array} of {Range}s in the buffer - # options - A hash of options + # {Delegates to: EditSession.setSelectedBufferRanges} setSelectedBufferRanges: (bufferRanges, options) -> @activeEditSession.setSelectedBufferRanges(bufferRanges, options) - # Public: Given a buffer range, this adds a new selection for it. - # - # bufferRange - A {Range} in the buffer - # options - A hash of options - # - # Returns the new {Selection}. + # {Delegates to: EditSession.addSelectionForBufferRange} addSelectionForBufferRange: (bufferRange, options) -> @activeEditSession.addSelectionForBufferRange(bufferRange, options) - # Public: Selects the text one position right of the cursor. + # {Delegates to: EditSession.selectRight} selectRight: -> @activeEditSession.selectRight() - # Public: Selects the text one position left of the cursor. + # {Delegates to: EditSession.selectLeft} selectLeft: -> @activeEditSession.selectLeft() - # Public: Selects all the text one position above the cursor. + # {Delegates to: EditSession.selectUp} selectUp: -> @activeEditSession.selectUp() - # Public: Selects all the text one position below the cursor. + # {Delegates to: EditSession.selectDown} selectDown: -> @activeEditSession.selectDown() - # Public: Selects all the text from the current cursor position to the top of the buffer. + # {Delegates to: EditSession.selectToTop} selectToTop: -> @activeEditSession.selectToTop() - # Public: Selects all the text from the current cursor position to the bottom of the buffer. + # {Delegates to: EditSession.selectToBottom} selectToBottom: -> @activeEditSession.selectToBottom() - # Public: Selects all the text in the buffer. + # {Delegates to: EditSession.selectAll} selectAll: -> @activeEditSession.selectAll() - # Public: Selects all the text from the current cursor position to the beginning of the line. + # {Delegates to: EditSession.selectToBeginningOfLine} selectToBeginningOfLine: -> @activeEditSession.selectToBeginningOfLine() - # Public: Selects all the text from the current cursor position to the end of the line. + # {Delegates to: EditSession.selectToEndOfLine} selectToEndOfLine: -> @activeEditSession.selectToEndOfLine() - # Public: Moves the current selection down one row. + # {Delegates to: EditSession.addSelectionBelow} addSelectionBelow: -> @activeEditSession.addSelectionBelow() - # Public: Moves the current selection up one row. + # {Delegates to: EditSession.addSelectionAbove} addSelectionAbove: -> @activeEditSession.addSelectionAbove() - # Public: Selects all the text from the current cursor position to the beginning of the word. + # {Delegates to: EditSession.selectToBeginningOfWord} selectToBeginningOfWord: -> @activeEditSession.selectToBeginningOfWord() - # Public: Selects all the text from the current cursor position to the end of the word. + # {Delegates to: EditSession.selectToEndOfWord} selectToEndOfWord: -> @activeEditSession.selectToEndOfWord() - # Public: Selects all the text from the current cursor position to the beginning of the next word. + # {Delegates to: EditSession.selectToBeginningOfNextWord} selectToBeginningOfNextWord: -> @activeEditSession.selectToBeginningOfNextWord() - # Public: Selects the current word. + # {Delegates to: EditSession.selectWord} selectWord: -> @activeEditSession.selectWord() - # Public: Selects the current line. + # {Delegates to: EditSession.selectLine} selectLine: -> @activeEditSession.selectLine() - # Public: Selects the text from the current cursor position to a given position. - # - # position - An instance of {Point}, with a given `row` and `column`. + # {Delegates to: EditSession.selectToScreenPosition} selectToScreenPosition: (position) -> @activeEditSession.selectToScreenPosition(position) - # Public: Transposes the current text selections. - # - # This only works if there is more than one selection. Each selection is transferred - # to the position of the selection after it. The last selection is transferred to the - # position of the first. + + # {Delegates to: EditSession.transpose} transpose: -> @activeEditSession.transpose() - # Public: Turns the current selection into upper case. + # {Delegates to: EditSession.upperCase} upperCase: -> @activeEditSession.upperCase() - # Public: Turns the current selection into lower case. + # {Delegates to: EditSession.lowerCase} lowerCase: -> @activeEditSession.lowerCase() - # Public: Clears every selection. TODO + # {Delegates to: EditSession.clearSelections} clearSelections: -> @activeEditSession.clearSelections() - # Public: Performs a backspace, removing the character found behind the cursor position. + # {Delegates to: EditSession.backspace} backspace: -> @activeEditSession.backspace() - # Public: Performs a backspace to the beginning of the current word, removing characters found there. + # {Delegates to: EditSession.backspaceToBeginningOfWord} backspaceToBeginningOfWord: -> @activeEditSession.backspaceToBeginningOfWord() - # Public: Performs a backspace to the beginning of the current line, removing characters found there. + # {Delegates to: EditSession.backspaceToBeginningOfLine} backspaceToBeginningOfLine: -> @activeEditSession.backspaceToBeginningOfLine() - # Public: Performs a delete, removing the character found ahead the cursor position. + # {Delegates to: EditSession.delete} delete: -> @activeEditSession.delete() - # Public: Performs a delete to the end of the current word, removing characters found there. + # {Delegates to: EditSession.deleteToEndOfWord} deleteToEndOfWord: -> @activeEditSession.deleteToEndOfWord() - # Public: Performs a delete to the end of the current line, removing characters found there. + # {Delegates to: EditSession.deleteLine} deleteLine: -> @activeEditSession.deleteLine() - # Public: Performs a cut to the end of the current line. - # - # Characters are removed, but the text remains in the clipboard. + # {Delegates to: EditSession.cutToEndOfLine} cutToEndOfLine: -> @activeEditSession.cutToEndOfLine() - # Public: Inserts text at the current cursor positions. - # - # text - A {String} representing the text to insert. - # options - A set of options equivalent to {Selection.insertText}. + # {Delegates to: EditSession.insertText} insertText: (text, options) -> @activeEditSession.insertText(text, options) - # Public: Inserts a new line at the current cursor positions. + # {Delegates to: EditSession.insertNewline} insertNewline: -> @activeEditSession.insertNewline() - # Internal: - - consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections() - - # Public: Inserts a new line below the current cursor positions. + # {Delegates to: EditSession.insertNewlineBelow} insertNewlineBelow: -> @activeEditSession.insertNewlineBelow() - # Public: Inserts a new line above the current cursor positions. + # {Delegates to: EditSession.insertNewlineAbove} insertNewlineAbove: -> @activeEditSession.insertNewlineAbove() - # Public: Indents the current line. - # - # options - A set of options equivalent to {Selection.indent}. + # {Delegates to: EditSession.indent} indent: (options) -> @activeEditSession.indent(options) - # Public: TODO + # {Delegates to: EditSession.autoIndentSelectedRows} autoIndent: (options) -> @activeEditSession.autoIndentSelectedRows() - # Public: Indents the selected rows. + # {Delegates to: EditSession.indentSelectedRows} indentSelectedRows: -> @activeEditSession.indentSelectedRows() - # Public: Outdents the selected rows. + # {Delegates to: EditSession.outdentSelectedRows} outdentSelectedRows: -> @activeEditSession.outdentSelectedRows() - # Public: Cuts the selected text. + # {Delegates to: EditSession.cutSelectedText} cutSelection: -> @activeEditSession.cutSelectedText() - # Public: Copies the selected text. + # {Delegates to: EditSession.copySelectedText} copySelection: -> @activeEditSession.copySelectedText() - # Public: Pastes the text in the clipboard. - # - # options - A set of options equivalent to {Selection.insertText}. + # {Delegates to: EditSession.pasteText} paste: (options) -> @activeEditSession.pasteText(options) - # Public: Undos the last {Buffer} change. + # {Delegates to: EditSession.undo} undo: -> @activeEditSession.undo() - # Public: Redos the last {Buffer} change. + # {Delegates to: EditSession.redo} redo: -> @activeEditSession.redo() - # Public: Creates a new fold between two row numbers. - # - # startRow - The row {Number} to start folding at - # endRow - The row {Number} to end the fold - # - # Returns the new {Fold}. + # {Delegates to: EditSession.createFold} createFold: (startRow, endRow) -> @activeEditSession.createFold(startRow, endRow) - # Public: Folds the current row. + # {Delegates to: EditSession.foldCurrentRow} foldCurrentRow: -> @activeEditSession.foldCurrentRow() - # Public: Unfolds the current row. + # {Delegates to: EditSession.unfoldCurrentRow} unfoldCurrentRow: -> @activeEditSession.unfoldCurrentRow() - # Public: Folds all the rows. + # {Delegates to: EditSession.foldAll} foldAll: -> @activeEditSession.foldAll() - # Public: Unfolds all the rows. + # {Delegates to: EditSession.unfoldAll} unfoldAll: -> @activeEditSession.unfoldAll() - # Public: Folds the most recent selection. + # {Delegates to: EditSession.foldSelection} foldSelection: -> @activeEditSession.foldSelection() - # Public: Given the id of a {Fold}, this removes it. - # - # foldId - The fold id {Number} to remove - destroyFold: (foldId) -> @activeEditSession.destroyFold(foldId) - - # Public: Removes any {Fold}s found that contain the given buffer row. - # - # bufferRow - The buffer row {Number} to check against + # {Delegates to: EditSession.destroyFoldsContainingBufferRow} destroyFoldsContainingBufferRow: (bufferRow) -> @activeEditSession.destroyFoldsContainingBufferRow(bufferRow) - # Public: Determines if the given screen row is folded. - # - # screenRow - A {Number} indicating the screen row. - # - # Returns `true` if the screen row is folded, `false` otherwise. + # {Delegates to: EditSession.isFoldedAtScreenRow} isFoldedAtScreenRow: (screenRow) -> @activeEditSession.isFoldedAtScreenRow(screenRow) - # Public: Determines if the given buffer row is folded. - # - # screenRow - A {Number} indicating the buffer row. - # - # Returns `true` if the buffer row is folded, `false` otherwise. + # {Delegates to: EditSession.isFoldedAtBufferRow} isFoldedAtBufferRow: (bufferRow) -> @activeEditSession.isFoldedAtBufferRow(bufferRow) - # Public: Determines if the given row that the cursor is at is folded. - # - # Returns `true` if the row is folded, `false` otherwise. + # {Delegates to: EditSession.isFoldedAtCursorRow} isFoldedAtCursorRow: -> @activeEditSession.isFoldedAtCursorRow() - # Public: Gets the line for the given screen row. - # - # screenRow - A {Number} indicating the screen row. - # - # Returns a {String}. + # {Delegates to: EditSession.lineForScreenRow} lineForScreenRow: (screenRow) -> @activeEditSession.lineForScreenRow(screenRow) - # Public: Gets the lines for the given screen row boundaries. - # - # start - A {Number} indicating the beginning screen row. - # end - A {Number} indicating the ending screen row. - # - # Returns an {Array} of {String}s. + # {Delegates to: EditSession.linesForScreenRows} linesForScreenRows: (start, end) -> @activeEditSession.linesForScreenRows(start, end) - # Public: Gets the number of screen rows. - # - # Returns a {Number}. + # {Delegates to: EditSession.getScreenLineCount} getScreenLineCount: -> @activeEditSession.getScreenLineCount() - # Public: Defines the limit at which the buffer begins to soft wrap text. - # - # softWrapColumn - A {Number} defining the soft wrap limit + # {Delegates to: EditSession.setSoftWrapColumn} setSoftWrapColumn: (softWrapColumn) -> softWrapColumn ?= @calcSoftWrapColumn() @activeEditSession.setSoftWrapColumn(softWrapColumn) if softWrapColumn - # Public: Gets the length of the longest screen line. - # - # Returns a {Number}. + # {Delegates to: EditSession.maxScreenLineLength} maxScreenLineLength: -> @activeEditSession.maxScreenLineLength() - # Public: Gets the text in the last screen row. - # - # Returns a {String}. + # {Delegates to: EditSession.getLastScreenRow} getLastScreenRow: -> @activeEditSession.getLastScreenRow() - # Public: 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 - # to a real position. - # - # 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 - # - # Returns the new, clipped {Point}. Note that this could be the same as `position` if no clipping was performed. + # {Delegates to: EditSession.clipScreenPosition} clipScreenPosition: (screenPosition, options={}) -> @activeEditSession.clipScreenPosition(screenPosition, options) - # Public: 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 - The same options available to {DisplayBuffer.screenPositionForBufferPosition}. - # - # Returns a {Point}. + # {Delegates to: EditSession.screenPositionForBufferPosition} screenPositionForBufferPosition: (position, options) -> @activeEditSession.screenPositionForBufferPosition(position, options) - # Public: 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 - The same options available to {DisplayBuffer.bufferPositionForScreenPosition}. - # - # Returns a {Point}. + # {Delegates to: EditSession.bufferPositionForScreenPosition} bufferPositionForScreenPosition: (position, options) -> @activeEditSession.bufferPositionForScreenPosition(position, options) - # Public: Given a buffer range, this converts it into a screen position. - # - # bufferRange - The {Range} to convert - # - # Returns a {Range}. + # {Delegates to: EditSession.screenRangeForBufferRange} screenRangeForBufferRange: (range) -> @activeEditSession.screenRangeForBufferRange(range) - # Public: Given a screen range, this converts it into a buffer position. - # - # screenRange - The {Range} to convert - # - # Returns a {Range}. + # {Delegates to: EditSession.bufferRangeForScreenRange} bufferRangeForScreenRange: (range) -> @activeEditSession.bufferRangeForScreenRange(range) - # Public: Given a starting and ending row, this converts every row into a buffer position. - # - # startRow - The row {Number} to start at - # endRow - The row {Number} to end at (default: {.getLastScreenRow}) - # - # Returns an {Array} of {Range}s. + # {Delegates to: EditSession.bufferRowsForScreenRows} bufferRowsForScreenRows: (startRow, endRow) -> @activeEditSession.bufferRowsForScreenRows(startRow, endRow) - # Public: Gets the number of the last row in the buffer. - # - # Returns a {Number}. + # {Delegates to: EditSession.getLastScreenRow} getLastScreenRow: -> @activeEditSession.getLastScreenRow() - # Internal: - - logCursorScope: -> - console.log @activeEditSession.getCursorScopes() - # Public: Emulates the "page down" key, where the last row of a buffer scrolls to become the first. pageDown: -> newScrollTop = @scrollTop() + @scrollView[0].clientHeight @@ -680,13 +509,13 @@ class Editor extends View @activeEditSession.moveCursorUp(@getPageRows()) @scrollTop(newScrollTop, adjustVerticalScrollbar: true) - # Public: Gets the number of actual page rows existing in an editor. + # Gets the number of actual page rows existing in an editor. # # Returns a {Number}. getPageRows: -> Math.max(1, Math.ceil(@scrollView[0].clientHeight / @lineHeight)) - # Public: Set whether invisible characters are shown. + # Set whether invisible characters are shown. # # showInvisibles - A {Boolean} which, if `true`, show invisible characters setShowInvisibles: (showInvisibles) -> @@ -694,13 +523,13 @@ class Editor extends View @showInvisibles = showInvisibles @resetDisplay() - # Public: Defines which characters are invisible. + # Defines which characters are invisible. # # invisibles - A hash defining the invisible characters: The defaults are: - # :eol - `\u00ac` - # :space - `\u00b7` - # :tab - `\u00bb` - # :cr - `\u00a4` + # eol: `\u00ac` + # space: `\u00b7` + # tab: `\u00bb` + # cr: `\u00a4` setInvisibles: (@invisibles={}) -> _.defaults @invisibles, eol: '\u00ac' @@ -709,7 +538,7 @@ class Editor extends View cr: '\u00a4' @resetDisplay() - # Public: Sets whether you want to show the indentation guides. + # Sets whether you want to show the indentation guides. # # showIndentGuide - A {Boolean} you can set to `true` if you want to see the indentation guides. setShowIndentGuide: (showIndentGuide) -> @@ -717,86 +546,46 @@ class Editor extends View @showIndentGuide = showIndentGuide @resetDisplay() - # Public: Checks out the current HEAD revision of the file. + # {Delegates to: Buffer.checkoutHead} checkoutHead: -> @getBuffer().checkoutHead() - # Public: Replaces the current buffer contents. - # - # text - A {String} containing the new buffer contents. + # {Delegates to: EditSession.setText} setText: (text) -> @activeEditSession.setText(text) - # Public: Retrieves the current buffer contents. - # - # Returns a {String}. + # {Delegates to: EditSession.getText} getText: -> @activeEditSession.getText() - # Public: Retrieves the current buffer's file path. - # - # Returns a {String}. + # {Delegates to: EditSession.getPath} getPath: -> @activeEditSession?.getPath() - # Public: Gets the number of lines in a file. - # - # Returns a {Number}. + # {Delegates to: Buffer.getLineCount} getLineCount: -> @getBuffer().getLineCount() - # Public: Gets the row number of the last line. - # - # Returns a {Number}. + # {Delegates to: Buffer.getLastRow} getLastBufferRow: -> @getBuffer().getLastRow() - # Public: Given a range, returns the lines of text within it. - # - # range - A {Range} object specifying your points of interest - # - # Returns a {String} of the combined lines. + # {Delegates to: Buffer.getTextInRange} getTextInRange: (range) -> @getBuffer().getTextInRange(range) - # Public: Finds the last point in the current buffer. - # - # Returns a {Point} representing the last position. + # {Delegates to: Buffer.getEofPosition} getEofPosition: -> @getBuffer().getEofPosition() - # Public: Given a row, returns the line of text. - # - # row - A {Number} indicating the row. - # - # Returns a {String}. + # {Delegates to: Buffer.lineForRow} lineForBufferRow: (row) -> @getBuffer().lineForRow(row) - # Public: Given a row, returns the length of the line of text. - # - # row - A {Number} indicating the row - # - # Returns a {Number}. + # {Delegates to: Buffer.lineLengthForRow} lineLengthForBufferRow: (row) -> @getBuffer().lineLengthForRow(row) - # Public: 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 - # want to include the trailing newline - # - # Returns a {Range}. + # {Delegates to: Buffer.rangeForRow} rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row) - # Public: Scans for text in the buffer, calling a function on each match. - # - # regex - A {RegExp} representing the text to find - # range - A {Range} in the buffer to search within - # iterator - A {Function} that's called on each match + # {Delegates to: Buffer.scanInRange} scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...) - # Public: Scans for text in the buffer _backwards_, calling a function on each match. - # - # regex - A {RegExp} representing the text to find - # range - A {Range} in the buffer to search within - # iterator - A {Function} that's called on each match + # {Delegates to: Buffer.backwardsScanInRange} backwardsScanInBufferRange: (args...) -> @getBuffer().backwardsScanInRange(args...) - ### - # Internal # - ### + ### Internal ### configure: -> @observeConfig 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers) @@ -819,13 +608,9 @@ class Editor extends View @isFocused = false @removeClass 'is-focused' - @underlayer.on 'click', (e) => - return unless e.target is @underlayer[0] - return unless e.offsetY > @overlayer.height() - if e.shiftKey - @selectToBottom() - else - @moveCursorToBottom() + @underlayer.on 'mousedown', (e) => + @renderedLines.trigger(e) + false if @isFocused @overlayer.on 'mousedown', (e) => @overlayer.hide() @@ -839,7 +624,7 @@ class Editor extends View @destroyFold($(e.currentTarget).attr('fold-id')) false - onMouseDown = (e) => + @renderedLines.on 'mousedown', (e) => clickCount = e.originalEvent.detail screenPosition = @screenPositionFromMouseEvent(e) @@ -857,8 +642,6 @@ class Editor extends View @selectOnMousemoveUntilMouseup() unless e.ctrlKey or e.originalEvent.which > 1 - @renderedLines.on 'mousedown', onMouseDown - @on "textInput", (e) => @insertText(e.originalEvent.data) false @@ -989,26 +772,24 @@ class Editor extends View else @scrollTop() + @scrollView.height() - ### - # Public # - ### + ### Public ### - # Public: Retrieves the {EditSession}'s buffer. + # Retrieves the {EditSession}'s buffer. # # Returns the current {Buffer}. getBuffer: -> @activeEditSession.buffer - # Public: Scrolls the editor to the bottom. + # Scrolls the editor to the bottom. scrollToBottom: -> @scrollBottom(@getScreenLineCount() * @lineHeight) - # Public: Scrolls the editor to the position of the most recently added cursor. + # Scrolls the editor to the position of the most recently added cursor. # # The editor is also centered. scrollToCursorPosition: -> @scrollToBufferPosition(@getCursorBufferPosition(), center: true) - # Public: Scrolls the editor to the given buffer position. + # Scrolls the editor to the given buffer position. # # bufferPosition - An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} @@ -1016,7 +797,7 @@ class Editor extends View scrollToBufferPosition: (bufferPosition, options) -> @scrollToPixelPosition(@pixelPositionForBufferPosition(bufferPosition), options) - # Public: Scrolls the editor to the given screen position. + # Scrolls the editor to the given screen position. # # screenPosition - An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} @@ -1024,55 +805,18 @@ class Editor extends View scrollToScreenPosition: (screenPosition, options) -> @scrollToPixelPosition(@pixelPositionForScreenPosition(screenPosition), options) - # Public: Scrolls the editor to the given pixel position. + # Scrolls the editor to the given pixel position. # # pixelPosition - An object that represents a pixel position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} # options - A hash with the following keys: - # :center - if `true`, the position is scrolled such that it's in the center of the editor + # center: if `true`, the position is scrolled such that it's in the center of the editor scrollToPixelPosition: (pixelPosition, options) -> return unless @attached @scrollVertically(pixelPosition, options) @scrollHorizontally(pixelPosition) - # Internal: Scrolls the editor vertically to a given position. - scrollVertically: (pixelPosition, {center}={}) -> - scrollViewHeight = @scrollView.height() - scrollTop = @scrollTop() - scrollBottom = scrollTop + scrollViewHeight - - if center - unless scrollTop < pixelPosition.top < scrollBottom - @scrollTop(pixelPosition.top - (scrollViewHeight / 2)) - else - linesInView = @scrollView.height() / @lineHeight - maxScrollMargin = Math.floor((linesInView - 1) / 2) - scrollMargin = Math.min(@vScrollMargin, maxScrollMargin) - margin = scrollMargin * @lineHeight - desiredTop = pixelPosition.top - margin - desiredBottom = pixelPosition.top + @lineHeight + margin - if desiredBottom > scrollBottom - @scrollTop(desiredBottom - scrollViewHeight) - else if desiredTop < scrollTop - @scrollTop(desiredTop) - - # Internal: Scrolls the editor horizontally to a given position. - scrollHorizontally: (pixelPosition) -> - return if @activeEditSession.getSoftWrap() - - charsInView = @scrollView.width() / @charWidth - maxScrollMargin = Math.floor((charsInView - 1) / 2) - scrollMargin = Math.min(@hScrollMargin, maxScrollMargin) - margin = scrollMargin * @charWidth - desiredRight = pixelPosition.left + @charWidth + margin - desiredLeft = pixelPosition.left - margin - - if desiredRight > @scrollView.scrollRight() - @scrollView.scrollRight(desiredRight) - else if desiredLeft < @scrollView.scrollLeft() - @scrollView.scrollLeft(desiredLeft) - - # Public: Given a buffer range, this highlights all the folds within that range + # Given a buffer range, this highlights all the folds within that range # # "Highlighting" essentially just adds the `selected` class to the line # @@ -1097,11 +841,11 @@ class Editor extends View @activeEditSession.setScrollTop(@scrollTop()) @activeEditSession.setScrollLeft(@scrollView.scrollLeft()) - # Public: Activates soft tabs in the editor. + # {Delegates to: EditSession.setSoftTabs} toggleSoftTabs: -> @activeEditSession.setSoftTabs(not @activeEditSession.softTabs) - # Public: Activates soft wraps in the editor. + # Activates soft wraps in the editor. toggleSoftWrap: -> @setSoftWrap(not @activeEditSession.getSoftWrap()) @@ -1111,7 +855,7 @@ class Editor extends View else Infinity - # Public: Sets the soft wrap column for the editor. + # Sets the soft wrap column for the editor. # # softWrap - A {Boolean} which, if `true`, sets soft wraps # softWrapColumn - A {Number} indicating the length of a line in the editor when soft @@ -1128,7 +872,7 @@ class Editor extends View @removeClass 'soft-wrap' $(window).off 'resize', @_setSoftWrapColumn - # Public: Sets the font size for the editor. + # Sets the font size for the editor. # # fontSize - A {Number} indicating the font size in pixels. setFontSize: (fontSize) -> @@ -1145,13 +889,13 @@ class Editor extends View else @redrawOnReattach = @attached - # Public: Retrieves the font size for the editor. + # Retrieves the font size for the editor. # # Returns a {Number} indicating the font size in pixels. getFontSize: -> parseInt(@css("font-size")) - # Public: Sets the font family for the editor. + # Sets the font family for the editor. # # fontFamily - A {String} identifying the CSS `font-family`, setFontFamily: (fontFamily) -> @@ -1168,16 +912,16 @@ class Editor extends View @redraw() - # Public: Gets the font family for the editor. + # Gets the font family for the editor. # # Returns a {String} identifying the CSS `font-family`, getFontFamily: -> @css("font-family") - # Public: Clears the CSS `font-family` property from the editor. + # Clears the CSS `font-family` property from the editor. clearFontFamily: -> $('head style.editor-font-family').remove() - # Public: Clears the CSS `font-family` property from the editor. + # Clears the CSS `font-family` property from the editor. redraw: -> return unless @hasParent() return unless @attached @@ -1199,7 +943,7 @@ class Editor extends View splitDown: (items...) -> @getPane()?.splitDown(items...).activeView - # Public: Retrieve's the `Editor`'s pane. + # Retrieve's the `Editor`'s pane. # # Returns a {Pane}. getPane: -> @@ -1256,9 +1000,45 @@ class Editor extends View appendToLinesView: (view) -> @overlayer.append(view) - ### - # Internal # - ### + ### Internal ### + + + # Scrolls the editor vertically to a given position. + scrollVertically: (pixelPosition, {center}={}) -> + scrollViewHeight = @scrollView.height() + scrollTop = @scrollTop() + scrollBottom = scrollTop + scrollViewHeight + + if center + unless scrollTop < pixelPosition.top < scrollBottom + @scrollTop(pixelPosition.top - (scrollViewHeight / 2)) + else + linesInView = @scrollView.height() / @lineHeight + maxScrollMargin = Math.floor((linesInView - 1) / 2) + scrollMargin = Math.min(@vScrollMargin, maxScrollMargin) + margin = scrollMargin * @lineHeight + desiredTop = pixelPosition.top - margin + desiredBottom = pixelPosition.top + @lineHeight + margin + if desiredBottom > scrollBottom + @scrollTop(desiredBottom - scrollViewHeight) + else if desiredTop < scrollTop + @scrollTop(desiredTop) + + # Scrolls the editor horizontally to a given position. + scrollHorizontally: (pixelPosition) -> + return if @activeEditSession.getSoftWrap() + + charsInView = @scrollView.width() / @charWidth + maxScrollMargin = Math.floor((charsInView - 1) / 2) + scrollMargin = Math.min(@hScrollMargin, maxScrollMargin) + margin = scrollMargin * @charWidth + desiredRight = pixelPosition.left + @charWidth + margin + desiredLeft = pixelPosition.left - margin + + if desiredRight > @scrollView.scrollRight() + @scrollView.scrollRight(desiredRight) + else if desiredLeft < @scrollView.scrollLeft() + @scrollView.scrollLeft(desiredLeft) calculateDimensions: -> fragment = $('') @@ -1274,12 +1054,11 @@ class Editor extends View updateLayerDimensions: -> height = @lineHeight * @getScreenLineCount() unless @layerHeight == height - @renderedLines.height(height) - @underlayer.css('min-height', height) - @overlayer.height(height) @layerHeight = height - - @verticalScrollbarContent.height(height) + @underlayer.height(@layerHeight) + @renderedLines.height(@layerHeight) + @overlayer.height(@layerHeight) + @verticalScrollbarContent.height(@layerHeight) @scrollBottom(height) if @scrollBottom() > height minWidth = @charWidth * @maxScreenLineLength() + 20 @@ -1501,23 +1280,22 @@ class Editor extends View @renderedLines.css('padding-bottom', paddingBottom) @gutter.lineNumbers.css('padding-bottom', paddingBottom) - ### - # Public # - ### + ### Public ### - # Public: Retrieves the number of the row that is visible and currently at the top of the editor. + # Retrieves the number of the row that is visible and currently at the top of the editor. # # Returns a {Number}. getFirstVisibleScreenRow: -> Math.floor(@scrollTop() / @lineHeight) - # Public: Retrieves the number of the row that is visible and currently at the top of the editor. + # Retrieves the number of the row that is visible and currently at the top of the editor. # # Returns a {Number}. getLastVisibleScreenRow: -> - Math.max(0, Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1) + calculatedRow = Math.ceil((@scrollTop() + @scrollView.height()) / @lineHeight) - 1 + Math.max(0, Math.min(@getScreenLineCount() - 1, calculatedRow)) - # Public: Given a row number, identifies if it is currently visible. + # Given a row number, identifies if it is currently visible. # # row - A row {Number} to check # @@ -1525,9 +1303,7 @@ class Editor extends View isScreenRowVisible: (row) -> @getFirstVisibleScreenRow() <= row <= @getLastVisibleScreenRow() - ### - # Internal # - ### + ### Internal ### handleScreenLinesChange: (change) -> @pendingChanges.push(change) @@ -1549,7 +1325,22 @@ class Editor extends View htmlLines.push(@buildLineHtml(line, screenRow++)) htmlLines.join('\n\n') - buildEmptyLineHtml: (screenRow) -> + buildEndOfLineInvisibles: (screenLine) -> + invisibles = [] + for invisible in @getEndOfLineInvisibles(screenLine) + invisibles.push("#{invisible}") + invisibles.join('') + + getEndOfLineInvisibles: (screenLine) -> + return [] unless @showInvisibles and @invisibles + return [] if @mini or screenLine.isSoftWrapped() + + invisibles = [] + invisibles.push(@invisibles.cr) if @invisibles.cr and screenLine.lineEnding is '\r\n' + invisibles.push(@invisibles.eol) if @invisibles.eol + invisibles + + buildEmptyLineHtml: (screenLine, screenRow) -> if not @mini and @showIndentGuide indentation = 0 while --screenRow >= 0 @@ -1560,10 +1351,28 @@ class Editor extends View break if indentation > 0 - indentationHtml = "#{_.multiplyString(' ', @activeEditSession.getTabLength())}" - return _.multiplyString(indentationHtml, indentation) + tabLength = @activeEditSession.getTabLength() + invisibles = @getEndOfLineInvisibles(screenLine) + indentGuideHtml = [] + for level in [0...indentation] + indentLevelHtml = [""] + for characterPosition in [0...tabLength] + if invisible = invisibles.shift() + indentLevelHtml.push("#{invisible}") + else + indentLevelHtml.push(' ') + indentLevelHtml.push("") + indentGuideHtml.push(indentLevelHtml.join('')) - return ' ' unless @showInvisibles + for invisible in invisibles + indentGuideHtml.push("#{invisible}") + return indentGuideHtml.join('') + + invisibles = @buildEndOfLineInvisibles(screenLine) + if invisibles.length > 0 + invisibles + else + ' ' buildLineHtml: (screenLine, screenRow) -> scopeStack = [] @@ -1602,7 +1411,7 @@ class Editor extends View invisibles = @invisibles if @showInvisibles if screenLine.text == '' - html = @buildEmptyLineHtml(screenRow) + html = @buildEmptyLineHtml(screenLine, screenRow) line.push(html) if html else firstNonWhitespacePosition = screenLine.text.search(/\S/) @@ -1618,12 +1427,7 @@ class Editor extends View position += token.value.length popScope() while scopeStack.length > 0 - if invisibles and not @mini and not screenLine.isSoftWrapped() - if invisibles.cr and screenLine.lineEnding is '\r\n' - line.push("#{invisibles.cr}") - if invisibles.eol - line.push("#{invisibles.eol}") - + line.push(@buildEndOfLineInvisibles(screenLine)) unless screenLine.text == '' line.push("") if fold line.push('') @@ -1635,11 +1439,9 @@ class Editor extends View toggleLineCommentsInSelection: -> @activeEditSession.toggleLineCommentsInSelection() - ### - # Public # - ### + ### Public ### - # Public: Converts a buffer position to a pixel position. + # Converts a buffer position to a pixel position. # # position - An object that represents a buffer position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} @@ -1648,7 +1450,7 @@ class Editor extends View pixelPositionForBufferPosition: (position) -> @pixelPositionForScreenPosition(@screenPositionForBufferPosition(position)) - # Public: Converts a screen position to a pixel position. + # Converts a screen position to a pixel position. # # position - An object that represents a screen position. It can be either # an {Object} (`{row, column}`), {Array} (`[row, column]`), or {Point} @@ -1719,7 +1521,7 @@ class Editor extends View new Point(row, column) - # Public: Highlights the current line the cursor is on. + # Highlights the current line the cursor is on. highlightCursorLine: -> return if @mini @@ -1730,23 +1532,26 @@ class Editor extends View else @highlightedLine = null - # Public: Retrieves the current {EditSession}'s grammar. - # - # Returns a {String} indicating the language's grammar rules. + # {Delegates to: EditSession.getGrammar} getGrammar: -> @activeEditSession.getGrammar() - # Public: Sets the current {EditSession}'s grammar. This only works for mini-editors. - # - # grammar - A {String} indicating the language's grammar rules. + # {Delegates to: EditSession.setGrammar} setGrammar: (grammar) -> throw new Error("Only mini-editors can explicity set their grammar") unless @mini @activeEditSession.setGrammar(grammar) - # Public: Reloads the current grammar. + # {Delegates to: EditSession.reloadGrammar} reloadGrammar: -> @activeEditSession.reloadGrammar() + # Copies the current file path to the native clipboard. + copyPathToPasteboard: -> + path = @getPath() + pasteboard.write(path) if path? + + ### Internal ### + bindToKeyedEvent: (key, event, callback) -> binding = {} binding[key] = event @@ -1754,7 +1559,6 @@ class Editor extends View @on event, => callback(this, event) - # Internal: Replaces all the currently selected text. replaceSelectedText: (replaceFn) -> selection = @getSelection() return false if selection.isEmpty() @@ -1765,14 +1569,10 @@ class Editor extends View @insertText(text, select: true) true - # Public: Copies the current file path to the native clipboard. - copyPathToPasteboard: -> - path = @getPath() - pasteboard.write(path) if path? + consolidateSelections: (e) -> e.abortKeyBinding() unless @activeEditSession.consolidateSelections() - ### - # Internal # - ### + logCursorScope: -> + console.log @activeEditSession.getCursorScopes() transact: (fn) -> @activeEditSession.transact(fn) commit: -> @activeEditSession.commit() diff --git a/src/app/event-emitter.coffee b/src/app/event-emitter.coffee index ad1b63a60..e50ba68ae 100644 --- a/src/app/event-emitter.coffee +++ b/src/app/event-emitter.coffee @@ -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: -> diff --git a/src/app/file.coffee b/src/app/file.coffee index 4f1782ff2..2c4afb05d 100644 --- a/src/app/file.coffee +++ b/src/app/file.coffee @@ -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 diff --git a/src/app/fold.coffee b/src/app/fold.coffee index 6d38616ae..e791a38b8 100644 --- a/src/app/fold.coffee +++ b/src/app/fold.coffee @@ -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() diff --git a/src/app/git.coffee b/src/app/git.coffee index b83aa802f..91fade3a0 100644 --- a/src/app/git.coffee +++ b/src/app/git.coffee @@ -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? diff --git a/src/app/gutter.coffee b/src/app/gutter.coffee index ff937d720..000405d6d 100644 --- a/src/app/gutter.coffee +++ b/src/app/gutter.coffee @@ -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 diff --git a/src/app/image-edit-session.coffee b/src/app/image-edit-session.coffee index 6a8ecb856..f34d77f74 100644 --- a/src/app/image-edit-session.coffee +++ b/src/app/image-edit-session.coffee @@ -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. # diff --git a/src/app/image-view.coffee b/src/app/image-view.coffee index 2a339576b..329d98bb1 100644 --- a/src/app/image-view.coffee +++ b/src/app/image-view.coffee @@ -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()) \ No newline at end of file + @setPath(imageEditSession?.getPath()) diff --git a/src/app/language-mode.coffee b/src/app/language-mode.coffee index 36afb5905..46d968ded 100644 --- a/src/app/language-mode.coffee +++ b/src/app/language-mode.coffee @@ -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) -> diff --git a/src/app/line-map.coffee b/src/app/line-map.coffee index 48a89de8e..bb79c045d 100644 --- a/src/app/line-map.coffee +++ b/src/app/line-map.coffee @@ -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 diff --git a/src/app/null-grammar.coffee b/src/app/null-grammar.coffee index 8d7079d55..54bdfe95f 100644 --- a/src/app/null-grammar.coffee +++ b/src/app/null-grammar.coffee @@ -2,9 +2,7 @@ Token = require 'token' EventEmitter = require 'event-emitter' _ = require 'underscore' -### -# Internal # -### +### Internal ### module.exports = class NullGrammar name: 'Null Grammar' diff --git a/src/app/package.coffee b/src/app/package.coffee index d4b72a446..c5e0777f8 100644 --- a/src/app/package.coffee +++ b/src/app/package.coffee @@ -1,8 +1,6 @@ fsUtils = require 'fs-utils' -### -# Internal # -### +### Internal ### module.exports = class Package @build: (path) -> diff --git a/src/app/pane-container.coffee b/src/app/pane-container.coffee index 48e506877..461d76664 100644 --- a/src/app/pane-container.coffee +++ b/src/app/pane-container.coffee @@ -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() diff --git a/src/app/pane-row.coffee b/src/app/pane-row.coffee index d1030cd68..f13e40570 100644 --- a/src/app/pane-row.coffee +++ b/src/app/pane-row.coffee @@ -2,9 +2,7 @@ $ = require 'jquery' _ = require 'underscore' PaneAxis = require 'pane-axis' -### -# Internal # -### +### Internal ### module.exports = class PaneRow extends PaneAxis diff --git a/src/app/pane.coffee b/src/app/pane.coffee index b042a66fb..e85cadd17 100644 --- a/src/app/pane.coffee +++ b/src/app/pane.coffee @@ -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) diff --git a/src/app/pasteboard.coffee b/src/app/pasteboard.coffee index 7a3384905..e940977f1 100644 --- a/src/app/pasteboard.coffee +++ b/src/app/pasteboard.coffee @@ -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. # diff --git a/src/app/point.coffee b/src/app/point.coffee index b49a3520c..cf1329e05 100644 --- a/src/app/point.coffee +++ b/src/app/point.coffee @@ -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() diff --git a/src/app/project.coffee b/src/app/project.coffee index f47a8894e..3c12330e9 100644 --- a/src/app/project.coffee +++ b/src/app/project.coffee @@ -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 diff --git a/src/app/range.coffee b/src/app/range.coffee index d4e7f2ba2..4c92d9497 100644 --- a/src/app/range.coffee +++ b/src/app/range.coffee @@ -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()}]" diff --git a/src/app/root-view.coffee b/src/app/root-view.coffee index 90407e2e2..960f9f9e6 100644 --- a/src/app/root-view.coffee +++ b/src/app/root-view.coffee @@ -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 diff --git a/src/app/screen-line.coffee b/src/app/screen-line.coffee index 99a0424fb..3bac61dcf 100644 --- a/src/app/screen-line.coffee +++ b/src/app/screen-line.coffee @@ -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 diff --git a/src/app/select-list.coffee b/src/app/select-list.coffee index e82c07598..1813cb6c3 100644 --- a/src/app/select-list.coffee +++ b/src/app/select-list.coffee @@ -6,9 +6,7 @@ fuzzyFilter = require 'fuzzy-filter' module.exports = class SelectList extends View - ### - # Internal # - ### + ### Internal ### @content: -> @div class: @viewClass(), => diff --git a/src/app/selection-view.coffee b/src/app/selection-view.coffee index 2adcf7627..bf9ccc777 100644 --- a/src/app/selection-view.coffee +++ b/src/app/selection-view.coffee @@ -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' diff --git a/src/app/selection.coffee b/src/app/selection.coffee index 6fe5c71d2..f800cddf5 100644 --- a/src/app/selection.coffee +++ b/src/app/selection.coffee @@ -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 diff --git a/src/app/syntax.coffee b/src/app/syntax.coffee index 4115c2797..a8859154e 100644 --- a/src/app/syntax.coffee +++ b/src/app/syntax.coffee @@ -6,9 +6,7 @@ fsUtils = require 'fs-utils' EventEmitter = require 'event-emitter' NullGrammar = require 'null-grammar' -### -# Internal # -### +### Internal ### module.exports = class Syntax diff --git a/src/app/text-buffer.coffee b/src/app/text-buffer.coffee index 634953083..e038a1591 100644 --- a/src/app/text-buffer.coffee +++ b/src/app/text-buffer.coffee @@ -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] diff --git a/src/app/text-mate-grammar.coffee b/src/app/text-mate-grammar.coffee index cf48323c0..d4a9016bd 100644 --- a/src/app/text-mate-grammar.coffee +++ b/src/app/text-mate-grammar.coffee @@ -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()] diff --git a/src/app/text-mate-package.coffee b/src/app/text-mate-package.coffee index 8700cbcc2..2f0efdda0 100644 --- a/src/app/text-mate-package.coffee +++ b/src/app/text-mate-package.coffee @@ -5,9 +5,7 @@ _ = require 'underscore' TextMateGrammar = require 'text-mate-grammar' async = require 'async' -### -# Internal # -### +### Internal ### module.exports = class TextMatePackage extends Package diff --git a/src/app/text-mate-scope-selector-matchers.coffee b/src/app/text-mate-scope-selector-matchers.coffee index 9cb852134..67b5310ab 100644 --- a/src/app/text-mate-scope-selector-matchers.coffee +++ b/src/app/text-mate-scope-selector-matchers.coffee @@ -1,6 +1,4 @@ -### -# Internal # -### +### Internal ### class SegmentMatcher constructor: (segment) -> diff --git a/src/app/text-mate-scope-selector.coffee b/src/app/text-mate-scope-selector.coffee index f21007015..d5713356b 100644 --- a/src/app/text-mate-scope-selector.coffee +++ b/src/app/text-mate-scope-selector.coffee @@ -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. # diff --git a/src/app/text-mate-theme.coffee b/src/app/text-mate-theme.coffee index c032ec620..f8e72512d 100644 --- a/src/app/text-mate-theme.coffee +++ b/src/app/text-mate-theme.coffee @@ -3,9 +3,7 @@ fsUtils = require 'fs-utils' plist = require 'plist' Theme = require 'theme' -### -# Internal # -### +### Internal ### module.exports = class TextMateTheme extends Theme diff --git a/src/app/theme.coffee b/src/app/theme.coffee index d6ebdff6b..b7aea0119 100644 --- a/src/app/theme.coffee +++ b/src/app/theme.coffee @@ -1,8 +1,6 @@ fsUtils = require 'fs-utils' -### -# Internal # -### +### Internal ### module.exports = class Theme diff --git a/src/app/token.coffee b/src/app/token.coffee index 01707dd2d..ca49e893b 100644 --- a/src/app/token.coffee +++ b/src/app/token.coffee @@ -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 "#{match}" 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(' ') diff --git a/src/app/tokenized-buffer.coffee b/src/app/tokenized-buffer.coffee index 876e65a51..0dd8a1254 100644 --- a/src/app/tokenized-buffer.coffee +++ b/src/app/tokenized-buffer.coffee @@ -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: -> diff --git a/src/app/window.coffee b/src/app/window.coffee index fdad3efec..ebedffe5d 100644 --- a/src/app/window.coffee +++ b/src/app/window.coffee @@ -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() diff --git a/src/packages/autoflow/autoflow.coffee b/src/packages/autoflow/autoflow.coffee index 058b9c3b5..83bf56d02 100644 --- a/src/packages/autoflow/autoflow.coffee +++ b/src/packages/autoflow/autoflow.coffee @@ -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 = [] diff --git a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee index 0080f7bbb..72b8d03b2 100644 --- a/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee +++ b/src/packages/fuzzy-finder/lib/fuzzy-finder-view.coffee @@ -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 diff --git a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee index 15035a371..f9efdf36b 100644 --- a/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee +++ b/src/packages/fuzzy-finder/spec/fuzzy-finder-spec.coffee @@ -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] = [] diff --git a/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less b/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less index 3c8a4f3f1..3371e6fcd 100644 --- a/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less +++ b/src/packages/fuzzy-finder/stylesheets/fuzzy-finder.less @@ -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"; + } + } } diff --git a/src/packages/gfm/grammars/gfm.cson b/src/packages/gfm/grammars/gfm.cson index 985e41663..91f263a57 100644 --- a/src/packages/gfm/grammars/gfm.cson +++ b/src/packages/gfm/grammars/gfm.cson @@ -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]+)(\\:)' diff --git a/src/packages/gfm/spec/gfm-spec.coffee b/src/packages/gfm/spec/gfm-spec.coffee index f7e8b88bd..fa3107709 100644 --- a/src/packages/gfm/spec/gfm-spec.coffee +++ b/src/packages/gfm/spec/gfm-spec.coffee @@ -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:") diff --git a/src/packages/grammar-selector/lib/grammar-selector.coffee b/src/packages/grammar-selector/lib/grammar-selector.coffee index 6bf1d5721..70499295e 100644 --- a/src/packages/grammar-selector/lib/grammar-selector.coffee +++ b/src/packages/grammar-selector/lib/grammar-selector.coffee @@ -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() diff --git a/src/packages/symbols-view/lib/symbols-view.coffee b/src/packages/symbols-view/lib/symbols-view.coffee index b5ff72e57..9881d6a5f 100644 --- a/src/packages/symbols-view/lib/symbols-view.coffee +++ b/src/packages/symbols-view/lib/symbols-view.coffee @@ -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() diff --git a/src/packages/symbols-view/spec/symbols-view-spec.coffee b/src/packages/symbols-view/spec/symbols-view-spec.coffee index 8c43ecf8b..f8f87cdb5 100644 --- a/src/packages/symbols-view/spec/symbols-view-spec.coffee +++ b/src/packages/symbols-view/spec/symbols-view-spec.coffee @@ -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() diff --git a/src/packages/tabs/lib/tab-bar-view.coffee b/src/packages/tabs/lib/tab-bar-view.coffee index 6b524c2a7..6d6ec95c7 100644 --- a/src/packages/tabs/lib/tab-bar-view.coffee +++ b/src/packages/tabs/lib/tab-bar-view.coffee @@ -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 diff --git a/src/packages/tabs/spec/tabs-spec.coffee b/src/packages/tabs/spec/tabs-spec.coffee index 953ef3bd7..6d53313f2 100644 --- a/src/packages/tabs/spec/tabs-spec.coffee +++ b/src/packages/tabs/spec/tabs-spec.coffee @@ -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') diff --git a/src/packages/tree-view/lib/directory-view.coffee b/src/packages/tree-view/lib/directory-view.coffee index e1ebb798f..14bcbd8e6 100644 --- a/src/packages/tree-view/lib/directory-view.coffee +++ b/src/packages/tree-view/lib/directory-view.coffee @@ -2,7 +2,6 @@ FileView = require './file-view' Directory = require 'directory' $ = require 'jquery' -Git = require 'git' module.exports = class DirectoryView extends View diff --git a/src/packages/tree-view/lib/file-view.coffee b/src/packages/tree-view/lib/file-view.coffee index fb1790fa4..2223b8807 100644 --- a/src/packages/tree-view/lib/file-view.coffee +++ b/src/packages/tree-view/lib/file-view.coffee @@ -1,6 +1,5 @@ {View} = require 'space-pen' $ = require 'jquery' -Git = require 'git' fsUtils = require 'fs-utils' module.exports = diff --git a/src/packages/tree-view/stylesheets/tree-view.less b/src/packages/tree-view/stylesheets/tree-view.less index 4e02304b3..fcc209fca 100644 --- a/src/packages/tree-view/stylesheets/tree-view.less +++ b/src/packages/tree-view/stylesheets/tree-view.less @@ -24,7 +24,7 @@ .tree-view-scroller { height: 100%; width: 100%; - overflow: scroll; + overflow: auto; } .tree-view { diff --git a/src/packages/wrap-guide/lib/wrap-guide-view.coffee b/src/packages/wrap-guide/lib/wrap-guide-view.coffee index dcce9c44e..dbfbc6333 100644 --- a/src/packages/wrap-guide/lib/wrap-guide-view.coffee +++ b/src/packages/wrap-guide/lib/wrap-guide-view.coffee @@ -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') diff --git a/src/stdlib/cson.coffee b/src/stdlib/cson.coffee index 5b8527d75..6d703d578 100644 --- a/src/stdlib/cson.coffee +++ b/src/stdlib/cson.coffee @@ -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' diff --git a/static/editor.less b/static/editor.less index 7e81c9cab..cf3a4eb87 100644 --- a/static/editor.less +++ b/static/editor.less @@ -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 { diff --git a/static/octicon-mixins.less b/static/octicon-mixins.less index fa660a6e2..ea2b93892 100644 --- a/static/octicon-mixins.less +++ b/static/octicon-mixins.less @@ -5,7 +5,6 @@ display: inline-block; line-height: 1; -webkit-font-smoothing: antialiased; - line-height: 1; text-decoration: none; } diff --git a/static/overlay.less b/static/overlay.less index 60bd0a88f..60e57628d 100644 --- a/static/overlay.less +++ b/static/overlay.less @@ -40,4 +40,4 @@ border-bottom: none; border-bottom-left-radius: 0; border-bottom-right-radius: 0; -} \ No newline at end of file +} diff --git a/static/select-list.less b/static/select-list.less index affeec33c..32ac015bf 100644 --- a/static/select-list.less +++ b/static/select-list.less @@ -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 { diff --git a/themes/atom-dark-syntax.css b/themes/atom-dark-syntax.css index e14796b22..a095d3018 100644 --- a/themes/atom-dark-syntax.css +++ b/themes/atom-dark-syntax.css @@ -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 { diff --git a/themes/atom-dark-ui/select-list.less b/themes/atom-dark-ui/select-list.less index 0413d192a..bd7b59c7e 100644 --- a/themes/atom-dark-ui/select-list.less +++ b/themes/atom-dark-ui/select-list.less @@ -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 { diff --git a/themes/atom-light-syntax.css b/themes/atom-light-syntax.css index 248630da8..774a3c561 100644 --- a/themes/atom-light-syntax.css +++ b/themes/atom-light-syntax.css @@ -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 { diff --git a/themes/atom-light-ui/select-list.less b/themes/atom-light-ui/select-list.less index 1864cd06c..692b61a74 100644 --- a/themes/atom-light-ui/select-list.less +++ b/themes/atom-light-ui/select-list.less @@ -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; }