From 402f6056cc793b04f86efc2ce6c5f1b6e9d16ea8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Thu, 29 Oct 2015 11:00:41 -0700 Subject: [PATCH 01/72] 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fb2e615ce..4233d1359 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.1.0-beta2", + "version": "1.1.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From f1617c77971015c2a04aef66aa942b1bdf590566 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 5 Nov 2015 09:56:01 -0800 Subject: [PATCH 02/72] :arrow_up: legal-eagle@0.12 --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index 93354cdbd..7e737afec 100644 --- a/build/package.json +++ b/build/package.json @@ -27,7 +27,7 @@ "grunt-peg": "~1.1.0", "grunt-shell": "~0.3.1", "grunt-standard": "^1.0.2", - "legal-eagle": "~0.11.0", + "legal-eagle": "~0.12.0", "minidump": "~0.9", "npm": "2.13.3", "rcedit": "~0.3.0", From f0ec4e380f28ed9c3683bac8b8cff9e662e5bc7a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 5 Nov 2015 09:56:01 -0800 Subject: [PATCH 03/72] :arrow_up: legal-eagle@0.12 --- build/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index 308849a93..2ce92de17 100644 --- a/build/package.json +++ b/build/package.json @@ -27,7 +27,7 @@ "grunt-peg": "~1.1.0", "grunt-shell": "~0.3.1", "grunt-standard": "^1.0.2", - "legal-eagle": "~0.11.0", + "legal-eagle": "~0.12.0", "minidump": "~0.9", "npm": "2.13.3", "rcedit": "~0.3.0", From 7d46fe6c287f4788aaf2e9d4fab3f14e1b9b1e26 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 4 Nov 2015 13:58:10 -0800 Subject: [PATCH 04/72] :fire: Unused properties on TextEditor.prototype --- src/text-editor.coffee | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index c0c4dbe14..82169040f 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -54,13 +54,11 @@ GutterContainer = require './gutter-container' # soft wraps and folds to ensure your code interacts with them correctly. module.exports = class TextEditor extends Model - callDisplayBufferCreatedHook: false buffer: null languageMode: null cursors: null selections: null suppressSelectionMerging: false - updateBatchDepth: 0 selectionFlashDuration: 500 gutterContainer: null From 4d40e28c6b8d21e8cdc67dea6bdd99c453522782 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 4 Nov 2015 16:58:47 -0800 Subject: [PATCH 05/72] Remove presenter constructor parameters that aren't used in production --- spec/text-editor-presenter-spec.coffee | 91 ++++++++++++++++++-------- src/text-editor-presenter.coffee | 13 ++-- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 1804b7b6b..8d7279610 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -25,27 +25,36 @@ describe "TextEditorPresenter", -> editor.destroy() buffer.destroy() - buildPresenter = (params={}) -> + buildPresenterWithoutMeasurements = (params={}) -> _.defaults params, model: editor - explicitHeight: 130 - contentFrameWidth: 500 - windowWidth: 500 - windowHeight: 130 - boundingClientRect: {left: 0, top: 0, width: 500, height: 130} - gutterWidth: 0 - lineHeight: 10 - baseCharacterWidth: 10 - horizontalScrollbarHeight: 10 - verticalScrollbarWidth: 10 - scrollTop: 0 - scrollLeft: 0 config: atom.config - + contentFrameWidth: 500 presenter = new TextEditorPresenter(params) presenter.setLinesYardstick(new FakeLinesYardstick(editor, presenter)) presenter + buildPresenter = (params={}) -> + presenter = buildPresenterWithoutMeasurements(_.defaults(params, + scrollTop: 0 + scrollLeft: 0 + )) + + presenter.setExplicitHeight(params.explicitHeight ? 130) + presenter.setWindowSize(params.windowWidth ? 500, params.windowHeight ? 130) + presenter.setBoundingClientRect(params.boundingClientRect ? { + left: 0 + top: 0 + width: 500 + height: 130 + }) + presenter.setGutterWidth(params.gutterWidth ? 0) + presenter.setLineHeight(params.lineHeight ? 10) + presenter.setBaseCharacterWidth(params.baseCharacterWidth ? 10) + presenter.setHorizontalScrollbarHeight(params.horizontalScrollbarHeight ? 10) + presenter.setVerticalScrollbarWidth(params.verticalScrollbarWidth ? 10) + presenter + expectValues = (actual, expected) -> for key, value of expected expect(actual[key]).toEqual value @@ -160,7 +169,7 @@ describe "TextEditorPresenter", -> expect(stateFn(presenter).tiles[12]).toBeDefined() it "is empty until all of the required measurements are assigned", -> - presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null) + presenter = buildPresenterWithoutMeasurements() expect(stateFn(presenter).tiles).toEqual({}) presenter.setExplicitHeight(25) @@ -999,20 +1008,25 @@ describe "TextEditorPresenter", -> describe ".backgroundColor", -> it "is assigned to ::backgroundColor unless the editor is mini", -> - presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)') + presenter = buildPresenter() + presenter.setBackgroundColor('rgba(255, 0, 0, 0)') expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)' + editor.setMini(true) - presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)') + presenter = buildPresenter() + presenter.setBackgroundColor('rgba(255, 0, 0, 0)') expect(presenter.getState().content.backgroundColor).toBeNull() it "updates when ::backgroundColor changes", -> - presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)') + presenter = buildPresenter() + presenter.setBackgroundColor('rgba(255, 0, 0, 0)') expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)' expectStateUpdate presenter, -> presenter.setBackgroundColor('rgba(0, 0, 255, 0)') expect(presenter.getState().content.backgroundColor).toBe 'rgba(0, 0, 255, 0)' it "updates when ::mini changes", -> - presenter = buildPresenter(backgroundColor: 'rgba(255, 0, 0, 0)') + presenter = buildPresenter() + presenter.setBackgroundColor('rgba(255, 0, 0, 0)') expect(presenter.getState().content.backgroundColor).toBe 'rgba(255, 0, 0, 0)' expectStateUpdate presenter, -> editor.setMini(true) expect(presenter.getState().content.backgroundColor).toBeNull() @@ -1040,6 +1054,7 @@ describe "TextEditorPresenter", -> describe "[tileId].lines[lineId]", -> # line state objects it "includes the state for visible lines in a tile", -> presenter = buildPresenter(explicitHeight: 3, scrollTop: 4, lineHeight: 1, tileSize: 3, stoppedScrollingDelay: 200) + presenter.setExplicitHeight(3) expect(lineStateForScreenRow(presenter, 2)).toBeUndefined() @@ -1293,7 +1308,7 @@ describe "TextEditorPresenter", -> expect(stateForCursor(presenter, 4)).toBeUndefined() it "is empty until all of the required measurements are assigned", -> - presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null, baseCharacterWidth: null, horizontalScrollbarHeight: null) + presenter = buildPresenterWithoutMeasurements() expect(presenter.getState().content.cursors).toEqual({}) presenter.setExplicitHeight(25) @@ -1308,6 +1323,15 @@ describe "TextEditorPresenter", -> presenter.setBaseCharacterWidth(8) expect(presenter.getState().content.cursors).toEqual({}) + presenter.setBoundingClientRect(top: 0, left: 0, width: 500, height: 130) + expect(presenter.getState().content.cursors).toEqual({}) + + presenter.setWindowSize(500, 130) + expect(presenter.getState().content.cursors).toEqual({}) + + presenter.setVerticalScrollbarWidth(10) + expect(presenter.getState().content.cursors).toEqual({}) + presenter.setHorizontalScrollbarHeight(10) expect(presenter.getState().content.cursors).not.toEqual({}) @@ -1439,7 +1463,8 @@ describe "TextEditorPresenter", -> it "alternates between true and false twice per ::cursorBlinkPeriod when the editor is focused", -> cursorBlinkPeriod = 100 cursorBlinkResumeDelay = 200 - presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true}) + presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay}) + presenter.setFocused(true) expect(presenter.getState().content.cursorsVisible).toBe true expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2) @@ -1466,7 +1491,8 @@ describe "TextEditorPresenter", -> it "stops alternating for ::cursorBlinkResumeDelay when a cursor moves or a cursor is added", -> cursorBlinkPeriod = 100 cursorBlinkResumeDelay = 200 - presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true}) + presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay}) + presenter.setFocused(true) expect(presenter.getState().content.cursorsVisible).toBe true expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2) @@ -1616,7 +1642,7 @@ describe "TextEditorPresenter", -> [[0, 2], [2, 4]], ]) - presenter = buildPresenter(explicitHeight: null, lineHeight: null, scrollTop: null, baseCharacterWidth: null, tileSize: 2) + presenter = buildPresenterWithoutMeasurements(tileSize: 2) for tileId, tileState of presenter.getState().content.tiles expect(tileState.highlights).toEqual({}) @@ -1925,7 +1951,7 @@ describe "TextEditorPresenter", -> marker = editor.markBufferRange([[2, 13], [4, 14]], invalidate: 'touch') decoration = editor.decorateMarker(marker, {type: 'overlay', position: 'tail', item}) - presenter = buildPresenter(baseCharacterWidth: null, lineHeight: null, windowWidth: null, windowHeight: null, boundingClientRect: null) + presenter = buildPresenterWithoutMeasurements() expect(presenter.getState().content.overlays).toEqual({}) presenter.setBaseCharacterWidth(10) @@ -1937,6 +1963,12 @@ describe "TextEditorPresenter", -> presenter.setWindowSize(500, 100) expect(presenter.getState().content.overlays).toEqual({}) + presenter.setVerticalScrollbarWidth(10) + expect(presenter.getState().content.overlays).toEqual({}) + + presenter.setHorizontalScrollbarHeight(10) + expect(presenter.getState().content.overlays).toEqual({}) + presenter.setBoundingClientRect({top: 0, left: 0, height: 100, width: 500}) expect(presenter.getState().content.overlays).not.toEqual({}) @@ -2123,7 +2155,8 @@ describe "TextEditorPresenter", -> expect(editor.getRowsPerPage()).toBe(20) it "tracks the computed content height if ::autoHeight is true so the editor auto-expands vertically", -> - presenter = buildPresenter(explicitHeight: null, autoHeight: true) + presenter = buildPresenter(explicitHeight: null) + presenter.setAutoHeight(true) expect(presenter.getState().height).toBe editor.getScreenLineCount() * 10 expectStateUpdate presenter, -> presenter.setAutoHeight(false) @@ -2140,7 +2173,9 @@ describe "TextEditorPresenter", -> describe ".focused", -> it "tracks the value of ::focused", -> - presenter = buildPresenter(focused: false) + presenter = buildPresenter() + presenter.setFocused(false) + expect(presenter.getState().focused).toBe false expectStateUpdate presenter, -> presenter.setFocused(true) expect(presenter.getState().focused).toBe true @@ -2819,7 +2854,9 @@ describe "TextEditorPresenter", -> describe ".backgroundColor", -> it "is assigned to ::gutterBackgroundColor if present, and to ::backgroundColor otherwise", -> - presenter = buildPresenter(backgroundColor: "rgba(255, 0, 0, 0)", gutterBackgroundColor: "rgba(0, 255, 0, 0)") + presenter = buildPresenter() + presenter.setBackgroundColor("rgba(255, 0, 0, 0)") + presenter.setGutterBackgroundColor("rgba(0, 255, 0, 0)") expect(getStylesForGutterWithName(presenter, 'line-number').backgroundColor).toBe "rgba(0, 255, 0, 0)" expect(getStylesForGutterWithName(presenter, 'test-gutter').backgroundColor).toBe "rgba(0, 255, 0, 0)" diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 2e1d73c56..10fcfd6d3 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -13,15 +13,12 @@ class TextEditorPresenter minimumReflowInterval: 200 constructor: (params) -> - {@model, @config, @autoHeight, @explicitHeight, @contentFrameWidth, @scrollTop, @scrollLeft, @scrollColumn, @scrollRow, @boundingClientRect, @windowWidth, @windowHeight, @gutterWidth} = params - {horizontalScrollbarHeight, verticalScrollbarWidth} = params - {@lineHeight, @baseCharacterWidth, @backgroundColor, @gutterBackgroundColor, @tileSize} = params - {@cursorBlinkPeriod, @cursorBlinkResumeDelay, @stoppedScrollingDelay, @focused} = params - @measuredHorizontalScrollbarHeight = horizontalScrollbarHeight - @measuredVerticalScrollbarWidth = verticalScrollbarWidth - @gutterWidth ?= 0 - @tileSize ?= 6 + {@model, @config} = params + {@cursorBlinkPeriod, @cursorBlinkResumeDelay, @stoppedScrollingDelay, @tileSize} = params + {@contentFrameWidth, @scrollTop, @scrollLeft, @scrollColumn, @scrollRow} = params + @gutterWidth = 0 + @tileSize ?= 6 @realScrollTop = @scrollTop @realScrollLeft = @scrollLeft @disposables = new CompositeDisposable From b58752da38d8fd03f01f8ccd3463b9d57074feaa Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 4 Nov 2015 17:39:31 -0800 Subject: [PATCH 06/72] Keep model's logical scroll position up to date * Remove scrollRow and scrollColumn properties from the presenter * Assign presenter's scrollTop and scrollLeft based on model's first visible screen row and column, once the presenter has the required measurements. --- spec/text-editor-presenter-spec.coffee | 28 +++++++++++++------------- src/text-editor-component.coffee | 4 ---- src/text-editor-presenter.coffee | 21 +++++++------------ src/text-editor.coffee | 17 +++++++++------- 4 files changed, 31 insertions(+), 39 deletions(-) diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index 8d7279610..ae9dfb6a6 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -35,11 +35,9 @@ describe "TextEditorPresenter", -> presenter buildPresenter = (params={}) -> - presenter = buildPresenterWithoutMeasurements(_.defaults(params, - scrollTop: 0 - scrollLeft: 0 - )) - + presenter = buildPresenterWithoutMeasurements(params) + presenter.setScrollTop(params.scrollTop) if params.scrollTop? + presenter.setScrollLeft(params.scrollLeft) if params.scrollLeft? presenter.setExplicitHeight(params.explicitHeight ? 130) presenter.setWindowSize(params.windowWidth ? 500, params.windowHeight ? 130) presenter.setBoundingClientRect(params.boundingClientRect ? { @@ -175,10 +173,8 @@ describe "TextEditorPresenter", -> presenter.setExplicitHeight(25) expect(stateFn(presenter).tiles).toEqual({}) + # Sets scroll row from model's logical position presenter.setLineHeight(10) - expect(stateFn(presenter).tiles).toEqual({}) - - presenter.setScrollTop(0) expect(stateFn(presenter).tiles).not.toEqual({}) it "updates when ::scrollTop changes", -> @@ -621,6 +617,8 @@ describe "TextEditorPresenter", -> describe ".scrollingVertically", -> it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", -> presenter = buildPresenter(scrollTop: 10, stoppedScrollingDelay: 200, explicitHeight: 100) + expect(presenter.getState().content.scrollingVertically).toBe true + advanceClock(300) expect(presenter.getState().content.scrollingVertically).toBe false expectStateUpdate presenter, -> presenter.setScrollTop(0) expect(presenter.getState().content.scrollingVertically).toBe true @@ -763,7 +761,8 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollTop).toBe(10) it "corresponds to the passed logical coordinates when building the presenter", -> - presenter = buildPresenter(scrollRow: 4, lineHeight: 10, explicitHeight: 20) + editor.setFirstVisibleScreenRow(4) + presenter = buildPresenter(lineHeight: 10, explicitHeight: 20) expect(presenter.getState().content.scrollTop).toBe(40) it "tracks the value of ::scrollTop", -> @@ -777,11 +776,11 @@ describe "TextEditorPresenter", -> expectStateUpdate presenter, -> presenter.setScrollTop(50) presenter.getState() # commits scroll position - expect(editor.getScrollRow()).toBe(5) + expect(editor.getFirstVisibleScreenRow()).toBe 5 expectStateUpdate presenter, -> presenter.setScrollTop(57) presenter.getState() # commits scroll position - expect(editor.getScrollRow()).toBe(6) + expect(editor.getFirstVisibleScreenRow()).toBe 6 it "reassigns the scrollTop if it exceeds the max possible value after lines are removed", -> presenter = buildPresenter(scrollTop: 80, lineHeight: 10, explicitHeight: 50, horizontalScrollbarHeight: 0) @@ -890,7 +889,8 @@ describe "TextEditorPresenter", -> expect(presenter.getState().content.scrollLeft).toBe(50) it "corresponds to the passed logical coordinates when building the presenter", -> - presenter = buildPresenter(scrollColumn: 3, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500) + editor.setFirstVisibleScreenColumn(3) + presenter = buildPresenter(lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500) expect(presenter.getState().content.scrollLeft).toBe(30) it "tracks the value of ::scrollLeft", -> @@ -904,11 +904,11 @@ describe "TextEditorPresenter", -> expectStateUpdate presenter, -> presenter.setScrollLeft(50) presenter.getState() # commits scroll position - expect(editor.getScrollColumn()).toBe(5) + expect(editor.getFirstVisibleScreenColumn()).toBe 5 expectStateUpdate presenter, -> presenter.setScrollLeft(57) presenter.getState() # commits scroll position - expect(editor.getScrollColumn()).toBe(6) + expect(editor.getFirstVisibleScreenColumn()).toBe 6 it "is always rounded to the nearest integer", -> presenter = buildPresenter(scrollLeft: 10, lineHeight: 10, baseCharacterWidth: 10, verticalScrollbarWidth: 10, contentFrameWidth: 500) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index d72c50382..dc0abbe60 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -50,10 +50,6 @@ class TextEditorComponent @presenter = new TextEditorPresenter model: @editor - scrollTop: 0 - scrollLeft: 0 - scrollRow: @editor.getScrollRow() - scrollColumn: @editor.getScrollColumn() tileSize: tileSize cursorBlinkPeriod: @cursorBlinkPeriod cursorBlinkResumeDelay: @cursorBlinkResumeDelay diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 10fcfd6d3..bda61ab87 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -15,7 +15,7 @@ class TextEditorPresenter constructor: (params) -> {@model, @config} = params {@cursorBlinkPeriod, @cursorBlinkResumeDelay, @stoppedScrollingDelay, @tileSize} = params - {@contentFrameWidth, @scrollTop, @scrollLeft, @scrollColumn, @scrollRow} = params + {@contentFrameWidth} = params @gutterWidth = 0 @tileSize ?= 6 @@ -72,7 +72,6 @@ class TextEditorPresenter @updateVerticalDimensions() @updateScrollbarDimensions() - @restoreScrollPosition() @commitPendingLogicalScrollTopPosition() @commitPendingScrollTopPosition() @@ -777,8 +776,7 @@ class TextEditorPresenter if scrollTop isnt @realScrollTop and not Number.isNaN(scrollTop) @realScrollTop = scrollTop @scrollTop = Math.round(scrollTop) - @scrollRow = Math.round(@scrollTop / @lineHeight) - @model.setScrollRow(@scrollRow) + @model.setFirstVisibleScreenRow(Math.round(@scrollTop / @lineHeight)) @updateStartRow() @updateEndRow() @@ -794,8 +792,7 @@ class TextEditorPresenter if scrollLeft isnt @realScrollLeft and not Number.isNaN(scrollLeft) @realScrollLeft = scrollLeft @scrollLeft = Math.round(scrollLeft) - @scrollColumn = Math.round(@scrollLeft / @baseCharacterWidth) - @model.setScrollColumn(@scrollColumn) + @model.setFirstVisibleScreenColumn(Math.round(@scrollLeft / @baseCharacterWidth)) @emitter.emit 'did-change-scroll-left', @scrollLeft @@ -1106,6 +1103,8 @@ class TextEditorPresenter setLineHeight: (lineHeight) -> unless @lineHeight is lineHeight @lineHeight = lineHeight + unless @scrollTop? + @updateScrollTop(@model.getFirstVisibleScreenRow() * lineHeight) @model.setLineHeightInPixels(lineHeight) @shouldUpdateHeightState = true @shouldUpdateHorizontalScrollState = true @@ -1133,6 +1132,8 @@ class TextEditorPresenter @halfWidthCharWidth = halfWidthCharWidth @koreanCharWidth = koreanCharWidth @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) + unless @scrollLeft? + @updateScrollLeft(@model.getFirstVisibleScreenColumn() * baseCharacterWidth) @characterWidthsChanged() characterWidthsChanged: -> @@ -1617,14 +1618,6 @@ class TextEditorPresenter @updateScrollTop(@pendingScrollTop) @pendingScrollTop = null - restoreScrollPosition: -> - return if @hasRestoredScrollPosition or not @hasPixelPositionRequirements() - - @setScrollTop(@scrollRow * @lineHeight) if @scrollRow? - @setScrollLeft(@scrollColumn * @baseCharacterWidth) if @scrollColumn? - - @hasRestoredScrollPosition = true - clearPendingScrollPosition: -> @pendingScrollLogicalPosition = null @pendingScrollTop = null diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 82169040f..327647cb7 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -87,7 +87,7 @@ class TextEditor extends Model super { - @softTabs, @scrollRow, @scrollColumn, initialLine, initialColumn, tabLength, + @softTabs, @firstVisibleScreenRow, @firstVisibleScreenColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, @grammarRegistry, @project, @assert, @applicationDelegate @@ -102,6 +102,8 @@ class TextEditor extends Model throw new Error("Must pass a project parameter when constructing TextEditors") unless @project? throw new Error("Must pass an assert parameter when constructing TextEditors") unless @assert? + @firstVisibleScreenRow ?= 0 + @firstVisibleScreenColumn ?= 0 @emitter = new Emitter @disposables = new CompositeDisposable @cursors = [] @@ -141,8 +143,8 @@ class TextEditor extends Model deserializer: 'TextEditor' id: @id softTabs: @softTabs - scrollRow: @getScrollRow() - scrollColumn: @getScrollColumn() + firstVisibleScreenRow: @getFirstVisibleScreenRow() + firstVisibleScreenColumn: @getFirstVisibleScreenColumn() displayBuffer: @displayBuffer.serialize() subscribeToBuffer: -> @@ -3086,11 +3088,12 @@ class TextEditor extends Model Grim.deprecate("This is now a view method. Call TextEditorElement::getWidth instead.") @displayBuffer.getWidth() - getScrollRow: -> @scrollRow - setScrollRow: (@scrollRow) -> + setFirstVisibleScreenRow: (@firstVisibleScreenRow) -> + getFirstVisibleScreenRow: -> @firstVisibleScreenRow + + setFirstVisibleScreenColumn: (@firstVisibleScreenColumn) -> + getFirstVisibleScreenColumn: -> @firstVisibleScreenColumn - getScrollColumn: -> @scrollColumn - setScrollColumn: (@scrollColumn) -> getScrollTop: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollTop instead.") From 396e8a42a4704ca1a19f928d36093aa4cc339fb1 Mon Sep 17 00:00:00 2001 From: aki Date: Sun, 8 Nov 2015 23:14:13 +0900 Subject: [PATCH 07/72] Fix activatePackages --- src/package-manager.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 5c0df4b70..0584fe41a 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -419,7 +419,7 @@ class PackageManager @config.transact => for pack in packages promise = @activatePackage(pack.name) - promises.push(promise) unless pack.hasActivationCommands() + promises.push(promise) unless pack.activationShouldBeDeferred() return @observeDisabledPackages() @observePackagesWithKeymapsDisabled() From 48cc5e713ea6f5110f680401b3bcdf287861a601 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 9 Nov 2015 10:13:09 -0800 Subject: [PATCH 08/72] Make presenter respond to external changes to model's first visible screen row --- spec/text-editor-spec.coffee | 65 ++++++++++++++++++++++++++++++++ src/text-editor-presenter.coffee | 6 ++- src/text-editor.coffee | 33 +++++++++++++--- 3 files changed, 98 insertions(+), 6 deletions(-) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index ed299ab54..77a2ba30a 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -4784,6 +4784,71 @@ describe "TextEditor", -> editor.selectPageUp() expect(editor.getSelectedBufferRanges()).toEqual [[[0, 0], [12, 2]]] + describe "::setFirstVisibleScreenRow() and ::getFirstVisibleScreenRow()", -> + beforeEach -> + line = Array(9).join('0123456789') + editor.setText([1..100].map(-> line).join('\n')) + expect(editor.getLineCount()).toBe 100 + expect(editor.lineTextForBufferRow(0).length).toBe 80 + + describe "when the editor doesn't have a height and lineHeightInPixels", -> + it "does not affect the editor's visible row range", -> + expect(editor.getVisibleRowRange()).toBeNull() + + editor.setFirstVisibleScreenRow(1) + expect(editor.getFirstVisibleScreenRow()).toEqual 1 + + editor.setFirstVisibleScreenRow(3) + expect(editor.getFirstVisibleScreenRow()).toEqual 3 + + expect(editor.getVisibleRowRange()).toBeNull() + + describe "when the editor has a height and lineHeightInPixels", -> + beforeEach -> + atom.config.set('editor.scrollPastEnd', true) + editor.setHeight(100, true) + editor.setLineHeightInPixels(10) + + it "updates the editor's visible row range", -> + editor.setFirstVisibleScreenRow(2) + expect(editor.getFirstVisibleScreenRow()).toEqual 2 + expect(editor.getVisibleRowRange()).toEqual [2, 12] + + it "notifies ::onDidChangeFirstVisibleScreenRow observers", -> + changeCount = 0 + editor.onDidChangeFirstVisibleScreenRow -> changeCount++ + + editor.setFirstVisibleScreenRow(2) + expect(changeCount).toBe 1 + + editor.setFirstVisibleScreenRow(2) + expect(changeCount).toBe 1 + + editor.setFirstVisibleScreenRow(3) + expect(changeCount).toBe 2 + + it "ensures that the top row is less than the buffer's line count", -> + editor.setFirstVisibleScreenRow(102) + expect(editor.getFirstVisibleScreenRow()).toEqual 99 + expect(editor.getVisibleRowRange()).toEqual [99, 99] + + it "ensures that the left column is less than the length of the longest screen line", -> + editor.setFirstVisibleScreenRow(10) + expect(editor.getFirstVisibleScreenRow()).toEqual 10 + + editor.setText("\n\n\n") + + editor.setFirstVisibleScreenRow(10) + expect(editor.getFirstVisibleScreenRow()).toEqual 3 + + describe "when the 'editor.scrollPastEnd' option is set to false", -> + it "ensures that the bottom row is less than the buffer's line count", -> + atom.config.set('editor.scrollPastEnd', false) + + editor.setFirstVisibleScreenRow(95) + expect(editor.getFirstVisibleScreenRow()).toEqual 89 + expect(editor.getVisibleRowRange()).toEqual [89, 99] + describe '.get/setPlaceholderText()', -> it 'can be created with placeholderText', -> newEditor = atom.workspace.buildTextEditor( diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index bda61ab87..3b679b319 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -213,6 +213,7 @@ class TextEditorPresenter @disposables.add @model.onDidAddDecoration(@didAddDecoration.bind(this)) @disposables.add @model.onDidAddCursor(@didAddCursor.bind(this)) @disposables.add @model.onDidRequestAutoscroll(@requestAutoscroll.bind(this)) + @disposables.add @model.onDidChangeFirstVisibleScreenRow(@didChangeFirstVisibleScreenRow.bind(this)) @observeDecoration(decoration) for decoration in @model.getDecorations() @observeCursor(cursor) for cursor in @model.getCursors() @disposables.add @model.onDidAddGutter(@didAddGutter.bind(this)) @@ -776,7 +777,7 @@ class TextEditorPresenter if scrollTop isnt @realScrollTop and not Number.isNaN(scrollTop) @realScrollTop = scrollTop @scrollTop = Math.round(scrollTop) - @model.setFirstVisibleScreenRow(Math.round(@scrollTop / @lineHeight)) + @model.setFirstVisibleScreenRow(Math.round(@scrollTop / @lineHeight), true) @updateStartRow() @updateEndRow() @@ -1539,6 +1540,9 @@ class TextEditorPresenter @emitDidUpdateState() + didChangeFirstVisibleScreenRow: (screenRow) -> + @updateScrollTop(screenRow * @lineHeight) + getVerticalScrollMarginInPixels: -> Math.round(@model.getVerticalScrollMargin() * @lineHeight) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 327647cb7..0e678b066 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -448,6 +448,9 @@ class TextEditor extends Model onDidChangeCharacterWidths: (callback) -> @displayBuffer.onDidChangeCharacterWidths(callback) + onDidChangeFirstVisibleScreenRow: (callback, fromView) -> + @emitter.on 'did-change-first-visible-screen-row', callback + onDidChangeScrollTop: (callback) -> Grim.deprecate("This is now a view method. Call TextEditorElement::onDidChangeScrollTop instead.") @@ -3088,13 +3091,27 @@ class TextEditor extends Model Grim.deprecate("This is now a view method. Call TextEditorElement::getWidth instead.") @displayBuffer.getWidth() - setFirstVisibleScreenRow: (@firstVisibleScreenRow) -> + # Experimental: Scroll the editor such that the given screen row is at the + # top of the visible area. + setFirstVisibleScreenRow: (screenRow, fromView) -> + unless fromView + maxScreenRow = @getLineCount() - 1 + unless @config.get('editor.scrollPastEnd') + height = @displayBuffer.getHeight() + lineHeightInPixels = @displayBuffer.getLineHeightInPixels() + if height? and lineHeightInPixels? + maxScreenRow -= Math.floor(height / lineHeightInPixels) + screenRow = Math.min(screenRow, maxScreenRow) + + unless screenRow is @firstVisibleScreenRow + @emitter.emit 'did-change-first-visible-screen-row', screenRow unless fromView + @firstVisibleScreenRow = screenRow + getFirstVisibleScreenRow: -> @firstVisibleScreenRow setFirstVisibleScreenColumn: (@firstVisibleScreenColumn) -> getFirstVisibleScreenColumn: -> @firstVisibleScreenColumn - getScrollTop: -> Grim.deprecate("This is now a view method. Call TextEditorElement::getScrollTop instead.") @@ -3151,9 +3168,15 @@ class TextEditor extends Model @viewRegistry.getView(this).getMaxScrollTop() getVisibleRowRange: -> - Grim.deprecate("This is now a view method. Call TextEditorElement::getVisibleRowRange instead.") - - @viewRegistry.getView(this).getVisibleRowRange() + height = @displayBuffer.getHeight() + lineHeightInPixels = @displayBuffer.getLineHeightInPixels() + if height? and lineHeightInPixels? + [ + @firstVisibleScreenRow, + Math.min(@firstVisibleScreenRow + Math.floor(height / lineHeightInPixels), @getLineCount() - 1) + ] + else + null intersectsVisibleRowRange: (startRow, endRow) -> Grim.deprecate("This is now a view method. Call TextEditorElement::intersectsVisibleRowRange instead.") From 130464836194e257d1d87a471051ea20c817b9a4 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 9 Nov 2015 11:00:38 -0800 Subject: [PATCH 09/72] Make getLastVisibleScreenRow a model API again --- spec/text-editor-spec.coffee | 2 ++ src/text-editor.coffee | 35 +++++++++++++++-------------------- 2 files changed, 17 insertions(+), 20 deletions(-) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index 77a2ba30a..b0c40d588 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -4802,6 +4802,7 @@ describe "TextEditor", -> expect(editor.getFirstVisibleScreenRow()).toEqual 3 expect(editor.getVisibleRowRange()).toBeNull() + expect(editor.getLastVisibleScreenRow()).toBeNull() describe "when the editor has a height and lineHeightInPixels", -> beforeEach -> @@ -4812,6 +4813,7 @@ describe "TextEditor", -> it "updates the editor's visible row range", -> editor.setFirstVisibleScreenRow(2) expect(editor.getFirstVisibleScreenRow()).toEqual 2 + expect(editor.getLastVisibleScreenRow()).toBe 12 expect(editor.getVisibleRowRange()).toEqual [2, 12] it "notifies ::onDidChangeFirstVisibleScreenRow observers", -> diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 0e678b066..27376c7f2 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -3029,14 +3029,6 @@ class TextEditor extends Model @placeholderText = placeholderText @emitter.emit 'did-change-placeholder-text', @placeholderText - getFirstVisibleScreenRow: -> - deprecate("This is now a view method. Call TextEditorElement::getFirstVisibleScreenRow instead.") - @viewRegistry.getView(this).getVisibleRowRange()[0] - - getLastVisibleScreenRow: -> - Grim.deprecate("This is now a view method. Call TextEditorElement::getLastVisibleScreenRow instead.") - @viewRegistry.getView(this).getVisibleRowRange()[1] - pixelPositionForBufferPosition: (bufferPosition) -> Grim.deprecate("This method is deprecated on the model layer. Use `TextEditorElement::pixelPositionForBufferPosition` instead") @viewRegistry.getView(this).pixelPositionForBufferPosition(bufferPosition) @@ -3101,7 +3093,7 @@ class TextEditor extends Model lineHeightInPixels = @displayBuffer.getLineHeightInPixels() if height? and lineHeightInPixels? maxScreenRow -= Math.floor(height / lineHeightInPixels) - screenRow = Math.min(screenRow, maxScreenRow) + screenRow = Math.max(Math.min(screenRow, maxScreenRow), 0) unless screenRow is @firstVisibleScreenRow @emitter.emit 'did-change-first-visible-screen-row', screenRow unless fromView @@ -3109,6 +3101,20 @@ class TextEditor extends Model getFirstVisibleScreenRow: -> @firstVisibleScreenRow + getLastVisibleScreenRow: -> + height = @displayBuffer.getHeight() + lineHeightInPixels = @displayBuffer.getLineHeightInPixels() + if height? and lineHeightInPixels? + Math.min(@firstVisibleScreenRow + Math.floor(height / lineHeightInPixels), @getLineCount() - 1) + else + null + + getVisibleRowRange: -> + if lastVisibleScreenRow = @getLastVisibleScreenRow() + [@firstVisibleScreenRow, lastVisibleScreenRow] + else + null + setFirstVisibleScreenColumn: (@firstVisibleScreenColumn) -> getFirstVisibleScreenColumn: -> @firstVisibleScreenColumn @@ -3167,17 +3173,6 @@ class TextEditor extends Model @viewRegistry.getView(this).getMaxScrollTop() - getVisibleRowRange: -> - height = @displayBuffer.getHeight() - lineHeightInPixels = @displayBuffer.getLineHeightInPixels() - if height? and lineHeightInPixels? - [ - @firstVisibleScreenRow, - Math.min(@firstVisibleScreenRow + Math.floor(height / lineHeightInPixels), @getLineCount() - 1) - ] - else - null - intersectsVisibleRowRange: (startRow, endRow) -> Grim.deprecate("This is now a view method. Call TextEditorElement::intersectsVisibleRowRange instead.") From 4dba6f10fed7696099b2fc5a100163ecd2e72cfe Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Fri, 6 Nov 2015 14:29:04 -0500 Subject: [PATCH 10/72] :arrow_up: git-utils --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9e01f5b3a..79c1ba691 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "fs-plus": "^2.8.0", "fstream": "0.1.24", "fuzzaldrin": "^2.1", - "git-utils": "^4", + "git-utils": "^4.0.7", "grim": "1.5.0", "jasmine-json": "~0.0", "jasmine-tagged": "^1.1.4", From 3a42a3409203ee471e4591c62198621358816bf5 Mon Sep 17 00:00:00 2001 From: Josh Abernathy Date: Fri, 6 Nov 2015 14:29:52 -0500 Subject: [PATCH 11/72] :arrow_down: pathwatcher 6.3.0 is broken on Windows (https://github.com/atom/node-pathwatcher/issues/96). --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 79c1ba691..b10b803cb 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,7 @@ "normalize-package-data": "^2.0.0", "nslog": "^3", "oniguruma": "^5", - "pathwatcher": "^6.2", + "pathwatcher": "~6.2", "property-accessors": "^1.1.3", "random-words": "0.0.1", "resolve": "^1.1.6", From 86eef8cbbfd7d0829c6d47c08d8bac48be264ca3 Mon Sep 17 00:00:00 2001 From: joshaber Date: Mon, 9 Nov 2015 16:32:40 -0500 Subject: [PATCH 12/72] 1.2.0-beta2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b10b803cb..575cf2d00 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.2.0-beta1", + "version": "1.2.0-beta2", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 49f391ff81ec2407738a018a0f3e3f86a9ffba50 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Tue, 10 Nov 2015 00:27:23 +0200 Subject: [PATCH 13/72] Prioritize file type matching over first line matching --- src/grammar-registry.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 4a5352275..9c01b48e9 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -36,21 +36,21 @@ class GrammarRegistry extends FirstMate.GrammarRegistry if score > highestScore or not bestMatch? bestMatch = grammar highestScore = score - else if score is highestScore and bestMatch?.bundledPackage - bestMatch = grammar unless grammar.bundledPackage bestMatch # Extended: Returns a {Number} representing how well the grammar matches the # `filePath` and `contents`. getGrammarScore: (grammar, filePath, contents) -> + return Infinity if @grammarOverrideForPath(filePath) is grammar.scopeName + contents = fs.readFileSync(filePath, 'utf8') if not contents? and fs.isFileSync(filePath) - if @grammarOverrideForPath(filePath) is grammar.scopeName - 2 + (filePath?.length ? 0) - else if @grammarMatchesContents(grammar, contents) - 1 + (filePath?.length ? 0) - else - @getGrammarPathScore(grammar, filePath) + score = @getGrammarPathScore(grammar, filePath) + if not grammar.bundledPackage + score += 0.25 + if @grammarMatchesContents(grammar, contents) + score += 0.125 + score getGrammarPathScore: (grammar, filePath) -> return -1 unless filePath From e437234c58e88ab0f9b14f9be903a439241a1bc4 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 10 Nov 2015 11:05:31 +0100 Subject: [PATCH 14/72] Transact on both async and sync package activation --- src/config.coffee | 12 +++++++++--- src/package-manager.coffee | 12 +++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 663dbb777..50989706e 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -671,12 +671,18 @@ class Config # # * `callback` {Function} to execute while suppressing calls to handlers. transact: (callback) -> - @transactDepth++ + @startTransaction() try callback() finally - @transactDepth-- - @emitChangeEvent() + @endTransaction() + + startTransaction: -> + @transactDepth++ + + endTransaction: -> + @transactDepth-- + @emitChangeEvent() ### Section: Internal methods used by core diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 5c0df4b70..9a3e35710 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -416,11 +416,13 @@ class PackageManager activatePackages: (packages) -> promises = [] - @config.transact => - for pack in packages - promise = @activatePackage(pack.name) - promises.push(promise) unless pack.hasActivationCommands() - return + @config.startTransaction() + for pack in packages + promise = @activatePackage(pack.name) + promises.push(promise) unless pack.hasActivationCommands() + Promise.all(promises) + .then(=> @config.endTransaction()) + .catch(=> @config.endTransaction()) @observeDisabledPackages() @observePackagesWithKeymapsDisabled() promises From d4a67a7db50c8a447a77d9d2d313c1a5fc3662e2 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 10 Nov 2015 11:42:39 +0100 Subject: [PATCH 15/72] :art: Call it ::beginTransaction --- src/config.coffee | 4 ++-- src/package-manager.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 50989706e..372e745c4 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -671,13 +671,13 @@ class Config # # * `callback` {Function} to execute while suppressing calls to handlers. transact: (callback) -> - @startTransaction() + @beginTransaction() try callback() finally @endTransaction() - startTransaction: -> + beginTransaction: -> @transactDepth++ endTransaction: -> diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 9a3e35710..13f8b2534 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -416,7 +416,7 @@ class PackageManager activatePackages: (packages) -> promises = [] - @config.startTransaction() + @config.beginTransaction() for pack in packages promise = @activatePackage(pack.name) promises.push(promise) unless pack.hasActivationCommands() From 66255baa7166b965e66e63b39a8c5164e2d5c6d8 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Tue, 10 Nov 2015 21:02:41 +0200 Subject: [PATCH 16/72] Only allow bundle bias if a file type was matched --- src/grammar-registry.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 9c01b48e9..383d4d776 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -46,7 +46,7 @@ class GrammarRegistry extends FirstMate.GrammarRegistry contents = fs.readFileSync(filePath, 'utf8') if not contents? and fs.isFileSync(filePath) score = @getGrammarPathScore(grammar, filePath) - if not grammar.bundledPackage + if score > 0 and not grammar.bundledPackage score += 0.25 if @grammarMatchesContents(grammar, contents) score += 0.125 From 077886070f966c992cdcd3192cbe86ac2f30ab68 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 13:29:07 -0800 Subject: [PATCH 17/72] :arrow_up: language-perl@0.31 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c7657fdfa..c29d36f91 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,7 @@ "language-make": "0.20.0", "language-mustache": "0.13.0", "language-objective-c": "0.15.0", - "language-perl": "0.30.0", + "language-perl": "0.31.0", "language-php": "0.34.0", "language-property-list": "0.8.0", "language-python": "0.41.0", From a0c208974b21d5c9f1fedbc7ad46da5fee865750 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 13:07:02 -0800 Subject: [PATCH 18/72] Add failing spec --- spec/package-manager-spec.coffee | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee index 88e730d44..391c63dc7 100644 --- a/spec/package-manager-spec.coffee +++ b/spec/package-manager-spec.coffee @@ -433,6 +433,13 @@ describe "PackageManager", -> runs -> expect(atom.keymaps.findKeyBindings(keystrokes: 'ctrl-z', target: element1)).toHaveLength 0 + describe "when setting core.packagesWithKeymapsDisabled", -> + it "ignores package names in the array that aren't loaded", -> + atom.packages.observePackagesWithKeymapsDisabled() + + expect(-> atom.config.set("core.packagesWithKeymapsDisabled", ["package-does-not-exist"])).not.toThrow() + expect(-> atom.config.set("core.packagesWithKeymapsDisabled", [])).not.toThrow() + describe "when the package's keymaps are disabled and re-enabled after it is activated", -> it "removes and re-adds the keymaps", -> element1 = createTestElement('test-1') From 4692ca9702210c0c25118a08deaee67f848afbc8 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 13:07:58 -0800 Subject: [PATCH 19/72] Guard against package not being loaded --- src/package-manager.coffee | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 5c0df4b70..215ddefcd 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -336,8 +336,10 @@ class PackageManager keymapsToEnable = _.difference(oldValue, newValue) keymapsToDisable = _.difference(newValue, oldValue) - @getLoadedPackage(packageName).deactivateKeymaps() for packageName in keymapsToDisable when not @isPackageDisabled(packageName) - @getLoadedPackage(packageName).activateKeymaps() for packageName in keymapsToEnable when not @isPackageDisabled(packageName) + for packageName in keymapsToDisable when not @isPackageDisabled(packageName) + @getLoadedPackage(packageName)?.deactivateKeymaps() + for packageName in keymapsToEnable when not @isPackageDisabled(packageName) + @getLoadedPackage(packageName)?.activateKeymaps() null loadPackages: -> From 1239ba5f7b0a9e213f5706e37b5c39ccd75a60a5 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Tue, 10 Nov 2015 00:27:23 +0200 Subject: [PATCH 20/72] Prioritize file type matching over first line matching --- src/grammar-registry.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 4a5352275..9c01b48e9 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -36,21 +36,21 @@ class GrammarRegistry extends FirstMate.GrammarRegistry if score > highestScore or not bestMatch? bestMatch = grammar highestScore = score - else if score is highestScore and bestMatch?.bundledPackage - bestMatch = grammar unless grammar.bundledPackage bestMatch # Extended: Returns a {Number} representing how well the grammar matches the # `filePath` and `contents`. getGrammarScore: (grammar, filePath, contents) -> + return Infinity if @grammarOverrideForPath(filePath) is grammar.scopeName + contents = fs.readFileSync(filePath, 'utf8') if not contents? and fs.isFileSync(filePath) - if @grammarOverrideForPath(filePath) is grammar.scopeName - 2 + (filePath?.length ? 0) - else if @grammarMatchesContents(grammar, contents) - 1 + (filePath?.length ? 0) - else - @getGrammarPathScore(grammar, filePath) + score = @getGrammarPathScore(grammar, filePath) + if not grammar.bundledPackage + score += 0.25 + if @grammarMatchesContents(grammar, contents) + score += 0.125 + score getGrammarPathScore: (grammar, filePath) -> return -1 unless filePath From dc4d6ad82ac0aeeeac23a02ab8e12c18714f1066 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Tue, 10 Nov 2015 21:02:41 +0200 Subject: [PATCH 21/72] Only allow bundle bias if a file type was matched --- src/grammar-registry.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grammar-registry.coffee b/src/grammar-registry.coffee index 9c01b48e9..383d4d776 100644 --- a/src/grammar-registry.coffee +++ b/src/grammar-registry.coffee @@ -46,7 +46,7 @@ class GrammarRegistry extends FirstMate.GrammarRegistry contents = fs.readFileSync(filePath, 'utf8') if not contents? and fs.isFileSync(filePath) score = @getGrammarPathScore(grammar, filePath) - if not grammar.bundledPackage + if score > 0 and not grammar.bundledPackage score += 0.25 if @grammarMatchesContents(grammar, contents) score += 0.125 From 19334be18825781967161279786cc3807598ae93 Mon Sep 17 00:00:00 2001 From: Joe Fitzgerald Date: Tue, 10 Nov 2015 15:37:01 -0700 Subject: [PATCH 22/72] Add Appveyor CI - Add Appveyor badge - Add Appveyor.yml definition, with encrypted ATOM_ACCESS_TOKEN - Add cibuild.cmd script to launch cibuild on Windows - Prepare to release Atom on Windows from Appveyor (but don't do it yet) - Reduce dependence on JANKY in ci scripts + tasks - Suppress release activities on PRs for Travis and Appveyor - Cache ~/.atom/.apm, ~/.atom/.node-gyp/.atom, and ~/.atom/.npm on Appveyor --- .node-version | 1 - .npmrc | 1 + README.md | 2 +- apm/.npmrc | 1 + appveyor.yml | 35 +++++++++++++++++++++++++++ build/Gruntfile.coffee | 25 ++++++++++++++----- build/tasks/publish-build-task.coffee | 7 +++--- build/tasks/set-version-task.coffee | 10 +++++--- build/tasks/spec-task.coffee | 3 +-- script/cibuild | 19 ++++++++++----- script/cibuild.cmd | 5 ++++ spec/integration/startup-spec.coffee | 2 +- 12 files changed, 86 insertions(+), 25 deletions(-) delete mode 100644 .node-version create mode 100644 .npmrc create mode 100644 apm/.npmrc create mode 100644 appveyor.yml create mode 100644 script/cibuild.cmd diff --git a/.node-version b/.node-version deleted file mode 100644 index 87a1cf595..000000000 --- a/.node-version +++ /dev/null @@ -1 +0,0 @@ -v0.12.0 diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000..c5ff09782 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +cache = ~/.atom/.npm diff --git a/README.md b/README.md index 580f52294..168124ac5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png) -[![Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) +[![Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Build status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) [![Join the Atom Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/) diff --git a/apm/.npmrc b/apm/.npmrc new file mode 100644 index 000000000..c5ff09782 --- /dev/null +++ b/apm/.npmrc @@ -0,0 +1 @@ +cache = ~/.atom/.npm diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 000000000..8e33549c7 --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,35 @@ +version: "{build}" + +skip_tags: true +clone_folder: c:\projects\atom +clone_depth: 10 + +platform: + - x86 + +environment: + global: + ATOM_DEV_RESOURCE_PATH: c:\projects\atom + ATOM_ACCESS_TOKEN: + secure: Q7vxmSq0bVCLTTRPzXw5ZhPTe7XYhWxX0tQV6neEkddTH6pZkOYNmSCG6VnMX2f+ + + matrix: + - NODE_VERSION: 0.10.35 + +install: + - SET PATH=C:\Program Files\Atom\resources\cli;%PATH% + - ps: Install-Product node $env:NODE_VERSION $env:PLATFORM + +build_script: + - cd %APPVEYOR_BUILD_FOLDER% + - C:\projects\atom\script\cibuild.cmd + +test: off +deploy: off +artifacts: + - path: atom-build + +cache: + - '%USERPROFILE%\.atom\.apm' + - '%USERPROFILE%\.atom\.node-gyp\.atom' + - '%USERPROFILE%\.atom\.npm' diff --git a/build/Gruntfile.coffee b/build/Gruntfile.coffee index a67bee93b..8dd1c573b 100644 --- a/build/Gruntfile.coffee +++ b/build/Gruntfile.coffee @@ -39,7 +39,16 @@ module.exports = (grunt) -> disableAutoUpdate = grunt.option('no-auto-update') ? false channel = grunt.option('channel') - channel ?= process.env.JANKY_BRANCH if process.env.JANKY_BRANCH in ['stable', 'beta'] + releasableBranches = ['stable', 'beta'] + if process.env.APPVEYOR and not process.env.APPVEYOR_PULL_REQUEST_NUMBER + channel ?= process.env.APPVEYOR_REPO_BRANCH if process.env.APPVEYOR_REPO_BRANCH in releasableBranches + + if process.env.TRAVIS and not process.env.TRAVIS_PULL_REQUEST + channel ?= process.env.TRAVIS_BRANCH if process.env.TRAVIS_BRANCH in releasableBranches + + if process.env.JANKY_BRANCH + channel ?= process.env.JANKY_BRANCH if process.env.JANKY_BRANCH in releasableBranches + channel ?= 'dev' metadata = packageJson @@ -270,16 +279,20 @@ module.exports = (grunt) -> grunt.registerTask('lint', ['standard', 'coffeelint', 'csslint', 'lesslint']) grunt.registerTask('test', ['shell:kill-atom', 'run-specs']) - ciTasks = ['output-disk-space', 'download-electron', 'download-electron-chromedriver', 'build'] + ciTasks = [] + ciTasks.push('output-disk-space') unless process.env.CI + ciTasks.push('download-electron') + ciTasks.push('download-electron-chromedriver') + ciTasks.push('build') ciTasks.push('dump-symbols') if process.platform isnt 'win32' ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar') ciTasks.push('mkdeb') if process.platform is 'linux' - ciTasks.push('codesign:exe') if process.platform is 'win32' and not process.env.TRAVIS + ciTasks.push('codesign:exe') if process.platform is 'win32' and not process.env.CI ciTasks.push('create-windows-installer:installer') if process.platform is 'win32' ciTasks.push('test') if process.platform is 'darwin' - ciTasks.push('codesign:installer') if process.platform is 'win32' and not process.env.TRAVIS - ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.TRAVIS - ciTasks.push('publish-build') unless process.env.TRAVIS + ciTasks.push('codesign:installer') if process.platform is 'win32' and not process.env.CI + ciTasks.push('codesign:app') if process.platform is 'darwin' and not process.env.CI + ciTasks.push('publish-build') unless process.env.CI grunt.registerTask('ci', ciTasks) defaultTasks = ['download-electron', 'download-electron-chromedriver', 'build', 'set-version', 'generate-asar'] diff --git a/build/tasks/publish-build-task.coffee b/build/tasks/publish-build-task.coffee index d1640a42b..fc96121ae 100644 --- a/build/tasks/publish-build-task.coffee +++ b/build/tasks/publish-build-task.coffee @@ -9,7 +9,6 @@ request = require 'request' grunt = null -commitSha = process.env.JANKY_SHA1 token = process.env.ATOM_ACCESS_TOKEN defaultHeaders = Authorization: "token #{token}" @@ -31,8 +30,8 @@ module.exports = (gruntObject) -> cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json') grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', -> - branchName = process.env.JANKY_BRANCH - switch branchName + channel = grunt.config.get('atom.channel') + switch channel when 'stable' isPrerelease = false when 'beta' @@ -55,7 +54,7 @@ module.exports = (gruntObject) -> zipAssets buildDir, assets, (error) -> return done(error) if error? - getAtomDraftRelease isPrerelease, branchName, (error, release) -> + getAtomDraftRelease isPrerelease, channel, (error, release) -> return done(error) if error? assetNames = (asset.assetName for asset in assets) deleteExistingAssets release, assetNames, (error) -> diff --git a/build/tasks/set-version-task.coffee b/build/tasks/set-version-task.coffee index 2cc148011..28abb6493 100644 --- a/build/tasks/set-version-task.coffee +++ b/build/tasks/set-version-task.coffee @@ -5,18 +5,20 @@ module.exports = (grunt) -> {spawn} = require('./task-helpers')(grunt) getVersion = (callback) -> - onBuildMachine = process.env.JANKY_SHA1 and process.env.JANKY_BRANCH in ['stable', 'beta'] + releasableBranches = ['stable', 'beta'] + channel = grunt.config.get('atom.channel') + shouldUseCommitHash = if channel in releasableBranches then false else true inRepository = fs.existsSync(path.resolve(__dirname, '..', '..', '.git')) {version} = require(path.join(grunt.config.get('atom.appDir'), 'package.json')) - if onBuildMachine or not inRepository - callback(null, version) - else + if shouldUseCommitHash and inRepository cmd = 'git' args = ['rev-parse', '--short', 'HEAD'] spawn {cmd, args}, (error, {stdout}={}, code) -> commitHash = stdout?.trim?() combinedVersion = "#{version}-#{commitHash}" callback(error, combinedVersion) + else + callback(null, version) grunt.registerTask 'set-version', 'Set the version in the plist and package.json', -> done = @async() diff --git a/build/tasks/spec-task.coffee b/build/tasks/spec-task.coffee index 27465efdf..892c92696 100644 --- a/build/tasks/spec-task.coffee +++ b/build/tasks/spec-task.coffee @@ -6,8 +6,7 @@ async = require 'async' # TODO: This should really be parallel on every platform, however: # - On Windows, our fixtures step on each others toes. -# - On Travis, Mac workers haven't enough horsepower. -if process.env.TRAVIS or process.platform is 'win32' +if process.platform is 'win32' concurrency = 1 else concurrency = 2 diff --git a/script/cibuild b/script/cibuild index d366af79a..c1aedddc8 100755 --- a/script/cibuild +++ b/script/cibuild @@ -22,12 +22,18 @@ function loadEnvironmentVariables(filePath) { } function readEnvironmentVariables() { - if (process.platform === 'win32') { - loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials')); - } else if (process.platform === 'darwin') { - loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials'); - loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain'); - } else if (process.platform === 'linux') { + if (process.env.JANKY_SHA1) { + if (process.platform === 'win32') { + loadEnvironmentVariables(path.resolve('/jenkins/config/atomcredentials')); + } else if (process.platform === 'darwin') { + loadEnvironmentVariables('/var/lib/jenkins/config/atomcredentials'); + loadEnvironmentVariables('/var/lib/jenkins/config/xcodekeychain'); + } + } +} + +function setEnvironmentVariables() { + if (process.platform === 'linux') { // Use Clang for building native code, the GCC on Precise is too old. process.env.CC = 'clang'; process.env.CXX = 'clang++'; @@ -81,6 +87,7 @@ function removeTempFolders() { } readEnvironmentVariables(); +setEnvironmentVariables(); removeNodeModules(); removeTempFolders(); cp.safeExec.bind(global, 'npm install npm --loglevel error', {cwd: path.resolve(__dirname, '..', 'build')}, function() { diff --git a/script/cibuild.cmd b/script/cibuild.cmd new file mode 100644 index 000000000..79197d1b1 --- /dev/null +++ b/script/cibuild.cmd @@ -0,0 +1,5 @@ +@IF EXIST "%~dp0\node.exe" ( + "%~dp0\node.exe" "%~dp0\cibuild" %* +) ELSE ( + node "%~dp0\cibuild" %* +) diff --git a/spec/integration/startup-spec.coffee b/spec/integration/startup-spec.coffee index 36342470d..799c7685f 100644 --- a/spec/integration/startup-spec.coffee +++ b/spec/integration/startup-spec.coffee @@ -4,7 +4,7 @@ return unless process.env.ATOM_INTEGRATION_TESTS_ENABLED # Integration tests require a fast machine and, for now, we cannot afford to # run them on Travis. -return if process.env.TRAVIS +return if process.env.CI fs = require "fs-plus" path = require "path" From 6520240652d2a0e55a822d8a002ac661833c4877 Mon Sep 17 00:00:00 2001 From: Indrek Ardel Date: Wed, 11 Nov 2015 01:23:07 +0200 Subject: [PATCH 23/72] Update spec --- spec/grammars-spec.coffee | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/spec/grammars-spec.coffee b/spec/grammars-spec.coffee index 82a29892a..a36a10170 100644 --- a/spec/grammars-spec.coffee +++ b/spec/grammars-spec.coffee @@ -142,9 +142,13 @@ describe "the `grammars` global", -> expect(atom.grammars.selectGrammar('Rakefile', '').scopeName).toBe 'source.coffee' expect(atom.grammars.selectGrammar('Cakefile', '').scopeName).toBe 'source.ruby' - it "favors grammars with matching first-line-regexps even if custom file types match the file", -> + it "favors user-defined file types over grammars with matching first-line-regexps", -> atom.config.set('core.customFileTypes', 'source.ruby': ['bootstrap']) - expect(atom.grammars.selectGrammar('bootstrap', '#!/usr/bin/env node').scopeName).toBe 'source.js' + expect(atom.grammars.selectGrammar('bootstrap', '#!/usr/bin/env node').scopeName).toBe 'source.ruby' + + describe "when there is a grammar with a first line pattern, the file type of the file is known, but from a different grammar", -> + it "favors file type over the matching pattern", -> + expect(atom.grammars.selectGrammar('foo.rb', '#!/usr/bin/env node').scopeName).toBe 'source.ruby' describe ".removeGrammar(grammar)", -> it "removes the grammar, so it won't be returned by selectGrammar", -> From 24511fef92473d9ff70a1f4b36e2310904264dba Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 15:55:23 -0800 Subject: [PATCH 24/72] Add custom notification for ELOOP save errors Closes #9242 --- src/pane.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pane.coffee b/src/pane.coffee index 92be02575..9886c735e 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -722,7 +722,7 @@ class Pane extends Model @notificationManager.addWarning("Unable to save file: #{error.message}") else if error.code is 'EACCES' addWarningWithPath('Unable to save file: Permission denied') - else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST'] + else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST', 'ELOOP'] addWarningWithPath('Unable to save file', detail: error.message) else if error.code is 'EROFS' addWarningWithPath('Unable to save file: Read-only file system') From cfd5b7b3540baaeda65d1f138c66445702c70ed1 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 16:20:58 -0800 Subject: [PATCH 25/72] Handle EMFILE errors on open Closes #8429 --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 80ef47c21..65a0a27fb 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -468,7 +468,7 @@ class Workspace extends Model when 'EACCES' @notificationManager.addWarning("Permission denied '#{error.path}'") return Promise.resolve() - when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL' + when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL', 'EMFILE' @notificationManager.addWarning("Unable to open '#{error.path ? uri}'", detail: error.message) return Promise.resolve() else From 9a35e4c9ec691e067bfd13ae8e4951d014a6071b Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 10 Nov 2015 16:26:52 -0800 Subject: [PATCH 26/72] :art: Extract methods for setting scroll position based on model --- src/text-editor-presenter.coffee | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 339280bf0..7bd66b87f 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -1090,8 +1090,7 @@ class TextEditorPresenter setLineHeight: (lineHeight) -> unless @lineHeight is lineHeight @lineHeight = lineHeight - unless @scrollTop? - @updateScrollTop(@model.getFirstVisibleScreenRow() * lineHeight) + @restoreScrollTopIfNeeded() @model.setLineHeightInPixels(lineHeight) @shouldUpdateHeightState = true @shouldUpdateHorizontalScrollState = true @@ -1119,8 +1118,7 @@ class TextEditorPresenter @halfWidthCharWidth = halfWidthCharWidth @koreanCharWidth = koreanCharWidth @model.setDefaultCharWidth(baseCharacterWidth, doubleWidthCharWidth, halfWidthCharWidth, koreanCharWidth) - unless @scrollLeft? - @updateScrollLeft(@model.getFirstVisibleScreenColumn() * baseCharacterWidth) + @restoreScrollLeftIfNeeded() @characterWidthsChanged() characterWidthsChanged: -> @@ -1525,6 +1523,14 @@ class TextEditorPresenter canScrollTopTo: (scrollTop) -> @scrollTop isnt @constrainScrollTop(scrollTop) + restoreScrollTopIfNeeded: -> + unless @scrollTop? + @updateScrollTop(@model.getFirstVisibleScreenRow() * @lineHeight) + + restoreScrollLeftIfNeeded: -> + unless @scrollLeft? + @updateScrollLeft(@model.getFirstVisibleScreenColumn() * @baseCharacterWidth) + onDidChangeScrollTop: (callback) -> @emitter.on 'did-change-scroll-top', callback From 0c72500b9e6c54ab5c1c0816799d21c2db82752c Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Tue, 10 Nov 2015 16:29:39 -0800 Subject: [PATCH 27/72] Set firstVisibleScreenRow property before emitting event --- src/text-editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index a419429cc..478fbed71 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -3200,8 +3200,8 @@ class TextEditor extends Model screenRow = Math.max(Math.min(screenRow, maxScreenRow), 0) unless screenRow is @firstVisibleScreenRow - @emitter.emit 'did-change-first-visible-screen-row', screenRow unless fromView @firstVisibleScreenRow = screenRow + @emitter.emit 'did-change-first-visible-screen-row', screenRow unless fromView getFirstVisibleScreenRow: -> @firstVisibleScreenRow From e95ce5d1d036fc798b0ad23ea520e9b68e093c92 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 16:30:12 -0800 Subject: [PATCH 28/72] Handle EAGAIN errors when saving pane items Closes #8202 --- src/pane.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pane.coffee b/src/pane.coffee index 9886c735e..143733a56 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -722,7 +722,7 @@ class Pane extends Model @notificationManager.addWarning("Unable to save file: #{error.message}") else if error.code is 'EACCES' addWarningWithPath('Unable to save file: Permission denied') - else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST', 'ELOOP'] + else if error.code in ['EPERM', 'EBUSY', 'UNKNOWN', 'EEXIST', 'ELOOP', 'EAGAIN'] addWarningWithPath('Unable to save file', detail: error.message) else if error.code is 'EROFS' addWarningWithPath('Unable to save file: Read-only file system') From 64d272050dfa215dbcee93efd9488abd58e81334 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Tue, 10 Nov 2015 16:35:34 -0800 Subject: [PATCH 29/72] Handle ENOTDIR errors on open Closes #7864 --- src/workspace.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/workspace.coffee b/src/workspace.coffee index 65a0a27fb..396008201 100644 --- a/src/workspace.coffee +++ b/src/workspace.coffee @@ -468,7 +468,7 @@ class Workspace extends Model when 'EACCES' @notificationManager.addWarning("Permission denied '#{error.path}'") return Promise.resolve() - when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL', 'EMFILE' + when 'EPERM', 'EBUSY', 'ENXIO', 'EIO', 'ENOTCONN', 'UNKNOWN', 'ECONNRESET', 'EINVAL', 'EMFILE', 'ENOTDIR' @notificationManager.addWarning("Unable to open '#{error.path ? uri}'", detail: error.message) return Promise.resolve() else From 38d713379f976b07550a72d4deb06312be75903c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 09:55:20 +0100 Subject: [PATCH 30/72] :art: Introduce Config::transactAsync --- spec/config-spec.coffee | 43 ++++++++++++++++++++++++++++++++++++++ src/config.coffee | 27 ++++++++++++++++++++++++ src/package-manager.coffee | 12 +++++------ 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index bb9ab89a8..766d0e1e5 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -589,6 +589,49 @@ describe "Config", -> atom.config.transact -> expect(changeSpy).not.toHaveBeenCalled() + describe ".transactAsync(callback)", -> + changeSpy = null + + beforeEach -> + changeSpy = jasmine.createSpy('onDidChange callback') + atom.config.onDidChange("foo.bar.baz", changeSpy) + + it "allows only one change event for the duration of the given promise if it gets resolved", -> + waitsForPromise -> + atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + Promise.resolve() + + runs -> + expect(changeSpy.callCount).toBe(1) + expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) + + it "allows only one change event for the duration of the given promise if it gets rejected", -> + waitsForPromise shouldReject: true, -> + atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + Promise.reject() + + runs -> + expect(changeSpy.callCount).toBe(1) + expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) + + it "allows only one change event even when the given callback throws", -> + waitsForPromise shouldReject: true, -> + atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + throw new Error("Oops!") + + runs -> + expect(changeSpy.callCount).toBe(1) + expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) + describe ".getSources()", -> it "returns an array of all of the config's source names", -> expect(atom.config.getSources()).toEqual([]) diff --git a/src/config.coffee b/src/config.coffee index 372e745c4..bf2a7eae1 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -677,6 +677,33 @@ class Config finally @endTransaction() + # Extended: Suppress calls to handler functions registered with + # {::onDidChange} and {::observe} for the duration of the {Promise} returned + # by `callback`. After the {Promise} is either resolved or rejected, handlers + # will be called once if the value for their key-path has changed. + # + # * `callback` {Function} that returns a {Promise}, which will be executed + # while suppressing calls to handlers. + # + # Returns a {Promise} that is either resolved or rejected according to the + # `{Promise}` returned by `callback`. If `callback` throws an error, a + # rejected {Promise} will be returned. + transactAsync: (callback) -> + @beginTransaction() + endTransaction = (resolveOrReject) => (args...) => + @endTransaction() + resolveOrReject(args...) + + try + result = callback() + new Promise (resolve, reject) => + result + .then(endTransaction(resolve)) + .catch(endTransaction(reject)) + catch error + @endTransaction() + Promise.reject(error) + beginTransaction: -> @transactDepth++ diff --git a/src/package-manager.coffee b/src/package-manager.coffee index d24004031..f99b8f8ed 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -418,13 +418,11 @@ class PackageManager activatePackages: (packages) -> promises = [] - @config.beginTransaction() - for pack in packages - promise = @activatePackage(pack.name) - promises.push(promise) unless pack.activationShouldBeDeferred() - Promise.all(promises) - .then(=> @config.endTransaction()) - .catch(=> @config.endTransaction()) + @config.transactAsync => + for pack in packages + promise = @activatePackage(pack.name) + promises.push(promise) unless pack.activationShouldBeDeferred() + Promise.all(promises) @observeDisabledPackages() @observePackagesWithKeymapsDisabled() promises From 68ea20a705d4a4289d6f1ae52c175c58a12d6901 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 09:56:25 +0100 Subject: [PATCH 31/72] :memo: --- src/config.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.coffee b/src/config.coffee index bf2a7eae1..a8ffade09 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -687,7 +687,7 @@ class Config # # Returns a {Promise} that is either resolved or rejected according to the # `{Promise}` returned by `callback`. If `callback` throws an error, a - # rejected {Promise} will be returned. + # rejected {Promise} will be returned instead. transactAsync: (callback) -> @beginTransaction() endTransaction = (resolveOrReject) => (args...) => From c85088fb465cd82339cc3a555fe4b83ffba57870 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 09:58:07 +0100 Subject: [PATCH 32/72] :art: --- src/config.coffee | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index a8ffade09..3bfdfdbc1 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -690,11 +690,10 @@ class Config # rejected {Promise} will be returned instead. transactAsync: (callback) -> @beginTransaction() - endTransaction = (resolveOrReject) => (args...) => - @endTransaction() - resolveOrReject(args...) - try + endTransaction = (fn) => (args...) => + @endTransaction() + fn(args...) result = callback() new Promise (resolve, reject) => result From 8c3c2dfa8dd244816ae229b333724b2f296359aa Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 09:59:41 +0100 Subject: [PATCH 33/72] :art: --- src/config.coffee | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index 3bfdfdbc1..eb752ff3d 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -696,9 +696,7 @@ class Config fn(args...) result = callback() new Promise (resolve, reject) => - result - .then(endTransaction(resolve)) - .catch(endTransaction(reject)) + result.then(endTransaction(resolve)).catch(endTransaction(reject)) catch error @endTransaction() Promise.reject(error) From 24e64ee9e16f2574be9893c23afbe19b4ad90773 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 11:21:16 +0100 Subject: [PATCH 34/72] :arrow_up: symbols-view This should fix the recurring flaky spec problem we observe during CI --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c29d36f91..c5b3a75d7 100644 --- a/package.json +++ b/package.json @@ -108,7 +108,7 @@ "spell-check": "0.63.0", "status-bar": "0.80.0", "styleguide": "0.45.0", - "symbols-view": "0.110.0", + "symbols-view": "0.110.1", "tabs": "0.88.0", "timecop": "0.33.0", "tree-view": "0.198.0", From 7d959df68347e77ab1231c81b186d1cf4c8c2549 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Sun, 6 Sep 2015 20:54:07 +0300 Subject: [PATCH 35/72] Defer activation hooks (#8313) --- src/package-manager.coffee | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index d24004031..e72956665 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -37,6 +37,7 @@ class PackageManager @emitter = new Emitter @activationHookEmitter = new Emitter @packageDirPaths = [] + @deferredActivationHooks = [] if configDirPath? and not safeMode if @devMode @packageDirPaths.push(path.join(configDirPath, "dev", "packages")) @@ -409,6 +410,8 @@ class PackageManager packages = @getLoadedPackagesForTypes(types) promises = promises.concat(activator.activatePackages(packages)) Promise.all(promises).then => + @triggerDeferredActivationHooks() + @emit 'activated' if Grim.includeDeprecatedAPIs @emitter.emit 'did-activate-initial-packages' # another type of package manager can handle other package types. @@ -441,9 +444,16 @@ class PackageManager else Promise.reject(new Error("Failed to load package '#{name}'")) + triggerDeferredActivationHooks: -> + @activationHookEmitter.emit(hook) for hook in @deferredActivationHooks + @deferredActivationHooks = null + triggerActivationHook: (hook) -> return new Error("Cannot trigger an empty activation hook") unless hook? and _.isString(hook) and hook.length > 0 - @activationHookEmitter.emit(hook) + if @deferredActivationHooks? + @deferredActivationHooks.push hook + else + @activationHookEmitter.emit(hook) onDidTriggerActivationHook: (hook, callback) -> return unless hook? and _.isString(hook) and hook.length > 0 From fe47394b22e605157ff1e8642571812a8c311b36 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Fri, 18 Sep 2015 04:45:31 +0300 Subject: [PATCH 36/72] Update specs for deferred activation hooks --- spec/package-manager-spec.coffee | 1 + src/package-manager.coffee | 1 + 2 files changed, 2 insertions(+) diff --git a/spec/package-manager-spec.coffee b/spec/package-manager-spec.coffee index 391c63dc7..4b5f3c26d 100644 --- a/spec/package-manager-spec.coffee +++ b/spec/package-manager-spec.coffee @@ -284,6 +284,7 @@ describe "PackageManager", -> expect(Package.prototype.requireMainModule.callCount).toBe 0 atom.packages.triggerActivationHook('language-fictitious:grammar-used') + atom.packages.triggerDeferredActivationHooks() waitsForPromise -> promise diff --git a/src/package-manager.coffee b/src/package-manager.coffee index e72956665..6a1a2e0a2 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -445,6 +445,7 @@ class PackageManager Promise.reject(new Error("Failed to load package '#{name}'")) triggerDeferredActivationHooks: -> + return unless @deferredActivationHooks? @activationHookEmitter.emit(hook) for hook in @deferredActivationHooks @deferredActivationHooks = null From 571686e52b1b35e2d975156a0841928a62c02739 Mon Sep 17 00:00:00 2001 From: Nikolay Yakimov Date: Sun, 11 Oct 2015 07:04:16 +0300 Subject: [PATCH 37/72] Remove deprecated call --- src/package-manager.coffee | 1 - 1 file changed, 1 deletion(-) diff --git a/src/package-manager.coffee b/src/package-manager.coffee index 6a1a2e0a2..5112ce266 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -411,7 +411,6 @@ class PackageManager promises = promises.concat(activator.activatePackages(packages)) Promise.all(promises).then => @triggerDeferredActivationHooks() - @emit 'activated' if Grim.includeDeprecatedAPIs @emitter.emit 'did-activate-initial-packages' # another type of package manager can handle other package types. From 4c3d35529809498bfb96841d1d67b10580d144f8 Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Wed, 11 Nov 2015 08:44:36 -0800 Subject: [PATCH 38/72] :shirt: Add missing space after comma --- src/text-editor.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index 478fbed71..e5b3bd481 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -88,7 +88,7 @@ class TextEditor extends Model super { - @softTabs, @firstVisibleScreenRow, @firstVisibleScreenColumn, initialLine,initialColumn, tabLength, + @softTabs, @firstVisibleScreenRow, @firstVisibleScreenColumn, initialLine, initialColumn, tabLength, softWrapped, @displayBuffer, @selectionsMarkerLayer, buffer, suppressCursorCreation, @mini, @placeholderText, lineNumberGutterVisible, largeFileMode, @config, @notificationManager, @packageManager, @clipboard, @viewRegistry, @grammarRegistry, From 84a6f0cb757adcf0b247fb01771ed394f97d4657 Mon Sep 17 00:00:00 2001 From: Eli Fatsi Date: Wed, 11 Nov 2015 10:08:12 -0700 Subject: [PATCH 39/72] Remap pane:show-item-9 to activate last pane item --- spec/pane-spec.coffee | 9 +++++++++ src/pane.coffee | 3 +++ src/register-default-commands.coffee | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 0c7a22b77..36803bde6 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -168,6 +168,15 @@ describe "Pane", -> pane.activateNextItem() expect(pane.getActiveItem()).toBe item1 + describe "::activateLastItem()", -> + it "sets the active item to the last item", -> + pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) + [item1, item2, item3] = pane.getItems() + + expect(pane.getActiveItem()).toBe item1 + pane.activateLastItem() + expect(pane.getActiveItem()).toBe item3 + describe "::moveItemRight() and ::moveItemLeft()", -> it "moves the active item to the right and left, without looping around at either end", -> pane = new Pane(paneParams(items: [new Item("A"), new Item("B"), new Item("C")])) diff --git a/src/pane.coffee b/src/pane.coffee index 143733a56..412fc5251 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -312,6 +312,9 @@ class Pane extends Model else @activateItemAtIndex(@items.length - 1) + activateLastItem: -> + @activateItemAtIndex(@items.length - 1) + # Public: Move the active tab to the right. moveItemRight: -> index = @getActiveItemIndex() diff --git a/src/register-default-commands.coffee b/src/register-default-commands.coffee index 80b7ff6c6..6c838b8c0 100644 --- a/src/register-default-commands.coffee +++ b/src/register-default-commands.coffee @@ -12,7 +12,7 @@ module.exports = ({commandRegistry, commandInstaller, config}) -> 'pane:show-item-6': -> @getModel().getActivePane().activateItemAtIndex(5) 'pane:show-item-7': -> @getModel().getActivePane().activateItemAtIndex(6) 'pane:show-item-8': -> @getModel().getActivePane().activateItemAtIndex(7) - 'pane:show-item-9': -> @getModel().getActivePane().activateItemAtIndex(8) + 'pane:show-item-9': -> @getModel().getActivePane().activateLastItem() 'pane:move-item-right': -> @getModel().getActivePane().moveItemRight() 'pane:move-item-left': -> @getModel().getActivePane().moveItemLeft() 'window:increase-font-size': -> @getModel().increaseFontSize() From 60841e574a715e4e0609ada1180698da53df392d Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 18:18:55 +0100 Subject: [PATCH 40/72] Make sure showing errors works correctly --- spec/command-installer-spec.coffee | 26 ++++++++++++++++++++++++-- src/command-installer.coffee | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/spec/command-installer-spec.coffee b/spec/command-installer-spec.coffee index 584dc193e..221da3a8b 100644 --- a/spec/command-installer-spec.coffee +++ b/spec/command-installer-spec.coffee @@ -20,10 +20,32 @@ describe "CommandInstaller on #darwin", -> spyOn(CommandInstaller::, 'getResourcesDirectory').andReturn(resourcesPath) spyOn(CommandInstaller::, 'getInstallDirectory').andReturn(installationPath) + it "shows an error dialog when installing commands interactively fails", -> + appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"]) + installer = new CommandInstaller("2.0.2", appDelegate) + spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback(new Error("an error")) + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Failed to install shell commands" + detailedMessage: "an error" + }) + + appDelegate.confirm.reset() + installer.installAtomCommand.andCallFake (__, callback) -> callback() + spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback(new Error("another error")) + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Failed to install shell commands" + detailedMessage: "another error" + }) + describe "when using a stable version of atom", -> beforeEach -> - confirm = -> - installer = new CommandInstaller("2.0.2", confirm) + installer = new CommandInstaller("2.0.2") it "symlinks the atom command as 'atom'", -> installedAtomPath = path.join(installationPath, 'atom') diff --git a/src/command-installer.coffee b/src/command-installer.coffee index 5a6a7f94e..e37e6a0e6 100644 --- a/src/command-installer.coffee +++ b/src/command-installer.coffee @@ -35,7 +35,7 @@ class CommandInstaller process.resourcesPath installShellCommandsInteractively: -> - showErrorDialog = (error) -> + showErrorDialog = (error) => @applicationDelegate.confirm message: "Failed to install shell commands" detailedMessage: error.message From 0490b1482fd81faf56c3071a8c241eb7433a01c6 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 18:19:32 +0100 Subject: [PATCH 41/72] Make sure showing success dialogs works correctly --- spec/command-installer-spec.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/command-installer-spec.coffee b/spec/command-installer-spec.coffee index 221da3a8b..84fd77a34 100644 --- a/spec/command-installer-spec.coffee +++ b/spec/command-installer-spec.coffee @@ -43,6 +43,19 @@ describe "CommandInstaller on #darwin", -> detailedMessage: "another error" }) + it "shows a success dialog when installing commands interactively succeeds", -> + appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"]) + installer = new CommandInstaller("2.0.2", appDelegate) + spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback() + spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback() + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Commands installed." + detailedMessage: "The shell commands `atom` and `apm` are installed." + }) + describe "when using a stable version of atom", -> beforeEach -> installer = new CommandInstaller("2.0.2") From b895baacbfdbb1c7eaa4a54739708215795c8f4e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 18:30:06 +0100 Subject: [PATCH 42/72] Make transactAsync private --- src/config.coffee | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/config.coffee b/src/config.coffee index eb752ff3d..888193059 100644 --- a/src/config.coffee +++ b/src/config.coffee @@ -677,10 +677,14 @@ class Config finally @endTransaction() - # Extended: Suppress calls to handler functions registered with - # {::onDidChange} and {::observe} for the duration of the {Promise} returned - # by `callback`. After the {Promise} is either resolved or rejected, handlers - # will be called once if the value for their key-path has changed. + ### + Section: Internal methods used by core + ### + + # Private: Suppress calls to handler functions registered with {::onDidChange} + # and {::observe} for the duration of the {Promise} returned by `callback`. + # After the {Promise} is either resolved or rejected, handlers will be called + # once if the value for their key-path has changed. # # * `callback` {Function} that returns a {Promise}, which will be executed # while suppressing calls to handlers. @@ -708,10 +712,6 @@ class Config @transactDepth-- @emitChangeEvent() - ### - Section: Internal methods used by core - ### - pushAtKeyPath: (keyPath, value) -> arrayValue = @get(keyPath) ? [] result = arrayValue.push(value) From 780979e122c3b686c08b0b5cdad658cbfbbaa89a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 18:18:55 +0100 Subject: [PATCH 43/72] Make sure showing errors works correctly --- spec/command-installer-spec.coffee | 26 ++++++++++++++++++++++++-- src/command-installer.coffee | 2 +- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/spec/command-installer-spec.coffee b/spec/command-installer-spec.coffee index 584dc193e..221da3a8b 100644 --- a/spec/command-installer-spec.coffee +++ b/spec/command-installer-spec.coffee @@ -20,10 +20,32 @@ describe "CommandInstaller on #darwin", -> spyOn(CommandInstaller::, 'getResourcesDirectory').andReturn(resourcesPath) spyOn(CommandInstaller::, 'getInstallDirectory').andReturn(installationPath) + it "shows an error dialog when installing commands interactively fails", -> + appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"]) + installer = new CommandInstaller("2.0.2", appDelegate) + spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback(new Error("an error")) + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Failed to install shell commands" + detailedMessage: "an error" + }) + + appDelegate.confirm.reset() + installer.installAtomCommand.andCallFake (__, callback) -> callback() + spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback(new Error("another error")) + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Failed to install shell commands" + detailedMessage: "another error" + }) + describe "when using a stable version of atom", -> beforeEach -> - confirm = -> - installer = new CommandInstaller("2.0.2", confirm) + installer = new CommandInstaller("2.0.2") it "symlinks the atom command as 'atom'", -> installedAtomPath = path.join(installationPath, 'atom') diff --git a/src/command-installer.coffee b/src/command-installer.coffee index 5a6a7f94e..e37e6a0e6 100644 --- a/src/command-installer.coffee +++ b/src/command-installer.coffee @@ -35,7 +35,7 @@ class CommandInstaller process.resourcesPath installShellCommandsInteractively: -> - showErrorDialog = (error) -> + showErrorDialog = (error) => @applicationDelegate.confirm message: "Failed to install shell commands" detailedMessage: error.message From cc30daa617bbbbb745ccf689b37c73209664200e Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 18:19:32 +0100 Subject: [PATCH 44/72] Make sure showing success dialogs works correctly --- spec/command-installer-spec.coffee | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/spec/command-installer-spec.coffee b/spec/command-installer-spec.coffee index 221da3a8b..84fd77a34 100644 --- a/spec/command-installer-spec.coffee +++ b/spec/command-installer-spec.coffee @@ -43,6 +43,19 @@ describe "CommandInstaller on #darwin", -> detailedMessage: "another error" }) + it "shows a success dialog when installing commands interactively succeeds", -> + appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"]) + installer = new CommandInstaller("2.0.2", appDelegate) + spyOn(installer, "installAtomCommand").andCallFake (__, callback) -> callback() + spyOn(installer, "installApmCommand").andCallFake (__, callback) -> callback() + + installer.installShellCommandsInteractively() + + expect(appDelegate.confirm).toHaveBeenCalledWith({ + message: "Commands installed." + detailedMessage: "The shell commands `atom` and `apm` are installed." + }) + describe "when using a stable version of atom", -> beforeEach -> installer = new CommandInstaller("2.0.2") From 37b3c45cc2ed1546607391ed784cdbb7906fe2d1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 11 Nov 2015 12:05:34 -0700 Subject: [PATCH 45/72] 1.2.0-beta3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 575cf2d00..f446ac6f6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.2.0-beta2", + "version": "1.2.0-beta3", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From ab6f26368b84dce01683bb74e7c865dac324a979 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 11 Nov 2015 12:15:14 -0700 Subject: [PATCH 46/72] Add link to comment --- src/initialize-test-window.coffee | 1 + 1 file changed, 1 insertion(+) diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 72a071fb6..d80bc11f4 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -58,6 +58,7 @@ module.exports = ({blobStore}) -> document.title = "Spec Suite" # Avoid throttling of test window by playing silence + # See related discussion in https://github.com/atom/atom/pull/9485 context = new AudioContext() source = context.createBufferSource() source.connect(context.destination) From 868b76e2d8e3603f5fd8b4ef6e32645a4dcbbae0 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Wed, 11 Nov 2015 12:17:43 -0700 Subject: [PATCH 47/72] :arrow_up: atom-keymap --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index c5b3a75d7..e33d3e3fe 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,7 @@ "electronVersion": "0.34.3", "dependencies": { "async": "0.2.6", - "atom-keymap": "^6.1.0", + "atom-keymap": "^6.1.1", "babel-core": "^5.8.21", "bootstrap": "^3.3.4", "cached-run-in-this-context": "0.4.0", From c6cb37ac88151ad234c079ad80b7167128f8f30c Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Wed, 11 Nov 2015 20:24:56 +0100 Subject: [PATCH 48/72] :art: --- spec/config-spec.coffee | 46 +++++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/spec/config-spec.coffee b/spec/config-spec.coffee index 766d0e1e5..e00cee789 100644 --- a/spec/config-spec.coffee +++ b/spec/config-spec.coffee @@ -597,38 +597,48 @@ describe "Config", -> atom.config.onDidChange("foo.bar.baz", changeSpy) it "allows only one change event for the duration of the given promise if it gets resolved", -> - waitsForPromise -> - atom.config.transactAsync -> - atom.config.set("foo.bar.baz", 1) - atom.config.set("foo.bar.baz", 2) - atom.config.set("foo.bar.baz", 3) - Promise.resolve() + promiseResult = null + transactionPromise = atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + Promise.resolve("a result") + + waitsForPromise -> transactionPromise.then (r) -> promiseResult = r runs -> + expect(promiseResult).toBe("a result") expect(changeSpy.callCount).toBe(1) expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) it "allows only one change event for the duration of the given promise if it gets rejected", -> - waitsForPromise shouldReject: true, -> - atom.config.transactAsync -> - atom.config.set("foo.bar.baz", 1) - atom.config.set("foo.bar.baz", 2) - atom.config.set("foo.bar.baz", 3) - Promise.reject() + promiseError = null + transactionPromise = atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + Promise.reject("an error") + + waitsForPromise -> transactionPromise.catch (e) -> promiseError = e runs -> + expect(promiseError).toBe("an error") expect(changeSpy.callCount).toBe(1) expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) it "allows only one change event even when the given callback throws", -> - waitsForPromise shouldReject: true, -> - atom.config.transactAsync -> - atom.config.set("foo.bar.baz", 1) - atom.config.set("foo.bar.baz", 2) - atom.config.set("foo.bar.baz", 3) - throw new Error("Oops!") + error = new Error("Oops!") + promiseError = null + transactionPromise = atom.config.transactAsync -> + atom.config.set("foo.bar.baz", 1) + atom.config.set("foo.bar.baz", 2) + atom.config.set("foo.bar.baz", 3) + throw error + + waitsForPromise -> transactionPromise.catch (e) -> promiseError = e runs -> + expect(promiseError).toBe(error) expect(changeSpy.callCount).toBe(1) expect(changeSpy.argsForCall[0][0]).toEqual(newValue: 3, oldValue: undefined) From d8bfaa62260b82ada948cdd5426112906118a8a6 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Wed, 11 Nov 2015 13:33:14 -0800 Subject: [PATCH 49/72] :arrow_up: language-ruby@0.62 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e33d3e3fe..84bba58da 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "language-php": "0.34.0", "language-property-list": "0.8.0", "language-python": "0.41.0", - "language-ruby": "0.61.0", + "language-ruby": "0.62.0", "language-ruby-on-rails": "0.24.0", "language-sass": "0.43.0", "language-shellscript": "0.20.0", From 27d8e979ced5fdfeab5f015e328a90bc45abd621 Mon Sep 17 00:00:00 2001 From: simurai Date: Thu, 12 Nov 2015 15:43:49 +0900 Subject: [PATCH 50/72] Add more file extensions to match all languages bundled with Atom --- resources/mac/atom-Info.plist | 116 ++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/resources/mac/atom-Info.plist b/resources/mac/atom-Info.plist index e5337551b..e6dbdb8a2 100644 --- a/resources/mac/atom-Info.plist +++ b/resources/mac/atom-Info.plist @@ -214,6 +214,20 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + COMMIT_EDITMSG + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Commit message + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -228,6 +242,21 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + clj + cljs + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Clojure source + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -422,6 +451,20 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + go + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Go source + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -624,6 +667,20 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + less + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Less source + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -702,6 +759,20 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + mk + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Makefile source + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -809,6 +880,21 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + mustache + hbs + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Mustache document + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -998,6 +1084,7 @@ CFBundleTypeExtensions rhtml + erb CFBundleTypeIconFile file.icns @@ -1039,6 +1126,21 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + sass + scss + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + Sass source + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions @@ -1243,6 +1345,20 @@ LSHandlerRank Alternate + + CFBundleTypeExtensions + + toml + + CFBundleTypeIconFile + file.icns + CFBundleTypeName + TOML file + CFBundleTypeRole + Editor + LSHandlerRank + Alternate + CFBundleTypeExtensions From 58bc966053e400e2caaccb1c0a79d9afb7ebf156 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Nov 2015 09:59:31 -0700 Subject: [PATCH 51/72] 1.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f446ac6f6..4d1fbbf22 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.2.0-beta3", + "version": "1.2.0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 0ec2fc55179e1328726218338c8e6751c60a5639 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Nov 2015 09:59:32 -0700 Subject: [PATCH 52/72] 1.4.0-dev --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84bba58da..d5eccff28 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.3.0-dev", + "version": "1.4.0-dev", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From c52da333327d2b71632d554e5684d29d3a10efe7 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Nov 2015 09:59:32 -0700 Subject: [PATCH 53/72] 1.3.0-beta0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 84bba58da..a158ca3a8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.3.0-dev", + "version": "1.3.0-beta0", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From fa66048d71d4edcc6f066075f2ee649a220e2e7b Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Nov 2015 17:34:48 -0700 Subject: [PATCH 54/72] Guard against focusing a destroyed pane --- spec/pane-spec.coffee | 6 ++++++ src/pane.coffee | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/spec/pane-spec.coffee b/spec/pane-spec.coffee index 36803bde6..325087263 100644 --- a/spec/pane-spec.coffee +++ b/spec/pane-spec.coffee @@ -751,6 +751,12 @@ describe "Pane", -> pane2.destroy() expect(container.root).toBe pane1 + describe "::focus()", -> + it "doesn't blow up if the pane has been destroyed", -> + pane = new Pane(paneParams()) + pane.destroy() + pane.focus() + describe "serialization", -> pane = null diff --git a/src/pane.coffee b/src/pane.coffee index 412fc5251..06ffd8f49 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -248,7 +248,7 @@ class Pane extends Model # Called by the view layer to indicate that the pane has gained focus. focus: -> @focused = true - @activate() unless @isActive() + @activate() unless @isActive() or @isDestroyed() # Called by the view layer to indicate that the pane has lost focus. blur: -> From 3b4fc84fea87dfd7f8f00bc221af9e816cc15b07 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Thu, 12 Nov 2015 17:35:05 -0700 Subject: [PATCH 55/72] 1.3.0-beta1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a158ca3a8..7c3abdf2a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.3.0-beta0", + "version": "1.3.0-beta1", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From c7ca50b2b685ea78881143ad09f3e15161aa4e38 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 13 Nov 2015 18:01:21 +0100 Subject: [PATCH 56/72] Set initialLoadComplete to true only in test mode --- src/atom-environment.coffee | 4 ++-- src/initialize-test-window.coffee | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index f98e1b835..77f8a6a2e 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -117,7 +117,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params + {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, loadBaseStylesheetsOnly} = params @state = {version: @constructor.version} @@ -183,7 +183,7 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @themes.initialLoadComplete = true + @themes.initialLoadComplete = true if loadBaseStylesheetsOnly @setBodyPlatformClass() @stylesElement = @styles.buildStylesElement() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index d80bc11f4..f7704f2d8 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -70,6 +70,7 @@ module.exports = ({blobStore}) -> buildAtomEnvironment = (params) -> params = cloneObject(params) params.blobStore = blobStore unless params.hasOwnProperty("blobStore") + params.loadBaseStylesheetsOnly = true unless params.hasOwnProperty("loadBaseStylesheetsOnly") new AtomEnvironment(params) promise = testRunner({ From 967fca72140e16aaac6b17bb27934484cae1b5fa Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 13 Nov 2015 18:51:06 +0100 Subject: [PATCH 57/72] :art: --- src/atom-environment.coffee | 4 ++-- src/initialize-test-window.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 77f8a6a2e..938010607 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -117,7 +117,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, loadBaseStylesheetsOnly} = params + {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @state = {version: @constructor.version} @@ -183,7 +183,7 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @themes.initialLoadComplete = true if loadBaseStylesheetsOnly + @themes.initialLoadComplete = true if onlyLoadBaseStyleSheets @setBodyPlatformClass() @stylesElement = @styles.buildStylesElement() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index f7704f2d8..375581a96 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -70,7 +70,7 @@ module.exports = ({blobStore}) -> buildAtomEnvironment = (params) -> params = cloneObject(params) params.blobStore = blobStore unless params.hasOwnProperty("blobStore") - params.loadBaseStylesheetsOnly = true unless params.hasOwnProperty("loadBaseStylesheetsOnly") + params.onlyLoadBaseStyleSheets = true unless params.hasOwnProperty("onlyLoadBaseStyleSheets") new AtomEnvironment(params) promise = testRunner({ From 7c6fcea44173b1273f448b26dd114cacc3de7330 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 13 Nov 2015 18:01:21 +0100 Subject: [PATCH 58/72] Set initialLoadComplete to true only in test mode --- src/atom-environment.coffee | 4 ++-- src/initialize-test-window.coffee | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 004cfbc80..dcd7ca0ea 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -116,7 +116,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params + {@applicationDelegate, @window, @document, configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @state = {version: @constructor.version} @@ -182,7 +182,7 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @themes.initialLoadComplete = true + @themes.initialLoadComplete = true if onlyLoadBaseStyleSheets @setBodyPlatformClass() @stylesElement = @styles.buildStylesElement() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index 27ef46acc..3033ede18 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -6,6 +6,11 @@ exitWithStatusCode = (status) -> remote.require('app').emit('will-quit') remote.process.exit(status) +cloneObject = (object) -> + clone = {} + clone[key] = value for key, value of object + clone + try path = require 'path' ipc = require 'ipc' @@ -53,7 +58,10 @@ try testRunner = require(testRunnerPath) legacyTestRunner = require(legacyTestRunnerPath) - buildAtomEnvironment = (params) -> new AtomEnvironment(params) + buildAtomEnvironment = (params) -> + params = cloneObject(params) + params.onlyLoadBaseStyleSheets = true unless params.hasOwnProperty("onlyLoadBaseStyleSheets") + new AtomEnvironment(params) buildDefaultApplicationDelegate = (params) -> new ApplicationDelegate() promise = testRunner({ From 7e902bc31ee4ad446c25d5d64c46871645be0dbb Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 13 Nov 2015 16:14:25 -0700 Subject: [PATCH 59/72] 1.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4d1fbbf22..0186d9948 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.2.0", + "version": "1.2.1", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 32ec2b027076003b6a8810dafcda6bca8f25607b Mon Sep 17 00:00:00 2001 From: Wliu Date: Fri, 13 Nov 2015 18:14:37 -0500 Subject: [PATCH 60/72] :checkered_flag: Add apm.cmd --- resources/win/apm.cmd | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 resources/win/apm.cmd diff --git a/resources/win/apm.cmd b/resources/win/apm.cmd new file mode 100644 index 000000000..510168983 --- /dev/null +++ b/resources/win/apm.cmd @@ -0,0 +1,3 @@ +@echo off + +"%~dp0\..\app\apm\bin\node.exe" "%~dp0\..\app\apm\lib\cli.js" %* From 62de930b032e71fed25620e019a11906ae3b85f5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 13 Nov 2015 18:01:21 +0100 Subject: [PATCH 61/72] Set initialLoadComplete to true only in test mode --- src/atom-environment.coffee | 4 ++-- src/initialize-test-window.coffee | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index f98e1b835..77f8a6a2e 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -117,7 +117,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence} = params + {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, loadBaseStylesheetsOnly} = params @state = {version: @constructor.version} @@ -183,7 +183,7 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @themes.initialLoadComplete = true + @themes.initialLoadComplete = true if loadBaseStylesheetsOnly @setBodyPlatformClass() @stylesElement = @styles.buildStylesElement() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index d80bc11f4..f7704f2d8 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -70,6 +70,7 @@ module.exports = ({blobStore}) -> buildAtomEnvironment = (params) -> params = cloneObject(params) params.blobStore = blobStore unless params.hasOwnProperty("blobStore") + params.loadBaseStylesheetsOnly = true unless params.hasOwnProperty("loadBaseStylesheetsOnly") new AtomEnvironment(params) promise = testRunner({ From 1a8e2c6f8de33dace5c0e8a14abbb6e4a1dd5274 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 13 Nov 2015 18:51:06 +0100 Subject: [PATCH 62/72] :art: --- src/atom-environment.coffee | 4 ++-- src/initialize-test-window.coffee | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/atom-environment.coffee b/src/atom-environment.coffee index 77f8a6a2e..938010607 100644 --- a/src/atom-environment.coffee +++ b/src/atom-environment.coffee @@ -117,7 +117,7 @@ class AtomEnvironment extends Model # Call .loadOrCreate instead constructor: (params={}) -> - {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, loadBaseStylesheetsOnly} = params + {@blobStore, @applicationDelegate, @window, @document, configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params @state = {version: @constructor.version} @@ -183,7 +183,7 @@ class AtomEnvironment extends Model @themes.loadBaseStylesheets() @initialStyleElements = @styles.getSnapshot() - @themes.initialLoadComplete = true if loadBaseStylesheetsOnly + @themes.initialLoadComplete = true if onlyLoadBaseStyleSheets @setBodyPlatformClass() @stylesElement = @styles.buildStylesElement() diff --git a/src/initialize-test-window.coffee b/src/initialize-test-window.coffee index f7704f2d8..375581a96 100644 --- a/src/initialize-test-window.coffee +++ b/src/initialize-test-window.coffee @@ -70,7 +70,7 @@ module.exports = ({blobStore}) -> buildAtomEnvironment = (params) -> params = cloneObject(params) params.blobStore = blobStore unless params.hasOwnProperty("blobStore") - params.loadBaseStylesheetsOnly = true unless params.hasOwnProperty("loadBaseStylesheetsOnly") + params.onlyLoadBaseStyleSheets = true unless params.hasOwnProperty("onlyLoadBaseStyleSheets") new AtomEnvironment(params) promise = testRunner({ From 42a41c4db62b36dd43b59bf60c5cca95fad7d3e4 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Fri, 13 Nov 2015 16:31:37 -0700 Subject: [PATCH 63/72] 1.3.0-beta2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7c3abdf2a..adf5d68fb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "atom", "productName": "Atom", - "version": "1.3.0-beta1", + "version": "1.3.0-beta2", "description": "A hackable text editor for the 21st Century.", "main": "./src/browser/main.js", "repository": { From 84e18b281e812741286ec1145dc1b0d188c6c036 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Sun, 15 Nov 2015 10:54:41 -0500 Subject: [PATCH 64/72] :arrow_up: markdown-preview@0.156.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d5eccff28..488080f95 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "keybinding-resolver": "0.33.0", "line-ending-selector": "0.3.0", "link": "0.31.0", - "markdown-preview": "0.156.1", + "markdown-preview": "0.156.2", "metrics": "0.53.0", "notifications": "0.61.0", "open-on-github": "0.40.0", From baf2e24e53a24d2d84a03bf1bf035bfd86bff990 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Sun, 15 Nov 2015 23:36:03 -0800 Subject: [PATCH 65/72] :arrow_up: text-buffer --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index adf5d68fb..1d7b24ce8 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "service-hub": "^0.7.0", "source-map-support": "^0.3.2", "temp": "0.8.1", - "text-buffer": "^8.0.3", + "text-buffer": "^8.0.4", "typescript-simple": "1.0.0", "underscore-plus": "^1.6.6", "yargs": "^3.23.0" From 2696f493852a265e21c6e326ca963bf947625314 Mon Sep 17 00:00:00 2001 From: abe33 Date: Mon, 16 Nov 2015 10:06:35 +0100 Subject: [PATCH 66/72] :bug: Fix typo in project deserializer method Addresses #9598 --- src/project.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/project.coffee b/src/project.coffee index 935e3a213..bb9c8be80 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -55,7 +55,7 @@ class Project extends Model ### deserialize: (state, deserializerManager) -> - states.paths = [state.path] if state.path? # backward compatibility + state.paths = [state.path] if state.path? # backward compatibility @buffers = _.compact state.buffers.map (bufferState) -> # Check that buffer's file path is accessible From cf07f44ed3c0259631a0b1001834ff7897ce1b65 Mon Sep 17 00:00:00 2001 From: Ivan Zuzak Date: Mon, 16 Nov 2015 14:37:17 +0100 Subject: [PATCH 67/72] Attaching crash reports as file attachments is an option as well --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d215e1fe..8170b0121 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -98,7 +98,7 @@ Explain the problem and include additional details to help maintainers reproduce * **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. * **Explain which behavior you expected to see instead and why.** * **Include screenshots and animated GIFs** which show you following the described steps and clearly demonstrate the problem. If you use the keyboard while following the steps, **record the GIF with the [Keybinding Resolver](https://github.com/atom/keybinding-resolver) shown**. You can use [this tool](http://www.cockos.com/licecap/) to record GIFs on OSX and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux. -* **If you're reporting that Atom crashed**, include a crash report with a stack trace from the operating system. On OSX, the crash report will be available in `Console.app` under "Diagnostic and usage information" > "User diagnostic reports". Include the crash report in the issue in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines) or put it in a [gist](https://gist.github.com/) and provide link to that gist. +* **If you're reporting that Atom crashed**, include a crash report with a stack trace from the operating system. On OSX, the crash report will be available in `Console.app` under "Diagnostic and usage information" > "User diagnostic reports". Include the crash report in the issue in a [code block](https://help.github.com/articles/markdown-basics/#multiple-lines), a [file attachment](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/), or put it in a [gist](https://gist.github.com/) and provide link to that gist. * **If the problem is related to performance**, include a [CPU profile capture and a screenshot](https://atom.io/docs/latest/hacking-atom-debugging#diagnose-performance-problems-with-the-dev-tools-cpu-profiler) with your report. * **If the Chrome's developer tools pane is shown without you triggering it**, that normally means that an exception was thrown. The Console tab will include an entry for the exception. Expand the exception so that the stack trace is visible, and provide the full exception and stack trace in a [code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines) and as a screenshot. * **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. From af22a149bdd8989f5c279863ff319bdc652d7c66 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Mon, 16 Nov 2015 13:47:23 -0800 Subject: [PATCH 68/72] Replace getLongTitle with getUniqueTitle --- src/text-editor.coffee | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/src/text-editor.coffee b/src/text-editor.coffee index e5b3bd481..29d56c6c8 100644 --- a/src/text-editor.coffee +++ b/src/text-editor.coffee @@ -586,18 +586,18 @@ class TextEditor extends Model else 'untitled' - # Essential: Get unique title for display in other parts of the UI - # such as the window title. + # Essential: Get unique title for display in other parts of the UI, such as + # the window title. # # If the editor's buffer is unsaved, its title is "untitled" # If the editor's buffer is saved, its unique title is formatted as one # of the following, # * "" when it is the only editing buffer with this file name. # * "/.../", where the "..." may be omitted - # if the the direct parent directory is already different. + # if the the direct parent directory is already different. # # Returns a {String} - getUniqueTitle: -> + getLongTitle: -> if sessionPath = @getPath() title = @getTitle() @@ -625,22 +625,6 @@ class TextEditor extends Model else 'untitled' - # Essential: Get the editor's long title for display in other parts of the UI - # such as the window title. - # - # If the editor's buffer is saved, its long title is formatted as - # " - ". If it is unsaved, its title is "untitled" - # - # Returns a {String}. - getLongTitle: -> - if sessionPath = @getPath() - fileName = path.basename(sessionPath) - directory = @project.relativize(path.dirname(sessionPath)) - directory = if directory.length > 0 then directory else path.basename(path.dirname(sessionPath)) - "#{fileName} - #{directory}" - else - 'untitled' - # Essential: Returns the {String} path of this editor's text buffer. getPath: -> @buffer.getPath() From 9b649a3108bf78ca83455fee957ba59936fd9381 Mon Sep 17 00:00:00 2001 From: simurai Date: Tue, 17 Nov 2015 11:08:57 +0900 Subject: [PATCH 69/72] :arrow_up: welcome@v0.33.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a586cd4a..46ae3ea5a 100644 --- a/package.json +++ b/package.json @@ -113,7 +113,7 @@ "timecop": "0.33.0", "tree-view": "0.198.0", "update-package-dependencies": "0.10.0", - "welcome": "0.32.0", + "welcome": "0.33.0", "whitespace": "0.32.0", "wrap-guide": "0.38.1", "language-c": "0.49.0", From 4ba4fe856b3a5c22ec1c99910ac2fc7a3df9b186 Mon Sep 17 00:00:00 2001 From: simurai Date: Tue, 17 Nov 2015 11:20:11 +0900 Subject: [PATCH 70/72] :arrow_up: language-javascript@v0.101.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 46ae3ea5a..2929251ab 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "language-html": "0.42.0", "language-hyperlink": "0.15.0", "language-java": "0.16.1", - "language-javascript": "0.100.0", + "language-javascript": "0.101.0", "language-json": "0.17.1", "language-less": "0.28.3", "language-make": "0.20.0", From 86e608dc56fb29a2d7f7a0ad95ef618abfc61c13 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Mon, 16 Nov 2015 21:53:57 -0500 Subject: [PATCH 71/72] :arrow_down: language-javascript@0.100.0 Specs need to be updated for the changes in 0.101.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2929251ab..46ae3ea5a 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,7 @@ "language-html": "0.42.0", "language-hyperlink": "0.15.0", "language-java": "0.16.1", - "language-javascript": "0.101.0", + "language-javascript": "0.100.0", "language-json": "0.17.1", "language-less": "0.28.3", "language-make": "0.20.0", From 192e804c8f726dbd52932c7fed8a0f309981dad3 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 17 Nov 2015 08:53:13 -0800 Subject: [PATCH 72/72] Fix specs. Duh. --- spec/text-editor-spec.coffee | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/spec/text-editor-spec.coffee b/spec/text-editor-spec.coffee index 05e454da3..39740ebd2 100644 --- a/spec/text-editor-spec.coffee +++ b/spec/text-editor-spec.coffee @@ -163,14 +163,8 @@ describe "TextEditor", -> expect(editor.getTitle()).toBe 'untitled' describe ".getLongTitle()", -> - it "appends the name of the containing directory to the basename of the file", -> - expect(editor.getLongTitle()).toBe 'sample.js - fixtures' - buffer.setPath(undefined) - expect(editor.getLongTitle()).toBe 'untitled' - - describe ".getUniqueTitle()", -> it "returns file name when there is no opened file with identical name", -> - expect(editor.getUniqueTitle()).toBe 'sample.js' + expect(editor.getLongTitle()).toBe 'sample.js' buffer.setPath(undefined) expect(editor.getLongTitle()).toBe 'untitled' @@ -183,8 +177,8 @@ describe "TextEditor", -> atom.workspace.open(path.join('sample-theme-2', 'readme')).then (o) -> editor2 = o runs -> - expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/readme' - expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/readme' + expect(editor1.getLongTitle()).toBe 'sample-theme-1/readme' + expect(editor2.getLongTitle()).toBe 'sample-theme-2/readme' it "or returns /.../ when opened files has identical file names", -> editor1 = null @@ -195,8 +189,8 @@ describe "TextEditor", -> atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) -> editor2 = o runs -> - expect(editor1.getUniqueTitle()).toBe 'sample-theme-1/.../main.js' - expect(editor2.getUniqueTitle()).toBe 'sample-theme-2/.../main.js' + expect(editor1.getLongTitle()).toBe 'sample-theme-1/.../main.js' + expect(editor2.getLongTitle()).toBe 'sample-theme-2/.../main.js' it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", ->