Wait for next DOM update synchronously after change to avoid flakiness

--- spec/text-editor-component-spec.coffee
+++ spec/text-editor-component-spec.coffee
@@ -41,7 +41,7 @@
       horizontalScrollbarNode = componentNode.querySelector('.horizontal-scrollbar')

       component.measureDimensions()
-    waitsForNextDOMUpdate()
+      waitsForNextDOMUpdate()

   afterEach ->
     contentNode.style.width = ''
@@ -54,13 +54,11 @@
       # simulate state corruption
       component.presenter.startRow = -1
       component.presenter.endRow = 9999
-
       waitsForNextDOMUpdate()

     it "doesn't update when an animation frame was requested but the component got destroyed before its delivery", ->
       editor.setText("You shouldn't see this update.")
       component.destroy()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -89,8 +87,7 @@

         wrapperNode.style.height = 3.5 * lineHeightInPixels + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(linesNode.getBoundingClientRect().height).toBe(3.5 * lineHeightInPixels)
@@ -109,8 +106,7 @@

         verticalScrollbarNode.scrollTop = 1 * lineHeightInPixels
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         tilesNodes = component.tileNodesForLines()
@@ -152,8 +148,7 @@

         verticalScrollbarNode.scrollTop = tileSize * lineHeightInPixels + 5
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         tilesNodes = component.tileNodesForLines()
@@ -199,8 +194,7 @@
         expectTileContainsRow(tilesNodes[1], 5, top: 2 * lineHeightInPixels)

         editor.getBuffer().insert([0, 0], '\n\n')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         tilesNodes = component.tileNodesForLines()
@@ -228,22 +222,19 @@
       runs ->
         verticalScrollbarNode.scrollTop = 5 * lineHeightInPixels
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       buffer = null
       runs ->
         buffer = editor.getBuffer()
         buffer.insert([0, 0], '\n\n')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(component.lineNodeForScreenRow(3).textContent).toBe editor.tokenizedLineForScreenRow(3).text

         buffer.delete([[0, 0], [3, 0]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(component.lineNodeForScreenRow(3).textContent).toBe editor.tokenizedLineForScreenRow(3).text
@@ -301,8 +292,7 @@

         componentNode.style.width = gutterWidth + wrapperNode.getScrollWidth() + 100 + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         scrollViewWidth = scrollViewNode.offsetWidth
@@ -323,7 +313,6 @@
         expect(tileNode.style.backgroundColor).toBe(backgroundColor)

       wrapperNode.style.backgroundColor = 'rgb(255, 0, 0)'
-
       waitsForNextDOMUpdate()

       runs ->
@@ -341,8 +330,7 @@
         expect(leafNodes[0].classList.contains('trailing-whitespace')).toBe false

         editor.setText('\ta')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
@@ -359,8 +347,7 @@
         expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false

         editor.setText('\t')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
@@ -368,8 +355,7 @@
         expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false

         editor.setText('a ')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
@@ -377,7 +363,7 @@
         expect(leafNodes[0].classList.contains('leading-whitespace')).toBe false

         editor.setText('a\t')
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         leafNodes = getLeafNodes(component.lineNodeForScreenRow(0))
@@ -419,15 +405,13 @@
           expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab}and spaces#{invisibles.space}#{invisibles.eol}"

           atom.config.set("editor.showInvisibles", false)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(0).textContent).toBe " a line with tabs and spaces "

           atom.config.set("editor.showInvisibles", true)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(0).textContent).toBe "#{invisibles.space}a line with tabs#{invisibles.tab}and spaces#{invisibles.space}#{invisibles.eol}"
@@ -480,30 +464,26 @@

         runs ->
           editor.setTextInBufferRange([[10, 0], [11, 0]], "\r\n", normalizeLineEndings: false)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(10).innerHTML).toBe 'CE'

           editor.setTabLength(3)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(10).innerHTML).toBe 'CE '

           editor.setTabLength(1)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(10).innerHTML).toBe 'CE'

           editor.setTextInBufferRange([[9, 0], [9, Infinity]], ' ')
           editor.setTextInBufferRange([[11, 0], [11, Infinity]], ' ')
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(10).innerHTML).toBe 'CE'
@@ -516,7 +496,7 @@
           runs ->
             componentNode.style.width = 16 * charWidth + wrapperNode.getVerticalScrollbarWidth() + 'px'
             component.measureDimensions()
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

         it "doesn't show end of line invisibles at the end of wrapped lines", ->
           expect(component.lineNodeForScreenRow(0).textContent).toBe "a line that "
@@ -602,8 +582,7 @@

         runs ->
           editor.getBuffer().insert([13, 0], '    ')
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           line12LeafNodes = getLeafNodes(component.lineNodeForScreenRow(12))
@@ -617,9 +596,9 @@

         waitsForNextDOMUpdate()

-        runs -> editor.getBuffer().insert([12, 0], '    ')
-
-        waitsForNextDOMUpdate()
+        runs ->
+          editor.getBuffer().insert([12, 0], '    ')
+          waitsForNextDOMUpdate()

         runs ->
           line13LeafNodes = getLeafNodes(component.lineNodeForScreenRow(13))
@@ -669,8 +648,7 @@
           expect(foldedLineNode.querySelector('.fold-marker')).toBeTruthy()

           editor.unfoldBufferRow(4)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           foldedLineNode = component.lineNodeForScreenRow(4)
@@ -697,8 +675,7 @@

         verticalScrollbarNode.scrollTop = 1 * lineHeightInPixels
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         tilesNodes = component.tileNodesForLineNumbers()
@@ -720,8 +697,7 @@

         wrapperNode.style.height = 3.5 * lineHeightInPixels + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(linesNode.getBoundingClientRect().height).toBe(3.5 * lineHeightInPixels)
@@ -756,8 +732,7 @@

         verticalScrollbarNode.scrollTop = tileSize * lineHeightInPixels + 5
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         tilesNodes = component.tileNodesForLineNumbers()
@@ -797,8 +772,7 @@
         expect(component.lineNumberNodeForScreenRow(5).offsetTop).toBe 2 * lineHeightInPixels

         editor.getBuffer().insert([0, 0], '\n\n')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(component.lineNumberNodeForScreenRow(0).offsetTop).toBe 0 * lineHeightInPixels
