diff --git a/build/package.json b/build/package.json index bd0c9a474..acca67b70 100644 --- a/build/package.json +++ b/build/package.json @@ -21,7 +21,7 @@ "grunt-contrib-csslint": "~0.2.0", "grunt-contrib-less": "~0.8.0", "grunt-cson": "0.14.0", - "grunt-download-atom-shell": "~0.14.0", + "grunt-download-atom-shell": "~0.15.0", "grunt-electron-installer": "^0.37.0", "grunt-lesslint": "0.17.0", "grunt-peg": "~1.1.0", diff --git a/build/tasks/generate-asar-task.coffee b/build/tasks/generate-asar-task.coffee index 800721fee..3d28f1cca 100644 --- a/build/tasks/generate-asar-task.coffee +++ b/build/tasks/generate-asar-task.coffee @@ -10,7 +10,7 @@ module.exports = (grunt) -> unpack = [ '*.node' - '.ctags' + 'ctags-config' 'ctags-darwin' 'ctags-linux' 'ctags-win32.exe' diff --git a/package.json b/package.json index 5a4f0879d..b3e1b1e21 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "color": "^0.7.3", "delegato": "^1", "emissary": "^1.3.3", - "event-kit": "^1.2.0", + "event-kit": "^1.3.0", "first-mate": "^5.0.0", "fs-plus": "^2.8.0", "fstream": "0.1.24", @@ -56,7 +56,7 @@ "space-pen": "3.8.2", "stacktrace-parser": "0.1.1", "temp": "0.8.1", - "text-buffer": "6.6.1", + "text-buffer": "6.7.0", "theorist": "^1.0.2", "typescript-simple": "1.0.0", "underscore-plus": "^1.6.6", @@ -100,11 +100,11 @@ "image-view": "0.54.0", "incompatible-packages": "0.24.1", "keybinding-resolver": "0.33.0", - "line-ending-selector": "0.0.4", + "line-ending-selector": "0.0.5", "link": "0.30.0", "markdown-preview": "0.150.0", "metrics": "0.51.0", - "notifications": "0.58.0", + "notifications": "0.59.0", "open-on-github": "0.38.0", "package-generator": "0.40.0", "release-notes": "0.53.0", @@ -113,10 +113,10 @@ "spell-check": "0.59.0", "status-bar": "0.78.0", "styleguide": "0.44.0", - "symbols-view": "0.101.0", + "symbols-view": "0.103.0", "tabs": "0.82.0", "timecop": "0.31.0", - "tree-view": "0.184.0", + "tree-view": "0.185.0", "update-package-dependencies": "0.10.0", "welcome": "0.30.0", "whitespace": "0.30.0", @@ -132,7 +132,7 @@ "language-html": "0.41.0", "language-hyperlink": "0.14.0", "language-java": "0.16.0", - "language-javascript": "0.89.0", + "language-javascript": "0.90.0", "language-json": "0.16.0", "language-less": "0.28.2", "language-make": "0.17.0", diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 3b7bd6061..23541bfb5 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -1110,6 +1110,24 @@ describe "Config", -> nestedObject: superNestedInt: 36 + expect(atom.config.get("foo")).toEqual { + bar: + anInt: 12 + anObject: + nestedInt: 24 + nestedObject: + superNestedInt: 36 + } + atom.config.set("foo.bar.anObject.nestedObject.superNestedInt", 37) + expect(atom.config.get("foo")).toEqual { + bar: + anInt: 12 + anObject: + nestedInt: 24 + nestedObject: + superNestedInt: 37 + } + it 'can set a non-object schema', -> schema = type: 'integer' diff --git a/spec/display-buffer-spec.coffee b/spec/display-buffer-spec.coffee index 1b490d2ff..1331c2c0a 100644 --- a/spec/display-buffer-spec.coffee +++ b/spec/display-buffer-spec.coffee @@ -1025,7 +1025,7 @@ describe "DisplayBuffer", -> markerChangedHandler.reset() marker2ChangedHandler.reset() - marker3 = displayBuffer.markBufferRange([[8, 1], [8, 2]], maintainHistory: true) + marker3 = displayBuffer.markBufferRange([[8, 1], [8, 2]]) marker3.onDidChange marker3ChangedHandler = jasmine.createSpy("marker3ChangedHandler") onDisplayBufferChange = -> @@ -1039,10 +1039,6 @@ describe "DisplayBuffer", -> expect(marker.getHeadScreenPosition()).toEqual [5, 10] expect(marker.getTailScreenPosition()).toEqual [5, 4] - # but marker snapshots are not restored until the end of the undo. - expect(marker2.isValid()).toBeFalsy() - expect(marker3.isValid()).toBeFalsy() - buffer.undo() expect(changeHandler).toHaveBeenCalled() expect(markerChangedHandler).toHaveBeenCalled() @@ -1078,8 +1074,6 @@ describe "DisplayBuffer", -> expect(markerChangedHandler).toHaveBeenCalled() expect(marker2ChangedHandler).toHaveBeenCalled() expect(marker3ChangedHandler).toHaveBeenCalled() - expect(marker2.isValid()).toBeFalsy() - expect(marker3.isValid()).toBeTruthy() it "updates the position of markers before emitting change events that aren't caused by a buffer change", -> displayBuffer.onDidChange changeHandler = jasmine.createSpy("changeHandler").andCallFake -> diff --git a/spec/integration/startup-spec.coffee b/spec/integration/startup-spec.coffee index d2583ed27..87ecba409 100644 --- a/spec/integration/startup-spec.coffee +++ b/spec/integration/startup-spec.coffee @@ -10,6 +10,7 @@ fs = require "fs" path = require "path" temp = require("temp").track() runAtom = require "./helpers/start-atom" +CSON = require "season" describe "Starting Atom", -> [tempDirPath, otherTempDirPath, atomHome] = [] @@ -197,6 +198,17 @@ describe "Starting Atom", -> .waitForExist("atom-workspace") .waitForPaneItemCount(1, 5000) + it "doesn't open a new window if openEmptyEditorOnStart is disabled", -> + configPath = path.join(atomHome, 'config.cson') + config = CSON.readFileSync(configPath) + config['*'].core = {openEmptyEditorOnStart: false} + CSON.writeFileSync(configPath, config) + + runAtom [], {ATOM_HOME: atomHome}, (client) -> + client + .waitForExist("atom-workspace") + .waitForPaneItemCount(0, 5000) + it "reopens any previously opened windows", -> runAtom [tempDirPath], {ATOM_HOME: atomHome}, (client) -> client diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index 36dc9e739..291014a89 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -3417,6 +3417,63 @@ describe "TextEditor", -> expect(buffer.lineForRow(0)).not.toContain "foo" expect(buffer.lineForRow(0)).toContain "fovar" + it "restores cursors and selections to their states before and after undone and redone changes", -> + editor.setSelectedBufferRanges([ + [[0, 0], [0, 0]], + [[1, 0], [1, 3]], + ]) + editor.insertText("abc") + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[0, 3], [0, 3]], + [[1, 3], [1, 3]] + ] + + editor.setCursorBufferPosition([0, 0]) + editor.setSelectedBufferRanges([ + [[2, 0], [2, 0]], + [[3, 0], [3, 0]], + [[4, 0], [4, 3]], + ]) + editor.insertText("def") + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[2, 3], [2, 3]], + [[3, 3], [3, 3]] + [[4, 3], [4, 3]] + ] + + editor.setCursorBufferPosition([0, 0]) + editor.undo() + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[2, 0], [2, 0]], + [[3, 0], [3, 0]], + [[4, 0], [4, 3]], + ] + + editor.undo() + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[0, 0], [0, 0]], + [[1, 0], [1, 3]] + ] + + editor.redo() + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[0, 3], [0, 3]], + [[1, 3], [1, 3]] + ] + + editor.redo() + + expect(editor.getSelectedBufferRanges()).toEqual [ + [[2, 3], [2, 3]], + [[3, 3], [3, 3]] + [[4, 3], [4, 3]] + ] + it "restores the selected ranges after undo and redo", -> editor.setSelectedBufferRanges([[[1, 6], [1, 10]], [[1, 22], [1, 27]]]) editor.delete() diff --git a/src/atom.coffee b/src/atom.coffee index 28058f8dd..05228b6ca 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -669,6 +669,7 @@ class Atom extends Model @windowEventHandler?.unsubscribe() openInitialEmptyEditorIfNecessary: -> + return unless @config.get('core.openEmptyEditorOnStart') if @getLoadSettings().initialPaths?.length is 0 and @workspace.getPaneItems().length is 0 @workspace.open(null) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index a1bd91cc7..d8eeb6fe3 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -89,6 +89,10 @@ module.exports = 'windows1258', 'windows866' ] + openEmptyEditorOnStart: + description: 'Automatically opens an empty editor when atom starts.' + type: 'boolean' + default: true editor: type: 'object' diff --git a/src/config.coffee b/src/config.coffee index 00ebabf58..15aa664bb 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -865,7 +865,7 @@ class Config if value? value = @deepClone(value) - _.defaults(value, defaultValue) if isPlainObject(value) and isPlainObject(defaultValue) + @deepDefaults(value, defaultValue) if isPlainObject(value) and isPlainObject(defaultValue) else value = @deepClone(defaultValue) @@ -928,6 +928,19 @@ class Config else object + deepDefaults: (target) -> + result = target + i = 0 + while ++i < arguments.length + object = arguments[i] + if isPlainObject(result) and isPlainObject(object) + for key in Object.keys(object) + result[key] = @deepDefaults(result[key], object[key]) + else + if not result? + result = @deepClone(object) + result + # `schema` will look something like this # # ```coffee diff --git a/src/context-menu-manager.coffee b/src/context-menu-manager.coffee index 73bcbf440..0258fedc7 100644 --- a/src/context-menu-manager.coffee +++ b/src/context-menu-manager.coffee @@ -86,9 +86,14 @@ class ContextMenuManager # * `label` (Optional) A {String} containing the menu item's label. # * `command` (Optional) A {String} containing the command to invoke on the # target of the right click that invoked the context menu. + # * `enabled` (Optional) A {Boolean} indicating whether the menu item + # should be clickable. Disabled menu items typically appear grayed out. + # Defaults to `true`. # * `submenu` (Optional) An {Array} of additional items. # * `type` (Optional) If you want to create a separator, provide an item # with `type: 'separator'` and no other keys. + # * `visible` (Optional) A {Boolean} indicating whether the menu item + # should appear in the menu. Defaults to `true`. # * `created` (Optional) A {Function} that is called on the item each time a # context menu is created via a right click. You can assign properties to # `this` to dynamically compute the command, label, etc. This method is diff --git a/src/text-editor.coffee b/src/text-editor.coffee index e2b93a3b2..1e0c6f4d6 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -1119,12 +1119,12 @@ class TextEditor extends Model # Essential: Undo the last change. undo: -> - @buffer.undo() + @avoidMergingSelections => @buffer.undo() @getLastSelection().autoscroll() # Essential: Redo the last change. redo: -> - @buffer.redo(this) + @avoidMergingSelections => @buffer.redo() @getLastSelection().autoscroll() # Extended: Batch multiple operations as a single undo/redo step. @@ -2217,6 +2217,9 @@ class TextEditor extends Model previousSelection.intersectsScreenRowRange(screenRange.start.row, screenRange.end.row) + avoidMergingSelections: (args...) -> + @mergeSelections args..., -> false + mergeSelections: (args...) -> mergePredicate = args.pop() fn = args.pop() if _.isFunction(_.last(args))