mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Merge branch 'master' into as-tiled-rendering
Conflicts: spec/text-editor-presenter-spec.coffee
This commit is contained in:
@@ -2,6 +2,7 @@ path = require 'path'
|
||||
CSON = require 'season'
|
||||
fs = require 'fs-plus'
|
||||
_ = require 'underscore-plus'
|
||||
normalizePackageData = require 'normalize-package-data'
|
||||
|
||||
OtherPlatforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32'].filter (platform) -> platform isnt process.platform
|
||||
|
||||
@@ -32,6 +33,7 @@ module.exports = (grunt) ->
|
||||
|
||||
modulesDirectory = path.join(appDir, 'node_modules')
|
||||
packages = {}
|
||||
invalidPackages = false
|
||||
|
||||
for moduleDirectory in fs.listSync(modulesDirectory)
|
||||
continue if path.basename(moduleDirectory) is '.bin'
|
||||
@@ -40,6 +42,13 @@ module.exports = (grunt) ->
|
||||
metadata = grunt.file.readJSON(metadataPath)
|
||||
continue unless metadata?.engines?.atom?
|
||||
|
||||
reportPackageError = (msg) ->
|
||||
invalidPackages = true
|
||||
grunt.log.error("#{metadata.name}: #{msg}")
|
||||
normalizePackageData metadata, reportPackageError, true
|
||||
if metadata.repository?.type is 'git'
|
||||
metadata.repository.url = metadata.repository.url?.replace(/^git\+/, '')
|
||||
|
||||
moduleCache = metadata._atomModuleCache ? {}
|
||||
|
||||
rm metadataPath
|
||||
@@ -79,3 +88,4 @@ module.exports = (grunt) ->
|
||||
metadata._atomKeymaps = getKeymaps(appDir)
|
||||
|
||||
grunt.file.write(path.join(appDir, 'package.json'), JSON.stringify(metadata))
|
||||
not invalidPackages
|
||||
|
||||
33
package.json
33
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.199.0",
|
||||
"version": "0.200.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -38,13 +38,13 @@
|
||||
"fuzzaldrin": "^2.1",
|
||||
"git-utils": "^3.0.0",
|
||||
"grim": "1.4.1",
|
||||
"hosted-git-info": "^2.1.2",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.4",
|
||||
"jquery": "^2.1.1",
|
||||
"less-cache": "0.22",
|
||||
"marked": "^0.3.3",
|
||||
"mixto": "^1",
|
||||
"normalize-package-data": "^2.0.0",
|
||||
"nslog": "^2.0.0",
|
||||
"oniguruma": "^4.1",
|
||||
"optimist": "0.4.0",
|
||||
@@ -65,7 +65,7 @@
|
||||
"space-pen": "3.8.2",
|
||||
"stacktrace-parser": "0.1.1",
|
||||
"temp": "0.8.1",
|
||||
"text-buffer": "^5.2",
|
||||
"text-buffer": "6.0.0",
|
||||
"theorist": "^1.0.2",
|
||||
"typescript-simple": "1.0.0",
|
||||
"underscore-plus": "^1.6.6"
|
||||
@@ -86,22 +86,21 @@
|
||||
"archive-view": "0.57.0",
|
||||
"autocomplete-atom-api": "0.9.0",
|
||||
"autocomplete-css": "0.7.2",
|
||||
"autocomplete-emojis": "2.2.2",
|
||||
"autocomplete-html": "0.7.2",
|
||||
"autocomplete-plus": "2.15.2",
|
||||
"autocomplete-plus": "2.16.3",
|
||||
"autocomplete-snippets": "1.6.1",
|
||||
"autoflow": "0.23.0",
|
||||
"autosave": "0.20.0",
|
||||
"background-tips": "0.24.0",
|
||||
"bookmarks": "0.35.0",
|
||||
"bracket-matcher": "0.74.0",
|
||||
"command-palette": "0.35.0",
|
||||
"deprecation-cop": "0.47.0",
|
||||
"command-palette": "0.36.0",
|
||||
"deprecation-cop": "0.48.0",
|
||||
"dev-live-reload": "0.46.0",
|
||||
"encoding-selector": "0.20.0",
|
||||
"exception-reporting": "0.24.0",
|
||||
"find-and-replace": "0.162.0",
|
||||
"fuzzy-finder": "0.83.0",
|
||||
"find-and-replace": "0.165.0",
|
||||
"fuzzy-finder": "0.85.0",
|
||||
"git-diff": "0.55.0",
|
||||
"go-to-line": "0.30.0",
|
||||
"grammar-selector": "0.47.0",
|
||||
@@ -109,9 +108,9 @@
|
||||
"incompatible-packages": "0.24.0",
|
||||
"keybinding-resolver": "0.32.0",
|
||||
"link": "0.30.0",
|
||||
"markdown-preview": "0.148.0",
|
||||
"metrics": "0.46.0",
|
||||
"notifications": "0.43.0",
|
||||
"markdown-preview": "0.149.0",
|
||||
"metrics": "0.48.0",
|
||||
"notifications": "0.46.0",
|
||||
"open-on-github": "0.36.0",
|
||||
"package-generator": "0.39.0",
|
||||
"release-notes": "0.52.0",
|
||||
@@ -120,11 +119,11 @@
|
||||
"spell-check": "0.58.0",
|
||||
"status-bar": "0.72.0",
|
||||
"styleguide": "0.44.0",
|
||||
"symbols-view": "0.96.0",
|
||||
"symbols-view": "0.97.0",
|
||||
"tabs": "0.68.0",
|
||||
"timecop": "0.31.0",
|
||||
"tree-view": "0.171.0",
|
||||
"update-package-dependencies": "0.9.0",
|
||||
"update-package-dependencies": "0.10.0",
|
||||
"welcome": "0.27.0",
|
||||
"whitespace": "0.29.0",
|
||||
"wrap-guide": "0.33.0",
|
||||
@@ -133,7 +132,7 @@
|
||||
"language-coffee-script": "0.40.0",
|
||||
"language-csharp": "0.5.0",
|
||||
"language-css": "0.29.0",
|
||||
"language-gfm": "0.74.0",
|
||||
"language-gfm": "0.75.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.26.0",
|
||||
"language-html": "0.37.0",
|
||||
@@ -146,7 +145,7 @@
|
||||
"language-mustache": "0.11.0",
|
||||
"language-objective-c": "0.15.0",
|
||||
"language-perl": "0.24.0",
|
||||
"language-php": "0.22.0",
|
||||
"language-php": "0.23.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.34.0",
|
||||
"language-ruby": "0.52.0",
|
||||
@@ -156,7 +155,7 @@
|
||||
"language-source": "0.9.0",
|
||||
"language-sql": "0.15.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.20.0",
|
||||
"language-todo": "0.21.0",
|
||||
"language-toml": "0.16.0",
|
||||
"language-xml": "0.28.0",
|
||||
"language-yaml": "0.22.0"
|
||||
|
||||
@@ -30,15 +30,12 @@ describe "CustomGutterComponent", ->
|
||||
|
||||
buildTestState = (customDecorations) ->
|
||||
mockTestState =
|
||||
gutters:
|
||||
content: if customDecorations then customDecorations else {}
|
||||
styles:
|
||||
scrollHeight: 100
|
||||
scrollTop: 10
|
||||
backgroundColor: 'black'
|
||||
sortedDescriptions: [{gutter, visible: true}]
|
||||
customDecorations: customDecorations
|
||||
lineNumberGutter:
|
||||
maxLineNumberDigits: 10
|
||||
lineNumbers: {}
|
||||
|
||||
mockTestState
|
||||
|
||||
it "sets the custom-decoration wrapper's scrollHeight, scrollTop, and background color", ->
|
||||
@@ -53,7 +50,7 @@ describe "CustomGutterComponent", ->
|
||||
expect(decorationsWrapperNode.style.backgroundColor).not.toBe ''
|
||||
|
||||
it "creates a new DOM node for a new decoration and adds it to the gutter at the right place", ->
|
||||
customDecorations = 'test-gutter':
|
||||
customDecorations =
|
||||
'decoration-id-1':
|
||||
top: 0
|
||||
height: 10
|
||||
@@ -75,7 +72,7 @@ describe "CustomGutterComponent", ->
|
||||
expect(decorationItem).toBe decorationItem1
|
||||
|
||||
it "updates the existing DOM node for a decoration that existed but has new properties", ->
|
||||
initialCustomDecorations = 'test-gutter':
|
||||
initialCustomDecorations =
|
||||
'decoration-id-1':
|
||||
top: 0
|
||||
height: 10
|
||||
@@ -86,7 +83,7 @@ describe "CustomGutterComponent", ->
|
||||
|
||||
# Change the dimensions and item, remove the class.
|
||||
decorationItem2 = document.createElement('div')
|
||||
changedCustomDecorations = 'test-gutter':
|
||||
changedCustomDecorations =
|
||||
'decoration-id-1':
|
||||
top: 10
|
||||
height: 20
|
||||
@@ -103,7 +100,7 @@ describe "CustomGutterComponent", ->
|
||||
expect(decorationItem).toBe decorationItem2
|
||||
|
||||
# Remove the item, add a class.
|
||||
changedCustomDecorations = 'test-gutter':
|
||||
changedCustomDecorations =
|
||||
'decoration-id-1':
|
||||
top: 10
|
||||
height: 20
|
||||
@@ -118,7 +115,7 @@ describe "CustomGutterComponent", ->
|
||||
expect(changedDecorationNode.children.length).toBe 0
|
||||
|
||||
it "removes any decorations that existed previously but aren't in the latest update", ->
|
||||
customDecorations = 'test-gutter':
|
||||
customDecorations =
|
||||
'decoration-id-1':
|
||||
top: 0
|
||||
height: 10
|
||||
@@ -127,6 +124,6 @@ describe "CustomGutterComponent", ->
|
||||
decorationsWrapperNode = gutterComponent.getDomNode().children.item(0)
|
||||
expect(decorationsWrapperNode.children.length).toBe 1
|
||||
|
||||
emptyCustomDecorations = 'test-gutter': {}
|
||||
emptyCustomDecorations = {}
|
||||
gutterComponent.updateSync(buildTestState(emptyCustomDecorations))
|
||||
expect(decorationsWrapperNode.children.length).toBe 0
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
DefaultDirectoryProvider = require "../src/default-directory-provider"
|
||||
path = require "path"
|
||||
fs = require 'fs-plus'
|
||||
temp = require "temp"
|
||||
|
||||
describe "DefaultDirectoryProvider", ->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "no events",
|
||||
"name": "package-with-empty-activation-commands",
|
||||
"version": "0.1.0",
|
||||
"activationCommands": {"atom-workspace": []}
|
||||
}
|
||||
|
||||
@@ -5,17 +5,20 @@ describe "GutterContainerComponent", ->
|
||||
[gutterContainerComponent] = []
|
||||
mockGutterContainer = {}
|
||||
|
||||
buildTestState = (sortedDescriptions) ->
|
||||
mockTestState =
|
||||
gutters:
|
||||
scrollHeight: 100
|
||||
scrollTop: 10
|
||||
backgroundColor: 'black'
|
||||
sortedDescriptions: sortedDescriptions
|
||||
customDecorations: {}
|
||||
lineNumberGutter:
|
||||
maxLineNumberDigits: 10
|
||||
lineNumbers: {}
|
||||
buildTestState = (gutters) ->
|
||||
styles =
|
||||
scrollHeight: 100
|
||||
scrollTop: 10
|
||||
backgroundColor: 'black'
|
||||
|
||||
mockTestState = {gutters: []}
|
||||
for gutter in gutters
|
||||
if gutter.name is 'line-number'
|
||||
content = {maxLineNumberDigits: 10, lineNumbers: {}}
|
||||
else
|
||||
content = {}
|
||||
mockTestState.gutters.push({gutter, styles, content, visible: gutter.visible})
|
||||
|
||||
mockTestState
|
||||
|
||||
beforeEach ->
|
||||
@@ -30,7 +33,7 @@ describe "GutterContainerComponent", ->
|
||||
describe "when updated with state that contains a new line-number gutter", ->
|
||||
it "adds a LineNumberGutterComponent to its children", ->
|
||||
lineNumberGutter = new Gutter(mockGutterContainer, {name: 'line-number'})
|
||||
testState = buildTestState([{gutter: lineNumberGutter, visible: true}])
|
||||
testState = buildTestState([lineNumberGutter])
|
||||
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 0
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
@@ -45,7 +48,7 @@ describe "GutterContainerComponent", ->
|
||||
describe "when updated with state that contains a new custom gutter", ->
|
||||
it "adds a CustomGutterComponent to its children", ->
|
||||
customGutter = new Gutter(mockGutterContainer, {name: 'custom'})
|
||||
testState = buildTestState([{gutter: customGutter, visible: true}])
|
||||
testState = buildTestState([customGutter])
|
||||
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 0
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
@@ -57,15 +60,16 @@ describe "GutterContainerComponent", ->
|
||||
|
||||
describe "when updated with state that contains a new gutter that is not visible", ->
|
||||
it "creates the gutter view but hides it, and unhides it when it is later updated to be visible", ->
|
||||
customGutter = new Gutter(mockGutterContainer, {name: 'custom'})
|
||||
testState = buildTestState([{gutter: customGutter, visible: false}])
|
||||
customGutter = new Gutter(mockGutterContainer, {name: 'custom', visible: false})
|
||||
testState = buildTestState([customGutter])
|
||||
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
|
||||
expectedCustomGutterNode = gutterContainerComponent.getDomNode().children.item(0)
|
||||
expect(expectedCustomGutterNode.style.display).toBe 'none'
|
||||
|
||||
testState = buildTestState([{gutter: customGutter, visible: true}])
|
||||
customGutter.show()
|
||||
testState = buildTestState([customGutter])
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
|
||||
expectedCustomGutterNode = gutterContainerComponent.getDomNode().children.item(0)
|
||||
@@ -74,20 +78,20 @@ describe "GutterContainerComponent", ->
|
||||
describe "when updated with a gutter that already exists", ->
|
||||
it "reuses the existing gutter view, instead of recreating it", ->
|
||||
customGutter = new Gutter(mockGutterContainer, {name: 'custom'})
|
||||
testState = buildTestState([{gutter: customGutter, visible: true}])
|
||||
testState = buildTestState([customGutter])
|
||||
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
|
||||
expectedCustomGutterNode = gutterContainerComponent.getDomNode().children.item(0)
|
||||
|
||||
testState = buildTestState([{gutter: customGutter, visible: true}])
|
||||
testState = buildTestState([customGutter])
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
|
||||
expect(gutterContainerComponent.getDomNode().children.item(0)).toBe expectedCustomGutterNode
|
||||
|
||||
it "removes a gutter from the DOM if it does not appear in the latest state update", ->
|
||||
lineNumberGutter = new Gutter(mockGutterContainer, {name: 'line-number'})
|
||||
testState = buildTestState([{gutter: lineNumberGutter, visible: true}])
|
||||
testState = buildTestState([lineNumberGutter])
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
|
||||
@@ -99,7 +103,7 @@ describe "GutterContainerComponent", ->
|
||||
it "positions (and repositions) the gutters to match the order they appear in each state update", ->
|
||||
lineNumberGutter = new Gutter(mockGutterContainer, {name: 'line-number'})
|
||||
customGutter1 = new Gutter(mockGutterContainer, {name: 'custom', priority: -100})
|
||||
testState = buildTestState([{gutter: customGutter1, visible: true}, {gutter: lineNumberGutter, visible: true}])
|
||||
testState = buildTestState([customGutter1, lineNumberGutter])
|
||||
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 2
|
||||
@@ -110,11 +114,7 @@ describe "GutterContainerComponent", ->
|
||||
|
||||
# Add a gutter.
|
||||
customGutter2 = new Gutter(mockGutterContainer, {name: 'custom2', priority: -10})
|
||||
testState = buildTestState([
|
||||
{gutter: customGutter1, visible: true},
|
||||
{gutter: customGutter2, visible: true},
|
||||
{gutter: lineNumberGutter, visible: true}
|
||||
])
|
||||
testState = buildTestState([customGutter1, customGutter2, lineNumberGutter])
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 3
|
||||
expectedCustomGutterNode1 = gutterContainerComponent.getDomNode().children.item(0)
|
||||
@@ -125,12 +125,9 @@ describe "GutterContainerComponent", ->
|
||||
expect(expectedLineNumbersNode).toBe atom.views.getView(lineNumberGutter)
|
||||
|
||||
# Hide one gutter, reposition one gutter, remove one gutter; and add a new gutter.
|
||||
customGutter2.hide()
|
||||
customGutter3 = new Gutter(mockGutterContainer, {name: 'custom3', priority: 100})
|
||||
testState = buildTestState([
|
||||
{gutter: customGutter2, visible: false},
|
||||
{gutter: customGutter1, visible: true},
|
||||
{gutter: customGutter3, visible: true}
|
||||
])
|
||||
testState = buildTestState([customGutter2, customGutter1, customGutter3])
|
||||
gutterContainerComponent.updateSync(testState)
|
||||
expect(gutterContainerComponent.getDomNode().children.length).toBe 3
|
||||
expectedCustomGutterNode2 = gutterContainerComponent.getDomNode().children.item(0)
|
||||
|
||||
@@ -313,7 +313,7 @@ window.waitsForPromise = (args...) ->
|
||||
else
|
||||
promise.then(moveOn)
|
||||
promise.catch.call promise, (error) ->
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with #{jasmine.pp(error)}")
|
||||
jasmine.getEnv().currentSpec.fail("Expected promise to be resolved, but it was rejected with: #{error?.message} #{jasmine.pp(error)}")
|
||||
moveOn()
|
||||
|
||||
window.resetTimeouts = ->
|
||||
|
||||
@@ -2266,13 +2266,13 @@ describe "TextEditorComponent", ->
|
||||
editor.setText("")
|
||||
componentNode.dispatchEvent(buildTextInputEvent(data: 'x', target: inputNode))
|
||||
|
||||
currentTime += 99
|
||||
currentTime += 100
|
||||
componentNode.dispatchEvent(buildTextInputEvent(data: 'y', target: inputNode))
|
||||
|
||||
currentTime += 99
|
||||
currentTime += 100
|
||||
componentNode.dispatchEvent(new CustomEvent('editor:duplicate-lines', bubbles: true, cancelable: true))
|
||||
|
||||
currentTime += 100
|
||||
currentTime += 101
|
||||
componentNode.dispatchEvent(new CustomEvent('editor:duplicate-lines', bubbles: true, cancelable: true))
|
||||
expect(editor.getText()).toBe "xy\nxy\nxy"
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
44
spec/workspace-element-spec.coffee
Normal file
44
spec/workspace-element-spec.coffee
Normal file
@@ -0,0 +1,44 @@
|
||||
ipc = require 'ipc'
|
||||
path = require 'path'
|
||||
temp = require('temp').track()
|
||||
|
||||
describe "WorkspaceElement", ->
|
||||
workspaceElement = null
|
||||
|
||||
beforeEach ->
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
describe "the 'window:run-package-specs' command", ->
|
||||
it "runs the package specs for the active item's project path, or the first project path", ->
|
||||
spyOn(ipc, 'send')
|
||||
|
||||
# No project paths. Don't try to run specs.
|
||||
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
|
||||
expect(ipc.send).not.toHaveBeenCalledWith("run-package-specs")
|
||||
|
||||
projectPaths = [temp.mkdirSync("dir1-"), temp.mkdirSync("dir2-")]
|
||||
atom.project.setPaths(projectPaths)
|
||||
|
||||
# No active item. Use first project directory.
|
||||
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
|
||||
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
|
||||
ipc.send.reset()
|
||||
|
||||
# Active item doesn't implement ::getPath(). Use first project directory.
|
||||
item = document.createElement("div")
|
||||
atom.workspace.getActivePane().activateItem(item)
|
||||
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
|
||||
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
|
||||
ipc.send.reset()
|
||||
|
||||
# Active item has no path. Use first project directory.
|
||||
item.getPath = -> null
|
||||
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
|
||||
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[0], "spec"))
|
||||
ipc.send.reset()
|
||||
|
||||
# Active item has path. Use project path for item path.
|
||||
item.getPath = -> path.join(projectPaths[1], "a-file.txt")
|
||||
atom.commands.dispatch(workspaceElement, "window:run-package-specs")
|
||||
expect(ipc.send).toHaveBeenCalledWith("run-package-specs", path.join(projectPaths[1], "spec"))
|
||||
ipc.send.reset()
|
||||
@@ -56,6 +56,7 @@ class AtomApplication
|
||||
atomProtocolHandler: null
|
||||
resourcePath: null
|
||||
version: null
|
||||
quitting: false
|
||||
|
||||
exit: (status) -> app.exit(status)
|
||||
|
||||
@@ -104,7 +105,7 @@ class AtomApplication
|
||||
if process.platform in ['win32', 'linux']
|
||||
app.quit()
|
||||
return
|
||||
@saveState() unless window.isSpec
|
||||
@saveState() unless window.isSpec or @quitting
|
||||
|
||||
# Public: Adds the {AtomWindow} to the global window list.
|
||||
addWindow: (window) ->
|
||||
@@ -208,6 +209,9 @@ class AtomApplication
|
||||
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
|
||||
@openPathOnEvent('application:open-license', path.join(process.resourcesPath, 'LICENSE.md'))
|
||||
|
||||
app.on 'before-quit', =>
|
||||
@quitting = true
|
||||
|
||||
app.on 'will-quit', =>
|
||||
@killAllProcesses()
|
||||
@deleteSocketFile()
|
||||
|
||||
@@ -29,13 +29,14 @@ class CustomGutterComponent
|
||||
@domNode.style.removeProperty('display')
|
||||
@visible = true
|
||||
|
||||
# `state` is a subset of the TextEditorPresenter state that is specific
|
||||
# to this line number gutter.
|
||||
updateSync: (state) ->
|
||||
@oldDimensionsAndBackgroundState ?= {}
|
||||
newDimensionsAndBackgroundState = state.gutters
|
||||
setDimensionsAndBackground(@oldDimensionsAndBackgroundState, newDimensionsAndBackgroundState, @decorationsNode)
|
||||
setDimensionsAndBackground(@oldDimensionsAndBackgroundState, state.styles, @decorationsNode)
|
||||
|
||||
@oldDecorationPositionState ?= {}
|
||||
decorationState = state.gutters.customDecorations[@gutter.name]
|
||||
decorationState = state.content
|
||||
|
||||
updatedDecorationIds = new Set
|
||||
for decorationId, decorationInfo of decorationState
|
||||
|
||||
@@ -39,7 +39,6 @@ class DisplayBuffer extends Model
|
||||
@decorationsByMarkerId = {}
|
||||
@disposables.add @tokenizedBuffer.observeGrammar @subscribeToScopedConfigSettings
|
||||
@disposables.add @tokenizedBuffer.onDidChange @handleTokenizedBufferChange
|
||||
@disposables.add @buffer.onDidUpdateMarkers @handleBufferMarkersUpdated
|
||||
@disposables.add @buffer.onDidCreateMarker @handleBufferMarkerCreated
|
||||
@updateAllScreenLines()
|
||||
@foldMarkerAttributes = Object.freeze({class: 'fold', displayBufferId: @id})
|
||||
@@ -153,12 +152,12 @@ class DisplayBuffer extends Model
|
||||
@emitter.on 'did-update-markers', callback
|
||||
|
||||
emitDidChange: (eventProperties, refreshMarkers=true) ->
|
||||
if refreshMarkers
|
||||
@pauseMarkerChangeEvents()
|
||||
@refreshMarkerScreenPositions()
|
||||
@emit 'changed', eventProperties if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change', eventProperties
|
||||
@resumeMarkerChangeEvents()
|
||||
if refreshMarkers
|
||||
@refreshMarkerScreenPositions()
|
||||
@emit 'markers-updated' if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-update-markers'
|
||||
|
||||
updateWrappedScreenLines: ->
|
||||
start = 0
|
||||
@@ -1081,15 +1080,6 @@ class DisplayBuffer extends Model
|
||||
else
|
||||
@foldMarkerAttributes
|
||||
|
||||
pauseMarkerChangeEvents: ->
|
||||
marker.pauseChangeEvents() for marker in @getMarkers()
|
||||
return
|
||||
|
||||
resumeMarkerChangeEvents: ->
|
||||
marker.resumeChangeEvents() for marker in @getMarkers()
|
||||
@emit 'markers-updated' if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-update-markers'
|
||||
|
||||
refreshMarkerScreenPositions: ->
|
||||
for marker in @getMarkers()
|
||||
marker.notifyObservers(textChanged: false)
|
||||
@@ -1112,7 +1102,7 @@ class DisplayBuffer extends Model
|
||||
|
||||
handleTokenizedBufferChange: (tokenizedBufferChange) =>
|
||||
{start, end, delta, bufferChange} = tokenizedBufferChange
|
||||
@updateScreenLines(start, end + 1, delta, delayChangeEvent: bufferChange?)
|
||||
@updateScreenLines(start, end + 1, delta, refreshMarkers: false)
|
||||
@setScrollTop(Math.min(@getScrollTop(), @getMaxScrollTop())) if delta < 0
|
||||
|
||||
updateScreenLines: (startBufferRow, endBufferRow, bufferDelta=0, options={}) ->
|
||||
@@ -1135,11 +1125,7 @@ class DisplayBuffer extends Model
|
||||
screenDelta: screenDelta
|
||||
bufferDelta: bufferDelta
|
||||
|
||||
if options.delayChangeEvent
|
||||
@pauseMarkerChangeEvents()
|
||||
@pendingChangeEvent = changeEvent
|
||||
else
|
||||
@emitDidChange(changeEvent, options.refreshMarkers)
|
||||
@emitDidChange(changeEvent, options.refreshMarkers)
|
||||
|
||||
buildScreenLines: (startBufferRow, endBufferRow) ->
|
||||
screenLines = []
|
||||
@@ -1219,11 +1205,6 @@ class DisplayBuffer extends Model
|
||||
@scrollWidth += 1 unless @isSoftWrapped()
|
||||
@setScrollLeft(Math.min(@getScrollLeft(), @getMaxScrollLeft()))
|
||||
|
||||
handleBufferMarkersUpdated: =>
|
||||
if event = @pendingChangeEvent
|
||||
@pendingChangeEvent = null
|
||||
@emitDidChange(event, false)
|
||||
|
||||
handleBufferMarkerCreated: (textBufferMarker) =>
|
||||
@createFoldForMarker(textBufferMarker) if textBufferMarker.matchesParams(@getFoldMarkerAttributes())
|
||||
if marker = @getMarker(textBufferMarker.id)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
_ = require 'underscore-plus'
|
||||
CustomGutterComponent = require './custom-gutter-component'
|
||||
LineNumberGutterComponent = require './line-number-gutter-component'
|
||||
|
||||
@@ -26,11 +27,11 @@ class GutterContainerComponent
|
||||
updateSync: (state) ->
|
||||
# The GutterContainerComponent expects the gutters to be sorted in the order
|
||||
# they should appear.
|
||||
newState = state.gutters.sortedDescriptions
|
||||
newState = state.gutters
|
||||
|
||||
newGutterComponents = []
|
||||
newGutterComponentsByGutterName = {}
|
||||
for {gutter, visible} in newState
|
||||
for {gutter, visible, styles, content} in newState
|
||||
gutterComponent = @gutterComponentsByGutterName[gutter.name]
|
||||
if not gutterComponent
|
||||
if gutter.name is 'line-number'
|
||||
@@ -38,8 +39,20 @@ class GutterContainerComponent
|
||||
@lineNumberGutterComponent = gutterComponent
|
||||
else
|
||||
gutterComponent = new CustomGutterComponent({gutter})
|
||||
|
||||
if visible then gutterComponent.showNode() else gutterComponent.hideNode()
|
||||
gutterComponent.updateSync(state)
|
||||
# Pass the gutter only the state that it needs.
|
||||
if gutter.name is 'line-number'
|
||||
# For ease of use in the line number gutter component, set the shared
|
||||
# 'styles' as a field under the 'content'.
|
||||
gutterSubstate = _.clone(content)
|
||||
gutterSubstate.styles = styles
|
||||
else
|
||||
# Custom gutter 'content' is keyed on gutter name, so we cannot set
|
||||
# 'styles' as a subfield directly under it.
|
||||
gutterSubstate = {content, styles}
|
||||
gutterComponent.updateSync(gutterSubstate)
|
||||
|
||||
newGutterComponents.push({
|
||||
name: gutter.name,
|
||||
component: gutterComponent,
|
||||
|
||||
@@ -31,19 +31,25 @@ class LineNumberGutterComponent
|
||||
@domNode.style.removeProperty('display')
|
||||
@visible = true
|
||||
|
||||
# `state` is a subset of the TextEditorPresenter state that is specific
|
||||
# to this line number gutter.
|
||||
updateSync: (state) ->
|
||||
@newState = state.gutters.lineNumberGutter
|
||||
@oldState ?= {lineNumbers: {}}
|
||||
@newState = state
|
||||
@oldState ?=
|
||||
lineNumbers: {}
|
||||
styles: {}
|
||||
|
||||
@appendDummyLineNumber() unless @dummyLineNumberNode?
|
||||
|
||||
newDimensionsAndBackgroundState = state.gutters
|
||||
setDimensionsAndBackground(@oldState, newDimensionsAndBackgroundState, @lineNumbersNode)
|
||||
setDimensionsAndBackground(@oldState.styles, @newState.styles, @lineNumbersNode)
|
||||
|
||||
if @newState.maxLineNumberDigits isnt @oldState.maxLineNumberDigits
|
||||
@updateDummyLineNumber()
|
||||
node.remove() for id, node of @lineNumberNodesById
|
||||
@oldState = {maxLineNumberDigits: @newState.maxLineNumberDigits, lineNumbers: {}}
|
||||
@oldState =
|
||||
maxLineNumberDigits: @newState.maxLineNumberDigits
|
||||
lineNumbers: {}
|
||||
styles: {}
|
||||
@lineNumberNodesById = {}
|
||||
|
||||
@updateLineNumbers()
|
||||
|
||||
@@ -48,7 +48,6 @@ class Marker
|
||||
oldTailBufferPosition: null
|
||||
oldTailScreenPosition: null
|
||||
wasValid: true
|
||||
deferredChangeEvents: null
|
||||
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
@@ -332,11 +331,11 @@ class Marker
|
||||
newTailScreenPosition = @getTailScreenPosition()
|
||||
isValid = @isValid()
|
||||
|
||||
return if _.isEqual(isValid, @wasValid) and
|
||||
_.isEqual(newHeadBufferPosition, @oldHeadBufferPosition) and
|
||||
_.isEqual(newHeadScreenPosition, @oldHeadScreenPosition) and
|
||||
_.isEqual(newTailBufferPosition, @oldTailBufferPosition) and
|
||||
_.isEqual(newTailScreenPosition, @oldTailScreenPosition)
|
||||
return if isValid is @wasValid and
|
||||
newHeadBufferPosition.isEqual(@oldHeadBufferPosition) and
|
||||
newHeadScreenPosition.isEqual(@oldHeadScreenPosition) and
|
||||
newTailBufferPosition.isEqual(@oldTailBufferPosition) and
|
||||
newTailScreenPosition.isEqual(@oldTailScreenPosition)
|
||||
|
||||
changeEvent = {
|
||||
@oldHeadScreenPosition, newHeadScreenPosition,
|
||||
@@ -347,11 +346,8 @@ class Marker
|
||||
isValid
|
||||
}
|
||||
|
||||
if @deferredChangeEvents?
|
||||
@deferredChangeEvents.push(changeEvent)
|
||||
else
|
||||
@emit 'changed', changeEvent if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change', changeEvent
|
||||
@emit 'changed', changeEvent if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change', changeEvent
|
||||
|
||||
@oldHeadBufferPosition = newHeadBufferPosition
|
||||
@oldHeadScreenPosition = newHeadScreenPosition
|
||||
@@ -359,18 +355,6 @@ class Marker
|
||||
@oldTailScreenPosition = newTailScreenPosition
|
||||
@wasValid = isValid
|
||||
|
||||
pauseChangeEvents: ->
|
||||
@deferredChangeEvents = []
|
||||
|
||||
resumeChangeEvents: ->
|
||||
if deferredChangeEvents = @deferredChangeEvents
|
||||
@deferredChangeEvents = null
|
||||
|
||||
for event in deferredChangeEvents
|
||||
@emit 'changed', event if Grim.includeDeprecatedAPIs
|
||||
@emitter.emit 'did-change', event
|
||||
return
|
||||
|
||||
getPixelRange: ->
|
||||
@displayBuffer.pixelRangeForScreenRange(@getScreenRange(), false)
|
||||
|
||||
|
||||
@@ -427,7 +427,6 @@ class PackageManager
|
||||
path.join(packageDir, 'autocomplete-atom-api')
|
||||
path.join(packageDir, 'autocomplete-css')
|
||||
path.join(packageDir, 'autocomplete-html')
|
||||
path.join(packageDir, 'autocomplete-emojis')
|
||||
path.join(packageDir, 'autocomplete-snippets')
|
||||
]
|
||||
for dirToRemove in dirsToRemove
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
path = require 'path'
|
||||
hostedGitInfo = require 'hosted-git-info'
|
||||
normalizePackageData = null
|
||||
|
||||
_ = require 'underscore-plus'
|
||||
async = require 'async'
|
||||
@@ -26,16 +26,11 @@ class Package
|
||||
packagePath?.startsWith(@resourcePathWithTrailingSlash)
|
||||
|
||||
@normalizeMetadata: (metadata) ->
|
||||
if typeof metadata.repository is 'string'
|
||||
metadata.repository =
|
||||
type: 'git'
|
||||
url: metadata.repository
|
||||
|
||||
repoUrl = metadata.repository?.url
|
||||
if repoUrl
|
||||
info = hostedGitInfo.fromUrl(repoUrl)
|
||||
if info?.getDefaultRepresentation() is 'shortcut'
|
||||
metadata.repository.url = info.https().replace(/^git\+/, '')
|
||||
unless metadata?._id
|
||||
normalizePackageData ?= require 'normalize-package-data'
|
||||
normalizePackageData(metadata)
|
||||
if metadata.repository?.type is 'git' and typeof metadata.repository.url is 'string'
|
||||
metadata.repository.url = metadata.repository.url.replace(/^git\+/, '')
|
||||
|
||||
@loadMetadata: (packagePath, ignoreErrors=false) ->
|
||||
packageName = path.basename(packagePath)
|
||||
@@ -45,12 +40,12 @@ class Package
|
||||
if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
|
||||
try
|
||||
metadata = CSON.readFileSync(metadataPath)
|
||||
@normalizeMetadata(metadata)
|
||||
catch error
|
||||
throw error unless ignoreErrors
|
||||
|
||||
metadata ?= {}
|
||||
metadata.name = packageName
|
||||
@normalizeMetadata(metadata)
|
||||
|
||||
if includeDeprecatedAPIs and metadata.stylesheetMain?
|
||||
deprecate("Use the `mainStyleSheet` key instead of `stylesheetMain` in the `package.json` of `#{packageName}`", {packageName})
|
||||
|
||||
@@ -70,7 +70,7 @@ class TextEditorComponent
|
||||
@scrollViewNode.classList.add('scroll-view')
|
||||
@domNode.appendChild(@scrollViewNode)
|
||||
|
||||
@mountGutterContainerComponent() if @presenter.getState().gutters.sortedDescriptions.length
|
||||
@mountGutterContainerComponent() if @presenter.getState().gutters.length
|
||||
|
||||
@hiddenInputComponent = new InputComponent
|
||||
@scrollViewNode.appendChild(@hiddenInputComponent.getDomNode())
|
||||
@@ -137,7 +137,7 @@ class TextEditorComponent
|
||||
else
|
||||
@domNode.style.height = ''
|
||||
|
||||
if @newState.gutters.sortedDescriptions.length
|
||||
if @newState.gutters.length
|
||||
@mountGutterContainerComponent() unless @gutterContainerComponent?
|
||||
@gutterContainerComponent.updateSync(@newState)
|
||||
else
|
||||
|
||||
@@ -210,11 +210,13 @@ class TextEditorPresenter
|
||||
tiles: {}
|
||||
highlights: {}
|
||||
overlays: {}
|
||||
gutters:
|
||||
sortedDescriptions: []
|
||||
customDecorations: {}
|
||||
lineNumberGutter:
|
||||
lineNumbers: {}
|
||||
gutters: []
|
||||
# Shared state that is copied into ``@state.gutters`.
|
||||
@sharedGutterStyles = {}
|
||||
@customGutterDecorations = {}
|
||||
@lineNumberGutter =
|
||||
lineNumbers: {}
|
||||
|
||||
@updateState()
|
||||
|
||||
updateState: ->
|
||||
@@ -254,11 +256,11 @@ class TextEditorPresenter
|
||||
|
||||
updateVerticalScrollState: ->
|
||||
@state.content.scrollHeight = @scrollHeight
|
||||
@state.gutters.scrollHeight = @scrollHeight
|
||||
@sharedGutterStyles.scrollHeight = @scrollHeight
|
||||
@state.verticalScrollbar.scrollHeight = @scrollHeight
|
||||
|
||||
@state.content.scrollTop = @scrollTop
|
||||
@state.gutters.scrollTop = @scrollTop
|
||||
@sharedGutterStyles.scrollTop = @scrollTop
|
||||
@state.verticalScrollbar.scrollTop = @scrollTop
|
||||
|
||||
updateHorizontalScrollState: ->
|
||||
@@ -438,10 +440,10 @@ class TextEditorPresenter
|
||||
return
|
||||
|
||||
updateLineNumberGutterState: ->
|
||||
@state.gutters.lineNumberGutter.maxLineNumberDigits = @model.getLineCount().toString().length
|
||||
@lineNumberGutter.maxLineNumberDigits = @model.getLineCount().toString().length
|
||||
|
||||
updateCommonGutterState: ->
|
||||
@state.gutters.backgroundColor = if @gutterBackgroundColor isnt "rgba(0, 0, 0, 0)"
|
||||
@sharedGutterStyles.backgroundColor = if @gutterBackgroundColor isnt "rgba(0, 0, 0, 0)"
|
||||
@gutterBackgroundColor
|
||||
else
|
||||
@backgroundColor
|
||||
@@ -469,15 +471,25 @@ class TextEditorPresenter
|
||||
@emitDidUpdateState()
|
||||
|
||||
updateGutterOrderState: ->
|
||||
@state.gutters.sortedDescriptions = []
|
||||
@state.gutters = []
|
||||
if @model.isMini()
|
||||
return
|
||||
for gutter in @model.getGutters()
|
||||
isVisible = @gutterIsVisible(gutter)
|
||||
@state.gutters.sortedDescriptions.push({gutter, visible: isVisible})
|
||||
if gutter.name is 'line-number'
|
||||
content = @lineNumberGutter
|
||||
else
|
||||
@customGutterDecorations[gutter.name] ?= {}
|
||||
content = @customGutterDecorations[gutter.name]
|
||||
@state.gutters.push({
|
||||
gutter,
|
||||
visible: isVisible,
|
||||
styles: @sharedGutterStyles,
|
||||
content,
|
||||
})
|
||||
|
||||
# Updates the decoration state for the gutter with the given gutterName.
|
||||
# @state.gutters.customDecorations is an {Object}, with the form:
|
||||
# @customGutterDecorations is an {Object}, with the form:
|
||||
# * gutterName : {
|
||||
# decoration.id : {
|
||||
# top: # of pixels from top
|
||||
@@ -489,23 +501,43 @@ class TextEditorPresenter
|
||||
updateCustomGutterDecorationState: ->
|
||||
return unless @startRow? and @endRow? and @lineHeight?
|
||||
|
||||
@state.gutters.customDecorations = {}
|
||||
return if @model.isMini()
|
||||
if @model.isMini()
|
||||
# Mini editors have no gutter decorations.
|
||||
# We clear instead of reassigning to preserve the reference.
|
||||
@clearAllCustomGutterDecorations()
|
||||
|
||||
for gutter in @model.getGutters()
|
||||
gutterName = gutter.name
|
||||
@state.gutters.customDecorations[gutterName] = {}
|
||||
gutterDecorations = @customGutterDecorations[gutterName]
|
||||
if gutterDecorations
|
||||
# Clear the gutter decorations; they are rebuilt.
|
||||
# We clear instead of reassigning to preserve the reference.
|
||||
@clearDecorationsForCustomGutterName(gutterName)
|
||||
else
|
||||
@customGutterDecorations[gutterName] = {}
|
||||
return if not @gutterIsVisible(gutter)
|
||||
|
||||
relevantDecorations = @customGutterDecorationsInRange(gutterName, @startRow, @endRow - 1)
|
||||
relevantDecorations.forEach (decoration) =>
|
||||
decorationRange = decoration.getMarker().getScreenRange()
|
||||
@state.gutters.customDecorations[gutterName][decoration.id] =
|
||||
@customGutterDecorations[gutterName][decoration.id] =
|
||||
top: @lineHeight * decorationRange.start.row
|
||||
height: @lineHeight * decorationRange.getRowCount()
|
||||
item: decoration.getProperties().item
|
||||
class: decoration.getProperties().class
|
||||
|
||||
clearAllCustomGutterDecorations: ->
|
||||
allGutterNames = Object.keys(@customGutterDecorations)
|
||||
for gutterName in allGutterNames
|
||||
@clearDecorationsForCustomGutterName(gutterName)
|
||||
|
||||
clearDecorationsForCustomGutterName: (gutterName) ->
|
||||
gutterDecorations = @customGutterDecorations[gutterName]
|
||||
if gutterDecorations
|
||||
allDecorationIds = Object.keys(gutterDecorations)
|
||||
for decorationId in allDecorationIds
|
||||
delete gutterDecorations[decorationId]
|
||||
|
||||
gutterIsVisible: (gutterModel) ->
|
||||
isVisible = gutterModel.isVisible()
|
||||
if gutterModel.name is 'line-number'
|
||||
@@ -542,7 +574,7 @@ class TextEditorPresenter
|
||||
decorationClasses = @lineNumberDecorationClassesForRow(screenRow)
|
||||
foldable = @model.isFoldableAtScreenRow(screenRow)
|
||||
|
||||
@state.gutters.lineNumberGutter.lineNumbers[id] = {screenRow, bufferRow, softWrapped, top, decorationClasses, foldable}
|
||||
@lineNumberGutter.lineNumbers[id] = {screenRow, bufferRow, softWrapped, top, decorationClasses, foldable}
|
||||
visibleLineNumberIds[id] = true
|
||||
|
||||
# FIXME: We should either rely on @mouseWheelScreenRow or convert this to use tiles.
|
||||
@@ -553,8 +585,8 @@ class TextEditorPresenter
|
||||
id += '-' + wrapCount if wrapCount > 0
|
||||
visibleLineNumberIds[id] = true
|
||||
|
||||
for id of @state.gutters.lineNumberGutter.lineNumbers
|
||||
delete @state.gutters.lineNumberGutter.lineNumbers[id] unless visibleLineNumberIds[id]
|
||||
for id of @lineNumberGutter.lineNumbers
|
||||
delete @lineNumberGutter.lineNumbers[id] unless visibleLineNumberIds[id]
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -113,7 +113,10 @@ class WorkspaceElement extends HTMLElement
|
||||
focusPaneViewOnRight: -> @paneContainer.focusPaneViewOnRight()
|
||||
|
||||
runPackageSpecs: ->
|
||||
[projectPath] = atom.project.getPaths()
|
||||
if activePath = atom.workspace.getActivePaneItem()?.getPath?()
|
||||
[projectPath] = atom.project.relativizePath(activePath)
|
||||
else
|
||||
[projectPath] = atom.project.getPaths()
|
||||
ipc.send('run-package-specs', path.join(projectPath, 'spec')) if projectPath
|
||||
|
||||
atom.commands.add 'atom-workspace',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
(function() {
|
||||
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
@@ -204,3 +206,5 @@ var setupWindowBackground = function() {
|
||||
|
||||
parseLoadSettings();
|
||||
setupWindowBackground();
|
||||
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user