@@ -816,7 +790,6 @@
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       wrapperNode.style.width = 30 * charWidth + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -848,8 +821,7 @@

         # Removes padding when the max number of digits goes down
         editor.getBuffer().delete([[1, 0], [2, 0]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         for screenRow in [0..8]
@@ -858,8 +830,7 @@

         # Increases padding when the max number of digits goes up
         editor.getBuffer().insert([0, 0], '\n\n')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         for screenRow in [0..8]
@@ -870,7 +841,6 @@
     it "renders the .line-numbers div at the full height of the editor even if it's taller than its content", ->
       wrapperNode.style.height = componentNode.offsetHeight + 100 + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -887,7 +857,6 @@
       # favor gutter color if it's assigned
       gutterNode.style.backgroundColor = 'rgb(255, 0, 0)'
       atom.views.performDocumentPoll() # required due to DOM change not being detected inside shadow DOM
-
       waitsForNextDOMUpdate()

       runs ->
@@ -899,29 +868,25 @@
       expect(component.gutterContainerComponent.getLineNumberGutterComponent()?).toBe true

       editor.setLineNumberGutterVisible(false)
-
       waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.gutter').style.display).toBe 'none'

         atom.config.set("editor.showLineNumbers", false)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.gutter').style.display).toBe 'none'

         editor.setLineNumberGutterVisible(true)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.gutter').style.display).toBe 'none'

         atom.config.set("editor.showLineNumbers", true)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.gutter').style.display).toBe ''
@@ -965,14 +930,12 @@
           expect(lineNumberHasClass(11, 'foldable')).toBe false

           editor.getBuffer().insert([11, 44], '\n    fold me')
-
           waitsForNextDOMUpdate()

           runs ->
             expect(lineNumberHasClass(11, 'foldable')).toBe true
             editor.undo()
-
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

           runs ->
             expect(lineNumberHasClass(11, 'foldable')).toBe false
@@ -984,16 +947,14 @@
           runs ->
             expect(lineNumberHasClass(4, 'folded')).toBe true
             editor.getBuffer().insert([0, 0], '\n')
-
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

           runs ->
             expect(lineNumberHasClass(4, 'folded')).toBe false
             expect(lineNumberHasClass(5, 'folded')).toBe true

             editor.unfoldBufferRow(5)
-
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

           runs ->
             expect(lineNumberHasClass(5, 'folded')).toBe false
@@ -1006,8 +967,7 @@
             runs ->
               componentNode.style.width = 16 * charWidth + wrapperNode.getVerticalScrollbarWidth() + 'px'
               component.measureDimensions()
-
-            waitsForNextDOMUpdate()
+              waitsForNextDOMUpdate()

           it "doesn't add the foldable class for soft-wrapped lines", ->
             expect(lineNumberHasClass(0, 'foldable')).toBe true
@@ -1044,8 +1004,7 @@
             lineNumber = component.lineNumberNodeForScreenRow(1)
             target = lineNumber.querySelector('.icon-right')
             target.dispatchEvent(buildClickEvent(target))
-
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

           runs ->
             expect(lineNumberHasClass(1, 'folded')).toBe false
@@ -1067,7 +1026,6 @@
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       wrapperNode.style.width = 20 * lineHeightInPixels + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1079,8 +1037,7 @@

         cursor2 = editor.addCursorAtScreenPosition([8, 11], autoscroll: false)
         cursor3 = editor.addCursorAtScreenPosition([4, 10], autoscroll: false)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         cursorNodes = componentNode.querySelectorAll('.cursor')
@@ -1090,13 +1047,11 @@
         expect(cursorNodes[1].style['-webkit-transform']).toBe "translate(#{Math.round(10 * charWidth)}px, #{4 * lineHeightInPixels}px)"

         verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         horizontalScrollbarNode.scrollLeft = 3.5 * charWidth
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       cursorMovedListener = null
       runs ->
@@ -1107,16 +1062,14 @@

         editor.onDidChangeCursorPosition cursorMovedListener = jasmine.createSpy('cursorMovedListener')
         cursor3.setScreenPosition([4, 11], autoscroll: false)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(cursorNodes[0].style['-webkit-transform']).toBe "translate(#{Math.round(11 * charWidth - horizontalScrollbarNode.scrollLeft)}px, #{4 * lineHeightInPixels - verticalScrollbarNode.scrollTop}px)"
         expect(cursorMovedListener).toHaveBeenCalled()

         cursor3.destroy()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         cursorNodes = componentNode.querySelectorAll('.cursor')
@@ -1127,7 +1080,6 @@
     it "accounts for character widths when positioning cursors", ->
       atom.config.set('editor.fontFamily', 'sans-serif')
       editor.setCursorScreenPosition([0, 16])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1147,7 +1099,6 @@
       atom.config.set('editor.fontFamily', 'sans-serif')
       editor.setText('he\u0301y') # e with an accent mark
       editor.setCursorBufferPosition([0, 3])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1167,7 +1118,6 @@
     it "positions cursors correctly after character widths are changed via a stylesheet change", ->
       atom.config.set('editor.fontFamily', 'sans-serif')
       editor.setCursorScreenPosition([0, 16])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1176,8 +1126,7 @@
             font-weight: bold;
           }
         """, context: 'atom-text-editor'
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         cursor = componentNode.querySelector('.cursor')
@@ -1196,7 +1145,6 @@

     it "sets the cursor to the default character width at the end of a line", ->
       editor.setCursorScreenPosition([0, Infinity])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1205,7 +1153,6 @@

     it "gives the cursor a non-zero width even if it's inside atomic tokens", ->
       editor.setCursorScreenPosition([1, 0])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1215,8 +1162,8 @@
     it "blinks cursors when they aren't moving", ->
       cursorsNode = componentNode.querySelector('.cursors')
       wrapperNode.focus()
-
-      waitsForNextDOMUpdate()
+      waitsForNextDOMUpdate()
+
       runs -> expect(cursorsNode.classList.contains('blink-off')).toBe false

       waitsFor -> cursorsNode.classList.contains('blink-off')
@@ -1225,8 +1172,7 @@
       runs ->
         # Stop blinking after moving the cursor
         editor.moveRight()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(cursorsNode.classList.contains('blink-off')).toBe false
@@ -1236,7 +1182,6 @@
     it "does not render cursors that are associated with non-empty selections", ->
       editor.setSelectedScreenRange([[0, 4], [4, 6]])
       editor.addCursorAtScreenPosition([6, 8])
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1380,7 +1325,6 @@
     it "updates selections when the line height changes", ->
       editor.setSelectedBufferRange([[1, 6], [1, 10]])
       component.setLineHeight(2)
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1390,7 +1334,6 @@
     it "updates selections when the font size changes", ->
       editor.setSelectedBufferRange([[1, 6], [1, 10]])
       component.setFontSize(10)
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1401,7 +1344,6 @@
     it "updates selections when the font family changes", ->
       editor.setSelectedBufferRange([[1, 6], [1, 10]])
       component.setFontFamily('sans-serif')
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1411,7 +1353,6 @@

     it "will flash the selection when flash:true is passed to editor::setSelectedBufferRange", ->
       editor.setSelectedBufferRange([[1, 6], [1, 10]], flash: true)
-
       waitsForNextDOMUpdate()

       selectionNode = null
@@ -1423,8 +1364,7 @@

       runs ->
         editor.setSelectedBufferRange([[1, 5], [1, 7]], flash: true)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(selectionNode.classList.contains('flash')).toBe true
@@ -1445,30 +1385,26 @@
       # Shrink editor vertically
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
         # Add decorations that are out of range
         marker2 = editor.displayBuffer.markBufferRange([[9, 0], [9, 0]])
         editor.decorateMarker(marker2, type: ['line-number', 'line'], class: 'b')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         # Scroll decorations into view
         verticalScrollbarNode.scrollTop = 4.5 * lineHeightInPixels
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineAndLineNumberHaveClass(9, 'b')).toBe true

         # Fold a line to move the decorations
         editor.foldBufferRow(5)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineAndLineNumberHaveClass(9, 'b')).toBe false
@@ -1479,23 +1415,20 @@
       editor.setSoftWrapped(true)
       componentNode.style.width = 16 * charWidth + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
         marker.destroy()
         marker = editor.markBufferRange([[0, 0], [0, 2]])
         editor.decorateMarker(marker, type: ['line-number', 'line'], class: 'b')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineNumberHasClass(0, 'b')).toBe true
         expect(lineNumberHasClass(1, 'b')).toBe false

         marker.setBufferRange([[0, 0], [0, Infinity]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineNumberHasClass(0, 'b')).toBe true
@@ -1508,7 +1441,6 @@
       expect(lineAndLineNumberHaveClass(4, 'a')).toBe false

       editor.getBuffer().insert([0, 0], '\n')
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1518,8 +1450,7 @@
         expect(lineAndLineNumberHaveClass(5, 'a')).toBe false

         marker.setBufferRange([[4, 4], [6, 4]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineAndLineNumberHaveClass(2, 'a')).toBe false
@@ -1531,7 +1462,6 @@

     it "remove decoration classes when decorations are removed", ->
       decoration.destroy()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1542,7 +1472,6 @@

     it "removes decorations when their marker is invalidated", ->
       editor.getBuffer().insert([3, 2], 'n')
-
       waitsForNextDOMUpdate()

       runs ->
@@ -1553,8 +1482,7 @@
         expect(lineAndLineNumberHaveClass(4, 'a')).toBe false

         editor.undo()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(marker.isValid()).toBe true
@@ -1587,7 +1515,6 @@
     describe "when the decoration's 'onlyEmpty' property is true", ->
       it "only applies the decoration when its marker is empty", ->
         editor.decorateMarker(marker, type: ['line-number', 'line'], class: 'only-empty', onlyEmpty: true)
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1595,8 +1522,7 @@
           expect(lineAndLineNumberHaveClass(3, 'only-empty')).toBe false

           marker.clearTail()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(lineAndLineNumberHaveClass(2, 'only-empty')).toBe false
@@ -1605,7 +1531,6 @@
     describe "when the decoration's 'onlyNonEmpty' property is true", ->
       it "only applies the decoration when its marker is non-empty", ->
         editor.decorateMarker(marker, type: ['line-number', 'line'], class: 'only-non-empty', onlyNonEmpty: true)
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1613,8 +1538,7 @@
           expect(lineAndLineNumberHaveClass(3, 'only-non-empty')).toBe true

           marker.clearTail()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(lineAndLineNumberHaveClass(2, 'only-non-empty')).toBe false
@@ -1632,14 +1556,12 @@
     it "does not render highlights for off-screen lines until they come on-screen", ->
       wrapperNode.style.height = 2.5 * lineHeightInPixels + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
         marker = editor.displayBuffer.markBufferRange([[9, 2], [9, 4]], invalidate: 'inside')
         editor.decorateMarker(marker, type: 'highlight', class: 'some-highlight')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         # Should not be rendering range containing the marker
@@ -1652,8 +1574,7 @@

         verticalScrollbarNode.scrollTop = 6 * lineHeightInPixels
         verticalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(component.presenter.endRow).toBeGreaterThan(8)
@@ -1704,8 +1625,7 @@
         expect(regions.length).toBe 0

         editor.getBuffer().undo()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(marker.isValid()).toBe true
@@ -1714,14 +1634,12 @@

     it "allows multiple space-delimited decoration classes", ->
       decoration.setProperties(type: 'highlight', class: 'foo bar')
-
       waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelectorAll('.foo.bar').length).toBe 2
         decoration.setProperties(type: 'highlight', class: 'bar baz')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelectorAll('.bar.baz').length).toBe 2
@@ -1756,8 +1674,9 @@
           waitsForNextDOMUpdate()
           runs -> expect(highlightNode.classList.contains('flash-class')).toBe true
           waits 2
-          runs -> decoration.flash('flash-class', 10)
-          waitsForNextDOMUpdate()
+          runs ->
+            decoration.flash('flash-class', 10)
+            waitsForNextDOMUpdate()
           runs -> expect(highlightNode.classList.contains('flash-class')).toBe false
           waitsFor -> highlightNode.classList.contains('flash-class')

@@ -1769,7 +1688,6 @@
         expect(originalTop).toBe(2 * lineHeightInPixels)

         editor.getBuffer().insert([0, 0], '\n')
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1783,7 +1701,6 @@
         expect(parseInt(regionStyle.top)).toBe 2 * lineHeightInPixels

         marker.setBufferRange([[5, 8], [5, 13]])
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1795,7 +1712,6 @@
         expect(componentNode.querySelector('.test-highlight')).toBeTruthy()

         decoration.setProperties(type: 'highlight', class: 'new-test-highlight')
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1821,8 +1737,7 @@
           expect(overlay).toBe item

           decoration.destroy()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           overlay = component.getTopmostDOMNode().querySelector('atom-overlay .overlay-test')
@@ -1831,7 +1746,6 @@
       it "renders the overlay element with the CSS class specified by the decoration", ->
         marker = editor.displayBuffer.markBufferRange([[2, 13], [2, 13]], invalidate: 'never')
         decoration = editor.decorateMarker(marker, {type: 'overlay', class: 'my-overlay', item})
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1845,7 +1759,6 @@
       it "renders at the head of the marker by default", ->
         marker = editor.displayBuffer.markBufferRange([[2, 5], [2, 10]], invalidate: 'never')
         decoration = editor.decorateMarker(marker, {type: 'overlay', item})
-
         waitsForNextDOMUpdate()

         runs ->
@@ -1897,16 +1810,14 @@
           expect(overlay.style.top).toBe position.top + editor.getLineHeightInPixels() + 'px'

           editor.insertText('a')
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(overlay.style.left).toBe windowWidth - itemWidth + 'px'
           expect(overlay.style.top).toBe position.top + editor.getLineHeightInPixels() + 'px'

           editor.insertText('b')
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(overlay.style.left).toBe windowWidth - itemWidth + 'px'
@@ -1921,15 +1832,13 @@
       wrapperNode.style.height = 5 * lineHeightInPixels + 'px'
       wrapperNode.style.width = 10 * charWidth + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
         expect(editor.getCursorScreenPosition()).toEqual [0, 0]
         wrapperNode.setScrollTop(3 * lineHeightInPixels)
         wrapperNode.setScrollLeft(3 * charWidth)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe 0
@@ -1937,8 +1846,7 @@

         # In bounds, not focused
         editor.setCursorBufferPosition([5, 4], autoscroll: false)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe 0
@@ -1946,8 +1854,7 @@

         # In bounds and focused
         wrapperNode.focus() # updates via state change
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe (5 * lineHeightInPixels) - wrapperNode.getScrollTop()
@@ -1955,8 +1862,7 @@

         # In bounds, not focused
         inputNode.blur() # updates via state change
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe 0
@@ -1964,8 +1870,7 @@

         # Out of bounds, not focused
         editor.setCursorBufferPosition([1, 2], autoscroll: false)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe 0
@@ -1973,8 +1878,7 @@

         # Out of bounds, focused
         inputNode.focus() # updates via state change
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(inputNode.offsetTop).toBe 0
@@ -2000,8 +1904,7 @@
           coordinates = clientCoordinatesForScreenPosition([0, 2])
           coordinates.clientY = -1
           linesNode.dispatchEvent(buildMouseEvent('mousedown', coordinates))
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(editor.getCursorScreenPosition()).toEqual [0, 0]
@@ -2037,8 +1940,7 @@

           runs ->
             linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([4, 8])))
-
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()

           runs ->
             expect(editor.getCursorScreenPosition()).toEqual [4, 8]
@@ -2168,7 +2070,6 @@
         wrapperNode.style.height = '100px'
         wrapperNode.style.width = '100px'
         component.measureDimensions()
-
         waitsForNextDOMUpdate()

         runs ->
@@ -2643,7 +2544,7 @@
         runs ->
           componentNode.style.width = 21 * charWidth + wrapperNode.getVerticalScrollbarWidth() + 'px'
           component.measureDimensions()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

       describe "when the gutter is clicked", ->
         it "selects the clicked buffer row", ->
@@ -2794,7 +2695,7 @@
         expect(componentNode.classList.contains('is-focused')).toBe true
         expect(wrapperNode.classList.contains('is-focused')).toBe true
         inputNode.blur()
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()
       runs ->
         expect(componentNode.classList.contains('is-focused')).toBe false
         expect(wrapperNode.classList.contains('is-focused')).toBe false
@@ -2810,14 +2711,12 @@
     it "adds the 'has-selection' class to the editor when there is a selection", ->
       expect(componentNode.classList.contains('has-selection')).toBe false
       editor.selectDown()
-
       waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.classList.contains('has-selection')).toBe true
         editor.moveDown()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.classList.contains('has-selection')).toBe false
@@ -2826,14 +2725,12 @@
     it "updates the vertical scrollbar when the scrollTop is changed in the model", ->
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.scrollTop).toBe 0
         wrapperNode.setScrollTop(10)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.scrollTop).toBe 10
@@ -2855,8 +2752,7 @@
         expect(horizontalScrollbarNode.scrollLeft).toBe 0

         wrapperNode.setScrollLeft(100)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         top = 0
@@ -2875,8 +2771,7 @@
         expect(wrapperNode.getScrollLeft()).toBe 0
         horizontalScrollbarNode.scrollLeft = 100
         horizontalScrollbarNode.dispatchEvent(new UIEvent('scroll'))
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(wrapperNode.getScrollLeft()).toBe 100
@@ -2886,7 +2781,6 @@
       wrapperNode.style.width = 10 * charWidth + 'px'
       component.measureDimensions()
       wrapperNode.setScrollBottom(wrapperNode.getScrollHeight())
-
       waitsForNextDOMUpdate()

       lastLineNode = null
@@ -2899,8 +2793,7 @@
         # Scroll so there's no space below the last line when the horizontal scrollbar disappears
         wrapperNode.style.width = 100 * charWidth + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         bottomOfLastLine = lastLineNode.getBoundingClientRect().bottom
@@ -2912,7 +2805,6 @@
       wrapperNode.style.width = 10 * charWidth + 'px'
       component.measureDimensions()
       wrapperNode.setScrollLeft(Infinity)
-
       waitsForNextDOMUpdate()

       runs ->
@@ -2927,7 +2819,6 @@
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       wrapperNode.style.width = '1000px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -2936,8 +2827,7 @@

         componentNode.style.width = 10 * charWidth + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.style.display).toBe ''
@@ -2945,8 +2835,7 @@

         wrapperNode.style.height = 20 * lineHeightInPixels + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.style.display).toBe 'none'
@@ -2988,7 +2877,6 @@
       wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
       wrapperNode.style.width = '1000px'
       component.measureDimensions()
-
       waitsForNextDOMUpdate()

       runs ->
@@ -2998,8 +2886,7 @@

         componentNode.style.width = 10 * charWidth + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
@@ -3008,8 +2895,7 @@

         wrapperNode.style.height = 20 * lineHeightInPixels + 'px'
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(verticalScrollbarNode.style.bottom).toBe horizontalScrollbarNode.offsetHeight + 'px'
@@ -3545,7 +3431,6 @@
       newHeight = 4 * editor.getLineHeightInPixels() + "px"
       expect(parseInt(newHeight)).toBeLessThan wrapperNode.offsetHeight
       wrapperNode.style.height = newHeight
-
       waitsForNextDOMUpdate()

       runs ->
@@ -3554,8 +3439,7 @@
         gutterWidth = componentNode.querySelector('.gutter').offsetWidth
         componentNode.style.width = gutterWidth + 14 * charWidth + wrapperNode.getVerticalScrollbarWidth() + 'px'
         atom.views.performDocumentPoll()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.line').textContent).toBe "var quicksort "
@@ -3582,16 +3466,14 @@
         expect(lineNumberHasClass(5, 'cursor-line')).toBe false

         editor.setSelectedScreenRange([[3, 4], [4, 4]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineNumberHasClass(3, 'cursor-line')).toBe true
         expect(lineNumberHasClass(4, 'cursor-line')).toBe true

         editor.setSelectedScreenRange([[3, 4], [4, 0]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineNumberHasClass(3, 'cursor-line')).toBe true
@@ -3614,8 +3496,7 @@
         expect(lineHasClass(5, 'cursor-line')).toBe false

         editor.setSelectedScreenRange([[3, 4], [4, 4]])
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(lineHasClass(2, 'cursor-line')).toBe false
@@ -3686,8 +3567,7 @@
       runs ->
         expect(componentNode.querySelector('.placeholder-text').textContent).toBe "Hello World"
         editor.setText('hey')
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(componentNode.querySelector('.placeholder-text')).toBeNull()
@@ -3820,8 +3700,7 @@
         runs ->
           expect(component.lineNodeForScreenRow(0).textContent).toBe "#{newInvisibles.space}a line with tabs#{newInvisibles.tab}and spaces#{newInvisibles.space}#{newInvisibles.eol}"
           editor.setGrammar(jsGrammar)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(component.lineNodeForScreenRow(0).textContent).toBe "#{jsInvisibles.space}a line with tabs#{jsInvisibles.tab}and spaces#{jsInvisibles.space}#{jsInvisibles.eol}"
@@ -3839,7 +3718,6 @@
         expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false

         editor.setGrammar(coffeeEditor.getGrammar())
-
         waitsForNextDOMUpdate()

         runs ->
@@ -3876,14 +3754,12 @@
         wrapperNode.setWidth(55)
         wrapperNode.setHeight(55)
         component.measureDimensions()
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         component.presenter.setHorizontalScrollbarHeight(0)
         component.presenter.setVerticalScrollbarWidth(0)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

     describe "when selecting buffer ranges", ->
       it "autoscrolls the selection if it is last unless the 'autoscroll' option is false", ->
@@ -3899,16 +3775,14 @@
           expect(wrapperNode.getScrollRight()).toBeCloseTo right, 0

           editor.setSelectedBufferRange([[0, 0], [0, 0]])
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           expect(wrapperNode.getScrollLeft()).toBe 0

           editor.setSelectedBufferRange([[6, 6], [6, 8]])
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollBottom()).toBe (7 + editor.getVerticalScrollMargin()) * 10
@@ -3930,11 +3804,11 @@
         waitsForNextDOMUpdate()
         runs ->
           wrapperNode.scrollToTop()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.selectLinesContainingCursors()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollBottom()).toBe (7 + editor.getVerticalScrollMargin()) * 10

@@ -3945,11 +3819,11 @@
           waitsForNextDOMUpdate()
           runs ->
             editor.addCursorAtScreenPosition([10, 4], autoscroll: false)
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()
           runs ->
             expect(wrapperNode.getScrollTop()).toBe 0
             editor.insertText('a')
-          waitsForNextDOMUpdate()
+            waitsForNextDOMUpdate()
           runs ->
             expect(wrapperNode.getScrollTop()).toBe 75

@@ -3986,16 +3860,15 @@

         runs ->
           expect(wrapperNode.getScrollBottom()).toBe 5.5 * 10
+
           editor.moveDown()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollBottom()).toBe 6 * 10

           editor.moveDown()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollBottom()).toBe 7 * 10
@@ -4006,18 +3879,18 @@
         waitsForNextDOMUpdate()
         runs ->
           wrapperNode.setScrollBottom(wrapperNode.getScrollHeight())
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           editor.moveUp()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollBottom()).toBe wrapperNode.getScrollHeight()
           editor.moveUp()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 7 * 10
           editor.moveUp()
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 6 * 10

@@ -4026,14 +3899,13 @@
         expect(wrapperNode.getScrollRight()).toBe 5.5 * 10

         editor.setCursorScreenPosition([0, 2])
-
         waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollRight()).toBe 5.5 * 10
+
           editor.moveRight()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         margin = null
         runs ->
@@ -4056,13 +3928,11 @@
         runs ->
           expect(wrapperNode.getScrollRight()).toBe wrapperNode.getScrollWidth()
           editor.setCursorScreenPosition([6, 62], autoscroll: false)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           editor.moveLeft()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         margin = null
         runs ->
@@ -4070,8 +3940,7 @@
           left = wrapperNode.pixelPositionForScreenPosition([6, 61]).left - margin
           expect(wrapperNode.getScrollLeft()).toBeCloseTo left, 0
           editor.moveLeft()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           left = wrapperNode.pixelPositionForScreenPosition([6, 60]).left - margin
@@ -4085,8 +3954,7 @@
         runs ->
           expect(wrapperNode.getScrollBottom()).toBe 14 * 10
           editor.insertNewline()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollBottom()).toBe 15 * 10
@@ -4098,8 +3966,7 @@

         runs ->
           editor.undo()
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
@@ -4110,13 +3977,11 @@

         runs ->
           wrapperNode.setScrollTop(40)
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           editor.setCursorBufferPosition([6, 0])
-
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()

         runs ->
           expect(wrapperNode.getScrollTop()).toBe 40
@@ -4128,54 +3993,54 @@
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.addCursorAtBufferPosition([11, 11], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.setCursorScreenPosition([11, 11], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.setCursorBufferPosition([11, 11], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.addSelectionForBufferRange([[11, 11], [11, 11]], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.addSelectionForScreenRange([[11, 11], [11, 12]], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.setSelectedBufferRange([[11, 0], [11, 1]], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.setSelectedScreenRange([[11, 0], [11, 6]], autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.clearSelections(autoscroll: false)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.addSelectionForScreenRange([[0, 0], [0, 4]])
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           editor.getCursors()[0].setScreenPosition([11, 11], autoscroll: true)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBeGreaterThan 0
           editor.getCursors()[0].setBufferPosition([0, 0], autoscroll: true)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0
           editor.getSelections()[0].setScreenRange([[11, 0], [11, 4]], autoscroll: true)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBeGreaterThan 0
           editor.getSelections()[0].setBufferRange([[0, 0], [0, 4]], autoscroll: true)
-        waitsForNextDOMUpdate()
+          waitsForNextDOMUpdate()
         runs ->
           expect(wrapperNode.getScrollTop()).toBe 0

@@ -4199,8 +4064,7 @@

       runs ->
         component.setScrollTop(60)
-
-      waitsForNextDOMUpdate()
+        waitsForNextDOMUpdate()

       runs ->
         expect(component.getVisibleRowRange()).toEqual [0, 13]


Handled invalid/none command

Handled invalid/none command

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/maximilian-krauss/kb-sharer.git/'


bug fix

bug fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


Add a formatters object to Apollos with a currency helper

error: pathspec '_source/lib/formatters.coffee' did not match any file(s) known to git

--- _source/lib/formatters.coffee
+++ _source/lib/formatters.coffee
@@ -0,0 +1,4 @@
+Apollos.formatters =
+
+  toCurrency: (num) ->
+    "$#{num.toFixed(2).replace /(\d)(?=(\d{3})+\.)/g, '$1,'}"


[fix] [osu] Fixed a random crash when something happens, no idea.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Mikuia/Mikuia.git/'


added realtime news subscription plugin for ENL website

error: pathspec 'src/plugins/server/realtimenews.coffee' did not match any file(s) known to git

--- src/plugins/server/realtimenews.coffee
+++ src/plugins/server/realtimenews.coffee
@@ -0,0 +1,67 @@
+async = require 'async'
+
+plugin =
+
+    name: 'realtimeNews'
+
+    init: (callback) ->
+
+        Bot.Server.get '/feed', AccessLevel.LEVEL_GUEST, 'Get latest activities (2 minutes)', (req, res) ->
+
+            timestamp = Date.now() - 2 * 60 * 1000
+            timestamp = parseInt(req.params.gt) if req.params.gt? and parseInt(req.params.gt) > timestamp
+
+            Database.db.collection('Chat.Public').find
+                'time':
+                    $gte: timestamp
+            .sort {time: 1}
+            .toArray (err, activities) ->
+
+                if err
+                    res.jsonp {err: err.message}
+                    return
+
+                ret = []
+
+                for act in activities
+                    continue if act.plextType isnt 'SYSTEM_BROADCAST'
+                    continue if act.team isnt 'ENLIGHTENED'
+
+                    data = null
+
+                    if act.markup.TEXT1.plain is ' captured '
+                        data =
+                            action: 'capture'
+                            lat: act.markup.PORTAL1.latE6
+                            lng: act.markup.PORTAL1.lngE6
+                            time: act.time
+                    else if act.markup.TEXT1.plain is ' destroyed an '
+                        data =
+                            action: 'destroy'
+                            lat: act.markup.PORTAL1.latE6
+                            lng: act.markup.PORTAL1.lngE6
+                            time: act.time
+                    else if act.markup.TEXT1.plain is ' deployed an '
+                        data =
+                            action: 'deploy'
+                            lat: act.markup.PORTAL1.latE6
+                            lng: act.markup.PORTAL1.lngE6
+                            time: act.time
+                    else if act.markup.TEXT1.plain is ' linked '
+                        data =
+                            action: 'link'
+                            src:
+                                lat: act.markup.PORTAL1.latE6
+                                lng: act.markup.PORTAL1.lngE6
+                            dest:
+                                lat: act.markup.PORTAL2.latE6
+                                lng: act.markup.PORTAL2.lngE6
+                            time: act.time
+
+                    ret.push data if data
+
+                res.jsonp ret
+
+        callback()
+
+module.exports = plugin


Add migration for scripts

Add migration for scripts

error: pathspec 'server/startup/migrations/v33.coffee' did not match any file(s) known to git

--- server/startup/migrations/v33.coffee
+++ server/startup/migrations/v33.coffee
@@ -0,0 +1,28 @@
+RocketChat.Migrations.add
+	version: 33
+	up: ->
+		scriptAlert = "/**\n * This scrit is out-of-date, convert to the new format\n * (https://github.com/RocketChat/Rocket.Chat/wiki/WebHook-Scripting)\n**/\n\n"
+
+		integrations = RocketChat.models.Integrations.find({
+			$or: [
+				{script: {$exists: false}, processIncomingRequestScript: {$exists: true}}
+				{script: {$exists: false}, prepareOutgoingRequestScript: {$exists: true}}
+				{script: {$exists: false}, processOutgoingResponseScript: {$exists: true}}
+			]
+		}).fetch()
+
+
+		integrations.forEach (integration) ->
+			script = integration.processIncomingRequestScript or integration.prepareOutgoingRequestScript or integration.processOutgoingResponseScript
+			RocketChat.models.Integrations.update integration._id,
+				$set:
+					script: scriptAlert + script.replace(/^/gm, '// ')
+
+
+		update =
+			$unset:
+				processIncomingRequestScript: 1
+				prepareOutgoingRequestScript: 1
+				processOutgoingResponseScript: 1
+
+		RocketChat.models.Integrations.update {}, update, {multi: true}


Fix LDAP authentication to use provided username

Use the given username after user has been authenticated against LDAP
instead of some arbitary value from LDAP that likely does not exist in
all environments.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/leonidas/qa-dashboard.git/'


Add temp error handling for updateSessions

--- server/queues/scoring.coffee
+++ server/queues/scoring.coffee
@@ -439,6 +439,7 @@
     callback "The response to that query is required to be a JSON object."
   else
     @clientResponseObject = responseObject
+
     #log.info "Verified client response!"
     callback null, responseObject

@@ -497,11 +498,12 @@

   async.map sessionIDs, retrieveOldSessionData, (err, oldScores) =>
     if err? then callback err, {"error": "There was an error retrieving the old scores"}
-
-    oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores
-    newScoreArray = bayes.updatePlayerSkills oldScoreArray
-    saveNewScoresToDatabase newScoreArray, callback
-
+    try
+      oldScoreArray = _.toArray putRankingFromMetricsIntoScoreObject @clientResponseObject, oldScores
+      newScoreArray = bayes.updatePlayerSkills oldScoreArray
+      saveNewScoresToDatabase newScoreArray, callback
+    catch e
+      callback e

 saveNewScoresToDatabase = (newScoreArray, callback) ->
   async.eachSeries newScoreArray, updateScoreInSession, (err) ->


Adding ways to show love to Liona

Adding ways to show love to Liona

error: pathspec 'scripts/love.coffee' did not match any file(s) known to git

--- scripts/love.coffee
+++ scripts/love.coffee
@@ -0,0 +1,16 @@
+# Description:
+#   Liona is just so awesome
+#
+# Commands:
+#   hubot <3
+
+module.exports = (robot) ->
+  robot.respond /\<3/i, (msg) ->
+    msg.reply "<3"
+
+  robot.respond /you\'re the best/i, (msg) ->
+    msg.reply "Awe, you're the best!"
+
+  robot.hear /dammit,? Liona/i, (msg) ->
+    msg.reply "Oh come on! What do you want from me?  I'm written on node!  Ugh, rude."
+


Debug function coloration

Debug function coloration

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/Morgan9195/language-script.git/'


Google Custom Search API initial commit

Google Custom Search API initial commit

error: pathspec 'src/scripts/google-search-api.coffee' did not match any file(s) known to git

--- src/scripts/google-search-api.coffee
+++ src/scripts/google-search-api.coffee
@@ -0,0 +1,30 @@
+# A way to interact with the Google Custom Search API.
+# This script reqire to env variables to be set:
+# HUBOT_GOOGLE_SEARCH_KEY: Google Custom Search API Key from https://code.google.com/apis/console/
+# HUBOT_GOOGLE_SEARCH_CX: Google Custom Search Engine ID from http://www.google.com/cse/manage/all
+#
+# Limits for free version is 100 queries per day per API key.
+#
+# (google|search)( me) <query> - returns URL's and Title's for 5 first results from custom search#
+#
+module.exports = (robot) ->
+  robot.respond /(google|search)( me)? (.*)/i, (msg) ->
+    msg
+      .http("https://www.googleapis.com/customsearch/v1")
+      .query
+        key: process.env.HUBOT_GOOGLE_SEARCH_KEY
+        cx: process.env.HUBOT_GOOGLE_SEARCH_CX
+        fields: "items(title,link)"
+        num: 5
+        q: msg.match[3]
+      .get() (err, res, body) ->
+        resp = "";
+        results = JSON.parse(body)
+        if results.error
+          results.error.errors.forEach (err) ->
+            resp += err.message
+        else
+          results.items.forEach (item) ->
+            resp += item.title + " - " + item.link + "\n"
+
+        msg.send resp


Change createThumbnailFromUrl to accept crossOrigin argument

#988

--- src/dropzone.coffee
+++ src/dropzone.coffee
@@ -1005,12 +1005,12 @@

     fileReader.readAsDataURL file

-  createThumbnailFromUrl: (file, imageUrl, callback) ->
+  createThumbnailFromUrl: (file, imageUrl, callback, crossOrigin) ->
     # Not using `new Image` here because of a bug in latest Chrome versions.
     # See https://github.com/enyo/dropzone/pull/226
     img = document.createElement "img"

-    img.crossOrigin = file.crossOrigin if file.crossOrigin
+    img.crossOrigin = crossOrigin if crossOrigin

     img.onload = =>
       file.width = img.width


updated imageresizer path request

updated imageresizer path request

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/domjtalbot/Portfolio.git/'


params -> options.params to fix crash bug

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/supersonic.git/'


added socket controller

added socket controller

error: pathspec 'app/controllers/socket.coffee' did not match any file(s) known to git

--- app/controllers/socket.coffee
+++ app/controllers/socket.coffee
@@ -0,0 +1,74 @@
+EventEmitter = require('events').EventEmitter
+ss = require 'socket.io-stream'
+$q = require 'q'
+fs = require 'fs'
+
+redisCONFIG = require '../../config/app/redis'
+util = require '../../lib/util'
+
+Logger = new (require '../../lib/logger')
+S3 = new (require '../../app/controllers/s3')
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+Server = (io) ->
+  if !(@ instanceof Server)
+    return new Server io
+
+  EventEmitter.call @
+
+  @io = io || null
+  @init()
+
+  util.extend @, log
+  util.inherits @, EventEmitter
+
+  return @
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+Server::init = () ->
+  @io.sockets.on 'connection', (socket) =>
+    hs = socket.handshake
+    @debug 'Socket connected to server.'
+    @notify socket.id, 'server:handshake',
+      'Successfully connected to the server.'
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+Server::notify = (id, e, data) ->
+  # @debug 'Arguments.', arguments
+
+  @debug 'Notifying socket.',
+    id: id
+    e: e
+    # data: data
+
+  @io.sockets.socket(id).emit e, data
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+Server::toArrayBuffer = (buffer) ->
+  ab = new ArrayBuffer buffer.length
+  view = new Uint8Array ab
+  i = 0
+  while i < buffer.length
+    view[i] = buffer[i]
+    ++i
+  return view
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+Server::close = (socket) ->
+  # TODO: ...
+
+# # # # # # # # # # # # # # # # # # # #
+# # # # # # # # # # # # # # # # # # # #
+
+module.exports = (io) ->
+  return Server io


平岡コミット祥太

平岡コミット祥太

error: pathspec 'scripts/ito_test.coffee' did not match any file(s) known to git

--- scripts/ito_test.coffee
+++ scripts/ito_test.coffee
@@ -0,0 +1,22 @@
+# Description:
+#   AAを表示するbot
+# Author:
+#   raoka0000
+
+module.exports = (robot) ->
+  robot.respond /(ito)/i, (msg) ->
+    text = """
+    　　　　　　　　　　　_
+    　　　　　　　　／"'￣フ／)　　　　　　　 、
+    　　　　　　　,/ ,--、 ￣､__フ　　　　 ／/
+    　　　　　　 ,ヘｌ⌒ﾉ 　　＞　　　　,／　/＿
+    　　　　　　( ＿l_"_ニ_　く＿　 ／）　／　／
+          ,＞　　　　　 フ､　　　　､､＞
+    　　　　　　　 <"　（　　　　　　フ　_＿＞
+    　　　　　　　　ヽ　 ＼､､　＿フ' ノ
+    　　　　　　　　　＼、＿＿､､,_ノ゛
+    　　　　　　　　　　 　　 〉ﾆ〉ﾆ〉
+    　　　　　　　　　 　 ,､_/ﾆ/ﾆ/
+    　　　　　　　　　　∠ｌ∠ｌ､ニ＞
+    """
+    msg.send text


Initial commit

Initial commit

Lexer of Genome Query Language.
gQL®: An efficient Genome Query Language.
BioQL®: An efficient Query Language for interpreting genome and proteome.
Author: Prabhat Kumar, http://prabhatkumar.org/.
Copyright: Sequømics Corporation, http://sequomics.com/.

error: pathspec 'src/gql/lexer.coffee' did not match any file(s) known to git


:new: Add first test

:new: Add first test

error: pathspec 'spec/helper-spec.coffee' did not match any file(s) known to git

--- spec/helper-spec.coffee
+++ spec/helper-spec.coffee
@@ -0,0 +1,9 @@
+describe 'linter helpers', ->
+  helpers = require '../lib/helpers'
+  describe '::exec', ->
+    it 'cries when no argument is passed', ->
+      gotError = false
+      try
+        helpers.exec()
+      catch erro then gotError = true
+      expect(gotError).toBe(true)


:new: Add Atom-Hack.coffee

:new: Add Atom-Hack.coffee

error: pathspec 'lib/atom-hack.coffee' did not match any file(s) known to git

--- lib/atom-hack.coffee
+++ lib/atom-hack.coffee
@@ -0,0 +1,36 @@
+
+module.exports = LinterHack =
+  activate: ->
+  deactivate: ->
+  showError:(Message)->
+    Dismissible = atom.notifications.addError Message, {dismissable: true}
+    setTimeout ->
+      Dismissible.dismiss()
+    , 5000
+  provideLinter:->
+    CP = require 'child_process'
+    Path = require 'path'
+    return {
+      scopes: ['source.hack']
+      lint: (ActiveEditor, _, {Error, Trace})->
+        return new Promise (Resolve)->
+          FilePath = ActiveEditor.getPath()
+          return unless FilePath # Files that have not be saved
+          Data = []
+          Process = CP.exec('hh_client --json', {cwd: Path.dirname(FilePath)})
+          Process.stderr.on 'data', (data)-> Data.push(data.toString())
+          Process.on 'close', ->
+            try
+              Content = JSON.parse(Data.join(''))
+            catch error then return # Ignore weird errors for now
+            return Resolve([]) if Content.passed
+            ToReturn = []
+            Content.errors.forEach (ErrorEntry)->
+              ErrorEntry = ErrorEntry.message
+              First = ErrorEntry[0]
+              Traces = []
+              for Message in ErrorEntry.slice(1)
+                Traces.push new Trace Message.descr, Message.path, [[Message.line,Message.start],[Message.line,Message.end]]
+              ToReturn.push new Error First.descr, First.path, [[First.line,First.start],[First.line,First.end]], Traces
+            Resolve(ToReturn)
+    }


Caught errors during removal of Atlas to prevent old instance remaining.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/urbanetic/meteor-atlas-util.git/'


showNotificationForFileErrors -> catchAndShowFileErrors

--- lib/tree-view.coffee
+++ lib/tree-view.coffee
@@ -562,7 +562,7 @@
     copiedPaths = if LocalStorage['tree-view:copyPath'] then JSON.parse(LocalStorage['tree-view:copyPath']) else null
     initialPaths = copiedPaths or cutPaths

-    showNotificationForFileErrors = (operation) ->
+    catchAndShowFileErrors = (operation) ->
       try
         operation()
       catch error
@@ -589,15 +589,15 @@

           if fs.isDirectorySync(initialPath)
             # use fs.copy to copy directories since read/write will fail for directories
-            showNotificationForFileErrors -> fs.copySync(initialPath, newPath)
+            catchAndShowFileErrors -> fs.copySync(initialPath, newPath)
           else
             # read the old file and write a new one at target location
-            showNotificationForFileErrors -> fs.writeFileSync(newPath, fs.readFileSync(initialPath))
+            catchAndShowFileErrors -> fs.writeFileSync(newPath, fs.readFileSync(initialPath))
         else if cutPaths
           # Only move the target if the cut target doesn't exists and if the newPath
           # is not within the initial path
           unless fs.existsSync(newPath) or !!newPath.match(new RegExp("^#{initialPath}"))
-            showNotificationForFileErrors -> fs.moveSync(initialPath, newPath)
+            catchAndShowFileErrors -> fs.moveSync(initialPath, newPath)

   add: (isCreatingFile) ->
     selectedEntry = @selectedEntry() ? @roots[0]


Fix mixed-content warnings; always use client's protocol

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/kidaa/soundcloud-javascript.git/'


bug fix

bug fix

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/bubblegroup/bubblebot.git/'


main.coffee: use jQuery

main.coffee: use jQuery

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rremizov/github-notifier.git/'


Rename copy/cut menu items to match other menu item's style

--- menus/tree-view.cson
+++ menus/tree-view.cson
@@ -36,8 +36,8 @@

   '.tree-view.multi-select':
     'Delete': 'tree-view:remove'
-    'Copy Selected': 'tree-view:copy'
-    'Cut Selected': 'tree-view:cut'
+    'Copy': 'tree-view:copy'
+    'Cut': 'tree-view:cut'
     'Paste': 'tree-view:paste'

   '.pane .item-views':


don't use subdomain variant of s3 urls

don't use subdomain variant of s3 urls

closes #30

--- lib/bot.coffee
+++ lib/bot.coffee
@@ -62,7 +62,7 @@
             "s3-#{process.env.SLACKBOT_S3_BUCKET_REGION}"
           else
             "s3"
-          success("https://#{params.Bucket}.#{domain}.amazonaws.com/#{key}")
+          success("https://#{domain}.amazonaws.com/#{params.Bucket}/#{key}")

   looker.refreshCommands = ->
     return unless looker.customCommandSpaceId


Change location to Valladolid

Change location to Valladolid

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/enrmarc/f.git/'


fixed cloud building of fullscreen applications

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/AppGyver/steroids.git/'


Clear fields if user chooses a manager from select

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/startae/hub.git/'


[#63551636] wrong event bound fixed

[#63551636] wrong event bound fixed

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/netguru/review.git/'


Code review

Code review

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/rhumlover/dm-resizer.git/'


Added a command store class for offline storage

error: pathspec 'app/scripts/lib/command-store.coffee' did not match any file(s) known to git

--- app/scripts/lib/command-store.coffee
+++ app/scripts/lib/command-store.coffee
@@ -0,0 +1,62 @@
+define [
+  "underscore"
+  "backbone"
+], (_, Backbone) ->
+  class CommandStore
+    commands: null
+    fileEntry: null
+    constructor: ->
+      _.extend this, Backbone.Events
+
+      @requestFileSystem(
+        window.PERSISTENT
+        10 * 1024 * 1024
+        @onLoad.bind this
+        @onLoadError.bind this
+      )
+
+      @on "initialised", @sync.bind this
+
+    onLoad: (fs) ->
+      @fs = fs
+      @trigger "loaded"
+
+    onLoadError: console.log.bind("error", console)
+
+    readFile: (file) ->
+      reader = new FileReader
+      reader.readAsText file
+      self = this
+      reader.onloadend = ->
+        self.commands = JSON.parse(@result) if @result
+        self.trigger "initialised"
+
+    storeCommands: ->
+      @fileEntry.createWriter ((fileWriter) =>
+        blob = new Blob [JSON.stringify @commands], type: "application/json"
+
+        fileWriter.write blob
+        fileWriter.onwriteend = console.log.bind console, "Successfully wrote file"
+        fileWriter.onerror = console.log.bind console, "Error writing file"
+      ), console.log.bind(console, "Error creating writer")
+
+    init: ->
+      return @on "loaded", @init.bind(this, arguments) unless @fs
+      @fs.root.getFile "commands.json", { create: true }, (fileEntry) =>
+        @fileEntry = fileEntry
+        fileEntry.file @readFile.bind(this), @onLoadError.bind(this)
+
+    sync: ->
+      return _.defer @trigger.bind(this, "synced") if @commands
+
+      $.getJSON "http://#{location.hostname}:4100/commands", (response) =>
+        @commands = response
+        @trigger "synced"
+        @storeCommands()
+
+    requestFileSystem: (
+      window.requestFileSystem ||
+      window.webkitRequestFileSystem
+    ).bind(window)
+
+  new CommandStore


client: add findScrollableParent util

client: add findScrollableParent util

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/andrewjcasal/koding.git/'


:memo: Convert Selection docs

:memo: Convert Selection docs

--- src/selection.coffee
+++ src/selection.coffee
@@ -2,7 +2,20 @@
 {Model} = require 'theorist'
 {pick} = require 'underscore-plus'

-# Public: Represents a selection in the {Editor}.
+# Extended: Represents a selection in the {Editor}.
+#
+# ## Events
+#
+# ### screen-range-changed
+#
+# Extended: Emit when the selection was moved.
+#
+# * `screenRange` {Range} indicating the new screenrange
+#
+# ### destroyed
+#
+# Extended: Emit when the selection was destroyed
+#
 module.exports =
 class Selection extends Model
   cursor: null
@@ -56,8 +69,8 @@

   # Public: Modifies the screen range for the selection.
   #
-  # screenRange - The new {Range} to use.
-  # options - A hash of options matching those found in {::setBufferRange}.
+  # * `screenRange` The new {Range} to use.
+  # * `options` (optional) {Object} options matching those found in {::setBufferRange}.
   setScreenRange: (screenRange, options) ->
     @setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options)

@@ -67,11 +80,10 @@

   # Public: Modifies the buffer {Range} for the selection.
   #
-  # screenRange - The new {Range} to select.
-  # options - An {Object} with the keys:
-  #   :preserveFolds - if `true`, the fold settings are preserved after the
-  #                    selection moves.
-  #   :autoscroll - if `true`, the {Editor} scrolls to the new selection.
+  # * `screenRange` The new {Range} to select.
+  # * `options` (optional) {Object} with the keys:
+  #   * `preserveFolds` if `true`, the fold settings are preserved after the selection moves.
+  #   * `autoscroll` if `true`, the {Editor} scrolls to the new selection.
   setBufferRange: (bufferRange, options={}) ->
     bufferRange = Range.fromObject(bufferRange)
     @needsAutoscroll = options.autoscroll
@@ -141,7 +153,7 @@

   # Public: Selects an entire line in the buffer.
   #
-  # row - The line {Number} to select (default: the row of the cursor).
+  # * `row` The line {Number} to select (default: the row of the cursor).
   selectLine: (row=@cursor.getBufferPosition().row) ->
     range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
     @setBufferRange(@getBufferRange().union(range))
@@ -160,7 +172,7 @@
   # Public: Selects the text from the current cursor position to a given screen
   # position.
   #
-  # position - An instance of {Point}, with a given `row` and `column`.
+  # * `position` An instance of {Point}, with a given `row` and `column`.
   selectToScreenPosition: (position) ->
     position = Point.fromObject(position)

@@ -181,7 +193,7 @@
   # Public: Selects the text from the current cursor position to a given buffer
   # position.
   #
-  # position - An instance of {Point}, with a given `row` and `column`.
+  # * `position` An instance of {Point}, with a given `row` and `column`.
   selectToBufferPosition: (position) ->
     @modifySelection => @cursor.setBufferPosition(position)

@@ -306,14 +318,14 @@

   # Public: Replaces text at the current selection.
   #
-  # text - A {String} representing the text to add
-  # options - An {Object} with keys:
-  #   :select - if `true`, selects the newly added text.
-  #   :autoIndent - if `true`, indents all inserted text appropriately.
-  #   :autoIndentNewline - if `true`, indent newline appropriately.
-  #   :autoDecreaseIndent - if `true`, decreases indent level appropriately
-  #                         (for example, when a closing bracket is inserted).
-  #   :undo - if `skip`, skips the undo stack for this operation.
+  # * `text` A {String} representing the text to add
+  # * `options` (optional) {Object} with keys:
+  #   * `select` if `true`, selects the newly added text.
+  #   * `autoIndent` if `true`, indents all inserted text appropriately.
+  #   * `autoIndentNewline` if `true`, indent newline appropriately.
+  #   * `autoDecreaseIndent` if `true`, decreases indent level appropriately
+  #     (for example, when a closing bracket is inserted).
+  #   * `undo` if `skip`, skips the undo stack for this operation.
   insertText: (text, options={}) ->
     oldBufferRange = @getBufferRange()
     @editor.unfoldBufferRow(oldBufferRange.end.row)
@@ -345,8 +357,8 @@

   # Public: Indents the given text to the suggested level based on the grammar.
   #
-  # text - The {String} to indent within the selection.
-  # indentBasis - The beginning indent level.
+  # * `text` The {String} to indent within the selection.
+  # * `indentBasis` The beginning indent level.
   normalizeIndents: (text, indentBasis) ->
     textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
     isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
@@ -378,9 +390,9 @@
   # non-whitespace characters, and otherwise inserts a tab. If the selection is
   # non empty, calls {::indentSelectedRows}.
   #
-  # options - A {Object} with the keys:
-  #   :autoIndent - If `true`, the line is indented to an automatically-inferred
-  #                 level. Otherwise, {Editor::getTabText} is inserted.
+  # * `options` (optional) {Object} with the keys:
+  #   * `autoIndent` If `true`, the line is indented to an automatically-inferred
+  #     level. Otherwise, {Editor::getTabText} is inserted.
   indent: ({ autoIndent }={}) ->
     { row, column } = @cursor.getBufferPosition()

@@ -549,16 +561,18 @@
     @cut(maintainClipboard)

   # Public: Copies the selection to the clipboard and then deletes it.
+  #
+  # * `maintainClipboard` {Boolean} (default: false) See {::copy}
   cut: (maintainClipboard=false) ->
     @copy(maintainClipboard)
     @delete()

   # Public: Copies the current selection to the clipboard.
   #
-  # If the `maintainClipboard` is set to `true`, a specific metadata property
-  # is created to store each content copied to the clipboard. The clipboard
-  # `text` still contains the concatenation of the clipboard with the
-  # current selection.
+  # * `maintainClipboard` {Boolean} if `true`, a specific metadata property
+  #   is created to store each content copied to the clipboard. The clipboard
+  #   `text` still contains the concatenation of the clipboard with the
+  #   current selection. (default: false)
   copy: (maintainClipboard=false) ->
     return if @isEmpty()
     text = @editor.buffer.getTextInRange(@getBufferRange())
@@ -598,9 +612,9 @@

   # Public: Identifies if a selection intersects with a given buffer range.
   #
-  # bufferRange - A {Range} to check against.
-  #
-  # Returns a Boolean.
+  # * `bufferRange` A {Range} to check against.
+  #
+  # Returns a {Boolean}
   intersectsBufferRange: (bufferRange) ->
     @getBufferRange().intersectsWith(bufferRange)

@@ -612,17 +626,17 @@

   # Public: Identifies if a selection intersects with another selection.
   #
-  # otherSelection - A {Selection} to check against.
-  #
-  # Returns a Boolean.
+  # * `otherSelection` A {Selection} to check against.
+  #
+  # Returns a {Boolean}
   intersectsWith: (otherSelection) ->
     @getBufferRange().intersectsWith(otherSelection.getBufferRange())

   # Public: Combines the given selection into this selection and then destroys
   # the given selection.
   #
-  # otherSelection - A {Selection} to merge with.
-  # options - A hash of options matching those found in {::setBufferRange}.
+  # * `otherSelection` A {Selection} to merge with.
+  # * `options` (optional) {Object} options matching those found in {::setBufferRange}.
   merge: (otherSelection, options) ->
     myGoalBufferRange = @getGoalBufferRange()
     otherGoalBufferRange = otherSelection.getGoalBufferRange()
@@ -638,7 +652,7 @@
   #
   # See {Range::compare} for more details.
   #
-  # otherSelection - A {Selection} to compare against.
+  # * `otherSelection` A {Selection} to compare against
   compare: (otherSelection) ->
     @getBufferRange().compare(otherSelection.getBufferRange())


min/max index on the datasource

min/max index on the datasource

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/zagushka/ui-scroll.git/'


Clean up render() promise handling and resolution.

It is no longer required to pass a Promise object to the render
method. If a render was triggered from outside the View, the
promise is resolved in the event handler instead of within the
render() method.

remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/JoshuaToenyes/stout-core.git/'


Remove open profile

Remove open profile

--- src/workspace.coffee
+++ src/workspace.coffee
@@ -402,8 +402,6 @@
       item ?= opener(atom.project.resolve(uri), options) for opener in @getOpeners() when !item
     item ?= atom.project.open(uri, options)

-    console.profile('open')
-
     Q(item)
       .then (item) =>
         if not pane
@@ -415,7 +413,6 @@
         index = pane.getActiveItemIndex()
         @emit "uri-opened"
         @emitter.emit 'did-open', {uri, pane, item, index}
-        console.profileEnd('open')
         item
       .catch (error) ->
         console.error(error.stack ? error)


support/cson to require .cson files

support/cson to require .cson files

error: pathspec 'support/cson.coffee' did not match any file(s) known to git

--- support/cson.coffee
+++ support/cson.coffee
@@ -0,0 +1,8 @@
+coffee = require 'coffee-script'
+require.extensions['.cson'] = (module, filename) ->
+  content = require('fs').readFileSync filename, 'utf8'
+  try
+    module.exports = eval coffee.compile content, bare: true
+  catch err
+    err.message = filename + ': ' + err.message
+    throw err