mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
Merge branch 'master' into batch-updates
This commit is contained in:
12
package.json
12
package.json
@@ -104,19 +104,19 @@
|
||||
"link": "0.30.0",
|
||||
"markdown-preview": "0.137.0",
|
||||
"metrics": "0.45.0",
|
||||
"notifications": "0.28.0",
|
||||
"open-on-github": "0.32.0",
|
||||
"notifications": "0.31.0",
|
||||
"open-on-github": "0.33.0",
|
||||
"package-generator": "0.38.0",
|
||||
"release-notes": "0.51.0",
|
||||
"settings-view": "0.183.0",
|
||||
"snippets": "0.76.0",
|
||||
"snippets": "0.77.0",
|
||||
"spell-check": "0.55.0",
|
||||
"status-bar": "0.60.0",
|
||||
"styleguide": "0.44.0",
|
||||
"symbols-view": "0.84.0",
|
||||
"symbols-view": "0.85.0",
|
||||
"tabs": "0.67.0",
|
||||
"timecop": "0.31.0",
|
||||
"tree-view": "0.162.0",
|
||||
"tree-view": "0.163.0",
|
||||
"update-package-dependencies": "0.8.0",
|
||||
"welcome": "0.24.0",
|
||||
"whitespace": "0.29.0",
|
||||
@@ -138,7 +138,7 @@
|
||||
"language-make": "0.13.0",
|
||||
"language-mustache": "0.11.0",
|
||||
"language-objective-c": "0.15.0",
|
||||
"language-perl": "0.10.0",
|
||||
"language-perl": "0.11.0",
|
||||
"language-php": "0.21.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.32.0",
|
||||
|
||||
@@ -3,6 +3,8 @@ Exec = require('child_process').exec
|
||||
path = require 'path'
|
||||
Package = require '../src/package'
|
||||
ThemeManager = require '../src/theme-manager'
|
||||
_ = require "underscore-plus"
|
||||
temp = require "temp"
|
||||
|
||||
describe "the `atom` global", ->
|
||||
describe 'window sizing methods', ->
|
||||
@@ -124,3 +126,29 @@ describe "the `atom` global", ->
|
||||
line: 2
|
||||
column: 3
|
||||
originalError: error
|
||||
|
||||
describe "saving and loading", ->
|
||||
afterEach -> atom.mode = "spec"
|
||||
|
||||
it "selects the state based on the current project paths", ->
|
||||
Atom = atom.constructor
|
||||
[dir1, dir2] = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")]
|
||||
|
||||
loadSettings = _.extend Atom.getLoadSettings(),
|
||||
initialPaths: [dir1]
|
||||
windowState: null
|
||||
|
||||
spyOn(Atom, 'getLoadSettings').andCallFake -> loadSettings
|
||||
spyOn(Atom, 'getStorageDirPath').andReturn(temp.mkdirSync("storage-dir-"))
|
||||
|
||||
atom.mode = "editor"
|
||||
atom.state.stuff = "cool"
|
||||
atom.project.setPaths([dir1, dir2])
|
||||
atom.saveSync.originalValue.call(atom)
|
||||
|
||||
atom1 = Atom.loadOrCreate("editor")
|
||||
expect(atom1.state.stuff).toBeUndefined()
|
||||
|
||||
loadSettings.initialPaths = [dir2, dir1]
|
||||
atom2 = Atom.loadOrCreate("editor")
|
||||
expect(atom2.state.stuff).toBe("cool")
|
||||
|
||||
@@ -80,6 +80,14 @@ describe "DisplayBuffer", ->
|
||||
atom.config.set('editor.softWrapAtPreferredLineLength', false)
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(10).text).toBe ' return '
|
||||
|
||||
describe "when editor width is negative", ->
|
||||
it "does not hang while wrapping", ->
|
||||
displayBuffer.setDefaultCharWidth(1)
|
||||
displayBuffer.setWidth(-1)
|
||||
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(1).text).toBe " "
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(2).text).toBe " var sort = function(items) {"
|
||||
|
||||
describe "when the line is shorter than the max line length", ->
|
||||
it "renders the line unchanged", ->
|
||||
expect(displayBuffer.tokenizedLineForScreenRow(0).text).toBe buffer.lineForRow(0)
|
||||
|
||||
@@ -438,6 +438,23 @@ describe "Project", ->
|
||||
randomPath = path.join("some", "random", "path")
|
||||
expect(atom.project.relativize(randomPath)).toBe randomPath
|
||||
|
||||
describe ".relativizePath(path)", ->
|
||||
it "returns the root path that contains the given path, and the path relativized to that root path", ->
|
||||
atom.project.addPath(temp.mkdirSync("another-path"))
|
||||
|
||||
rootPath = atom.project.getPaths()[0]
|
||||
childPath = path.join(rootPath, "some", "child", "directory")
|
||||
expect(atom.project.relativizePath(childPath)).toEqual [rootPath, path.join("some", "child", "directory")]
|
||||
|
||||
rootPath = atom.project.getPaths()[1]
|
||||
childPath = path.join(rootPath, "some", "child", "directory")
|
||||
expect(atom.project.relativizePath(childPath)).toEqual [rootPath, path.join("some", "child", "directory")]
|
||||
|
||||
describe "when the given path isn't inside of any of the project's path", ->
|
||||
it "returns null for the root path, and the given path unchanged", ->
|
||||
randomPath = path.join("some", "random", "path")
|
||||
expect(atom.project.relativizePath(randomPath)).toEqual [null, randomPath]
|
||||
|
||||
describe ".contains(path)", ->
|
||||
it "returns whether or not the given path is in one of the root directories", ->
|
||||
rootPath = atom.project.getPaths()[0]
|
||||
|
||||
@@ -794,6 +794,8 @@ describe "TextEditorComponent", ->
|
||||
it "blinks cursors when they aren't moving", ->
|
||||
cursorsNode = componentNode.querySelector('.cursors')
|
||||
|
||||
wrapperNode.focus()
|
||||
nextAnimationFrame()
|
||||
expect(cursorsNode.classList.contains('blink-off')).toBe false
|
||||
|
||||
advanceClock(component.cursorBlinkPeriod / 2)
|
||||
@@ -2481,8 +2483,7 @@ describe "TextEditorComponent", ->
|
||||
gutterWidth = componentNode.querySelector('.gutter').offsetWidth
|
||||
componentNode.style.width = gutterWidth + 14 * charWidth + editor.getVerticalScrollbarWidth() + 'px'
|
||||
advanceClock(atom.views.documentPollingInterval)
|
||||
nextAnimationFrame() # won't poll until cursor blinks
|
||||
nextAnimationFrame() # handle update requested by poll
|
||||
nextAnimationFrame()
|
||||
expect(componentNode.querySelector('.line').textContent).toBe "var quicksort "
|
||||
|
||||
it "accounts for the scroll view's padding when determining the wrap location", ->
|
||||
|
||||
@@ -1135,49 +1135,63 @@ describe "TextEditorPresenter", ->
|
||||
presenter = buildPresenter(explicitHeight: 20, scrollTop: 0)
|
||||
expect(stateForCursor(presenter, 0).width).toBe 10
|
||||
|
||||
describe ".blinkCursorsOff", ->
|
||||
it "alternates between true and false twice per ::cursorBlinkPeriod", ->
|
||||
describe ".cursorsVisible", ->
|
||||
it "alternates between true and false twice per ::cursorBlinkPeriod when the editor is focused", ->
|
||||
cursorBlinkPeriod = 100
|
||||
cursorBlinkResumeDelay = 200
|
||||
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay})
|
||||
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true})
|
||||
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setFocused(false)
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setFocused(true)
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
|
||||
it "stops alternating for ::cursorBlinkResumeDelay when a cursor moves or a cursor is added", ->
|
||||
cursorBlinkPeriod = 100
|
||||
cursorBlinkResumeDelay = 200
|
||||
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay})
|
||||
presenter = buildPresenter({cursorBlinkPeriod, cursorBlinkResumeDelay, focused: true})
|
||||
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
|
||||
expectStateUpdate presenter, -> editor.moveRight()
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
|
||||
expectStateUpdate presenter, ->
|
||||
advanceClock(cursorBlinkResumeDelay)
|
||||
advanceClock(cursorBlinkPeriod / 2)
|
||||
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
expectStateUpdate presenter, -> advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
|
||||
expectStateUpdate presenter, -> editor.addCursorAtBufferPosition([1, 0])
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe false
|
||||
expect(presenter.state.content.cursorsVisible).toBe true
|
||||
|
||||
expectStateUpdate presenter, ->
|
||||
advanceClock(cursorBlinkResumeDelay)
|
||||
advanceClock(cursorBlinkPeriod / 2)
|
||||
expect(presenter.state.content.blinkCursorsOff).toBe true
|
||||
expect(presenter.state.content.cursorsVisible).toBe false
|
||||
|
||||
describe ".highlights", ->
|
||||
stateForHighlight = (presenter, decoration) ->
|
||||
|
||||
@@ -73,7 +73,7 @@ class Atom extends Model
|
||||
# Loads and returns the serialized state corresponding to this window
|
||||
# if it exists; otherwise returns undefined.
|
||||
@loadState: (mode) ->
|
||||
statePath = @getStatePath(mode)
|
||||
statePath = @getStatePath(@getLoadSettings().initialPaths, mode)
|
||||
|
||||
if fs.existsSync(statePath)
|
||||
try
|
||||
@@ -90,14 +90,13 @@ class Atom extends Model
|
||||
|
||||
# Returns the path where the state for the current window will be
|
||||
# located if it exists.
|
||||
@getStatePath: (mode) ->
|
||||
@getStatePath: (paths, mode) ->
|
||||
switch mode
|
||||
when 'spec'
|
||||
filename = 'spec'
|
||||
when 'editor'
|
||||
{initialPaths} = @getLoadSettings()
|
||||
if initialPaths?.length > 0
|
||||
sha1 = crypto.createHash('sha1').update(initialPaths.join("\n")).digest('hex')
|
||||
if paths?.length > 0
|
||||
sha1 = crypto.createHash('sha1').update(paths.slice().sort().join("\n")).digest('hex')
|
||||
filename = "editor-#{sha1}"
|
||||
|
||||
if filename
|
||||
@@ -773,7 +772,7 @@ class Atom extends Model
|
||||
|
||||
saveSync: ->
|
||||
stateString = JSON.stringify(@state)
|
||||
if statePath = @constructor.getStatePath(@mode)
|
||||
if statePath = @constructor.getStatePath(@project?.getPaths(), @mode)
|
||||
fs.writeFileSync(statePath, stateString, 'utf8')
|
||||
else
|
||||
@getCurrentWindow().loadSettings.windowState = stateString
|
||||
|
||||
@@ -22,6 +22,7 @@ class AutoUpdateManager
|
||||
# https://github.com/Squirrel/Squirrel.Windows/issues/132
|
||||
@feedUrl = 'https://atom.io/api/updates'
|
||||
else
|
||||
@iconPath = path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
|
||||
|
||||
process.nextTick => @setupAutoUpdater()
|
||||
@@ -89,7 +90,7 @@ class AutoUpdateManager
|
||||
dialog.showMessageBox
|
||||
type: 'info'
|
||||
buttons: ['OK']
|
||||
icon: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
icon: @iconPath
|
||||
message: 'No update available.'
|
||||
title: 'No Update Available'
|
||||
detail: "Version #{@version} is the latest version."
|
||||
@@ -100,7 +101,7 @@ class AutoUpdateManager
|
||||
dialog.showMessageBox
|
||||
type: 'warning'
|
||||
buttons: ['OK']
|
||||
icon: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
|
||||
icon: @iconPath
|
||||
message: 'There was an error checking for updates.'
|
||||
title: 'Update Error'
|
||||
detail: message
|
||||
|
||||
@@ -13,12 +13,12 @@ class CursorsComponent
|
||||
@oldState ?= {cursors: {}}
|
||||
|
||||
# update blink class
|
||||
if newState.blinkCursorsOff isnt @oldState.blinkCursorsOff
|
||||
if newState.blinkCursorsOff
|
||||
@domNode.classList.add 'blink-off'
|
||||
else
|
||||
if newState.cursorsVisible isnt @oldState.cursorsVisible
|
||||
if newState.cursorsVisible
|
||||
@domNode.classList.remove 'blink-off'
|
||||
@oldState.blinkCursorsOff = newState.blinkCursorsOff
|
||||
else
|
||||
@domNode.classList.add 'blink-off'
|
||||
@oldState.cursorsVisible = newState.cursorsVisible
|
||||
|
||||
# remove cursors
|
||||
for id of @oldState.cursors
|
||||
|
||||
@@ -458,7 +458,7 @@ class DisplayBuffer extends Model
|
||||
width = @width ? @getScrollWidth()
|
||||
width -= @getVerticalScrollbarWidth()
|
||||
if width? and @defaultCharWidth > 0
|
||||
Math.floor(width / @defaultCharWidth)
|
||||
Math.max(0, Math.floor(width / @defaultCharWidth))
|
||||
else
|
||||
@editorWidthInChars
|
||||
|
||||
|
||||
@@ -266,15 +266,25 @@ class Project extends Model
|
||||
else
|
||||
undefined
|
||||
|
||||
# Public: Make the given path relative to the project directory.
|
||||
#
|
||||
# * `fullPath` {String} full path
|
||||
relativize: (fullPath) ->
|
||||
@relativizePath(fullPath)[1]
|
||||
|
||||
# Public: Get the path to the project directory that contains the given path,
|
||||
# and the relative path from that project directory to the given path.
|
||||
#
|
||||
# * `fullPath` {String} An absolute path.
|
||||
#
|
||||
# Returns an {Array} with two elements:
|
||||
# * `projectPath` The {String} path to the project directory that contains the
|
||||
# given path, or `null` if none is found.
|
||||
# * `relativePath` {String} The relative path from the project directory to
|
||||
# the given path.
|
||||
relativizePath: (fullPath) ->
|
||||
return fullPath if fullPath?.match(/[A-Za-z0-9+-.]+:\/\//) # leave path alone if it has a scheme
|
||||
for rootDirectory in @rootDirectories
|
||||
relativePath = rootDirectory.relativize(fullPath)
|
||||
return relativePath if relativePath isnt fullPath
|
||||
fullPath
|
||||
return [rootDirectory.getPath(), relativePath] unless relativePath is fullPath
|
||||
[null, fullPath]
|
||||
|
||||
# Public: Determines whether the given path (real or symbolic) is inside the
|
||||
# project's directory.
|
||||
|
||||
@@ -25,7 +25,7 @@ class TextEditorPresenter
|
||||
@observeModel()
|
||||
@observeConfig()
|
||||
@buildState()
|
||||
@startBlinkingCursors()
|
||||
@startBlinkingCursors() if @focused
|
||||
@enterBatchMode()
|
||||
|
||||
destroy: ->
|
||||
@@ -160,7 +160,7 @@ class TextEditorPresenter
|
||||
hiddenInput: {}
|
||||
content:
|
||||
scrollingVertically: false
|
||||
blinkCursorsOff: false
|
||||
cursorsVisible: false
|
||||
lines: {}
|
||||
highlights: {}
|
||||
overlays: {}
|
||||
@@ -619,6 +619,10 @@ class TextEditorPresenter
|
||||
setFocused: (focused) ->
|
||||
unless @focused is focused
|
||||
@focused = focused
|
||||
if @focused
|
||||
@startBlinkingCursors()
|
||||
else
|
||||
@stopBlinkingCursors(false)
|
||||
@updateFocusedState()
|
||||
@updateHiddenInputState()
|
||||
|
||||
@@ -1092,18 +1096,22 @@ class TextEditorPresenter
|
||||
@updateCursorState(cursor)
|
||||
|
||||
startBlinkingCursors: ->
|
||||
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink.bind(this), @getCursorBlinkPeriod() / 2)
|
||||
unless @toggleCursorBlinkHandle
|
||||
@state.content.cursorsVisible = true
|
||||
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink.bind(this), @getCursorBlinkPeriod() / 2)
|
||||
|
||||
stopBlinkingCursors: ->
|
||||
clearInterval(@toggleCursorBlinkHandle)
|
||||
stopBlinkingCursors: (visible) ->
|
||||
if @toggleCursorBlinkHandle
|
||||
@state.content.cursorsVisible = visible
|
||||
clearInterval(@toggleCursorBlinkHandle)
|
||||
@toggleCursorBlinkHandle = null
|
||||
|
||||
toggleCursorBlink: ->
|
||||
@state.content.blinkCursorsOff = not @state.content.blinkCursorsOff
|
||||
@state.content.cursorsVisible = not @state.content.cursorsVisible
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
pauseCursorBlinking: ->
|
||||
@state.content.blinkCursorsOff = false
|
||||
@stopBlinkingCursors()
|
||||
@stopBlinkingCursors(true)
|
||||
@startBlinkingCursorsAfterDelay ?= _.debounce(@startBlinkingCursors, @getCursorBlinkResumeDelay())
|
||||
@startBlinkingCursorsAfterDelay()
|
||||
@emitter.emit 'did-update-state'
|
||||
|
||||
Reference in New Issue
Block a user