Comparar commits
1 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 0a0e848e7b |
@@ -13,5 +13,3 @@ debug.log
|
||||
docs/output
|
||||
docs/includes
|
||||
spec/fixtures/evil-files/
|
||||
resources/linux/Atom.desktop
|
||||
resources/linux/debian/control
|
||||
|
||||
@@ -11,7 +11,6 @@ pairs:
|
||||
bo: Ben Ogle; benogle
|
||||
jr: Jason Rudolph; jasonrudolph
|
||||
jl: Jessica Lord; jlord
|
||||
dh: Daniel Hengeveld; danielh
|
||||
email:
|
||||
domain: github.com
|
||||
#global: true
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.70.0"
|
||||
"atom-package-manager": "0.69.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,22 +39,21 @@ module.exports = (grunt) ->
|
||||
tmpDir = os.tmpdir()
|
||||
appName = if process.platform is 'darwin' then 'Atom.app' else 'Atom'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
installDir = grunt.option('install-dir')
|
||||
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
|
||||
symbolsDir = path.join(buildDir, 'Atom.breakpad.syms')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
if process.platform is 'win32'
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
installDir ?= path.join(process.env.ProgramFiles, appName)
|
||||
installDir = path.join(process.env.ProgramFiles, appName)
|
||||
else if process.platform is 'darwin'
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
installDir ?= path.join('/Applications', appName)
|
||||
installDir = path.join('/Applications', appName)
|
||||
else
|
||||
contentsDir = shellAppDir
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
|
||||
installDir = process.env.INSTALL_PREFIX ? '/usr/local'
|
||||
|
||||
coffeeConfig =
|
||||
glob_to_multiple:
|
||||
@@ -122,8 +121,6 @@ module.exports = (grunt) ->
|
||||
|
||||
atom: {appDir, appName, symbolsDir, buildDir, contentsDir, installDir, shellAppDir}
|
||||
|
||||
docsOutputDir: 'docs/output/api'
|
||||
|
||||
coffee: coffeeConfig
|
||||
|
||||
less: lessConfig
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"github-releases": "~0.2.0",
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-coffeelint": "git+https://github.com/atom/grunt-coffeelint.git",
|
||||
"grunt-coffeelint": "git://github.com/atom/grunt-coffeelint.git",
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-coffee": "~0.9.0",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
|
||||
@@ -90,11 +90,6 @@ module.exports = (grunt) ->
|
||||
cp path.join('resources', 'win', 'msvcp100.dll'), path.join(shellAppDir, 'msvcp100.dll')
|
||||
cp path.join('resources', 'win', 'msvcr100.dll'), path.join(shellAppDir, 'msvcr100.dll')
|
||||
|
||||
# Set up chocolatey ignore and gui files
|
||||
fs.writeFileSync path.join(appDir, 'apm', 'node_modules', 'atom-package-manager', 'bin', 'node.exe.ignore'), ''
|
||||
fs.writeFileSync path.join(appDir, 'node_modules', 'symbols-view', 'vendor', 'ctags-win32.exe.ignore'), ''
|
||||
fs.writeFileSync path.join(shellAppDir, 'atom.exe.gui'), ''
|
||||
|
||||
dependencies = ['compile', "generate-license:save"]
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
dependencies.push('set-exe-icon') if process.platform is 'win32'
|
||||
|
||||
@@ -15,17 +15,15 @@ module.exports = (grunt) ->
|
||||
grunt.registerTask 'build-docs', 'Builds the API docs in src', ->
|
||||
done = @async()
|
||||
|
||||
docsOutputDir = grunt.config.get('docsOutputDir')
|
||||
|
||||
downloadIncludes (error, includePaths) ->
|
||||
if error?
|
||||
done(error)
|
||||
else
|
||||
rm(docsOutputDir)
|
||||
rm('docs/output/api')
|
||||
args = [
|
||||
commonArgs...
|
||||
'--title', 'Atom API Documentation'
|
||||
'-o', docsOutputDir
|
||||
'-o', 'docs/output/api'
|
||||
'-r', 'docs/README.md'
|
||||
'--stability', '1'
|
||||
'src/'
|
||||
|
||||
@@ -40,15 +40,13 @@ module.exports = (grunt) ->
|
||||
mkdir path.dirname(shareDir)
|
||||
cp shellAppDir, shareDir
|
||||
|
||||
# Create Atom.desktop if installation not in temporary folder
|
||||
# Create Atom.desktop if installation in '/usr/local'
|
||||
applicationsDir = path.join('/usr','share','applications')
|
||||
tmpDir = if process.env.TMPDIR? then process.env.TMPDIR else '/tmp'
|
||||
desktopInstallFile = path.join(installDir,'share','applications','Atom.desktop')
|
||||
if installDir.indexOf(tmpDir) isnt 0
|
||||
mkdir path.dirname(desktopInstallFile)
|
||||
if installDir.indexOf(tmpDir) isnt 0 and fs.isDirectorySync(applicationsDir)
|
||||
{description} = grunt.file.readJSON('package.json')
|
||||
installDir = path.join(installDir,'.') # To prevent "Exec=/usr/local//share/atom/atom"
|
||||
fillTemplate(desktopFile, {description, installDir, iconName})
|
||||
cp desktopFile, desktopInstallFile
|
||||
cp desktopFile, path.join(applicationsDir,'Atom.desktop')
|
||||
|
||||
# Create relative symbol link for apm.
|
||||
process.chdir(binDir)
|
||||
|
||||
@@ -9,6 +9,16 @@ request = require 'request'
|
||||
|
||||
grunt = null
|
||||
|
||||
if process.platform is 'darwin'
|
||||
assets = [
|
||||
{assetName: 'atom-mac.zip', sourceName: 'Atom.app'}
|
||||
{assetName: 'atom-mac-symbols.zip', sourceName: 'Atom.breakpad.syms'}
|
||||
]
|
||||
else
|
||||
assets = [
|
||||
{assetName: 'atom-windows.zip', sourceName: 'Atom'}
|
||||
]
|
||||
|
||||
commitSha = process.env.JANKY_SHA1
|
||||
token = process.env.ATOM_ACCESS_TOKEN
|
||||
defaultHeaders =
|
||||
@@ -20,19 +30,11 @@ module.exports = (gruntObject) ->
|
||||
|
||||
grunt.registerTask 'publish-build', 'Publish the built app', ->
|
||||
return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master'
|
||||
tasks = ['upload-assets']
|
||||
tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin'
|
||||
grunt.task.run(tasks)
|
||||
|
||||
grunt.registerTask 'prepare-docs', 'Move the build docs to the build dir', ->
|
||||
fs.copySync(grunt.config.get('docsOutputDir'), path.join(grunt.config.get('atom.buildDir'), 'atom-docs'))
|
||||
|
||||
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
|
||||
done = @async()
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
assets = getAssets()
|
||||
|
||||
zipAssets buildDir, assets, (error) ->
|
||||
zipApps buildDir, assets, (error) ->
|
||||
return done(error) if error?
|
||||
getAtomDraftRelease (error, release) ->
|
||||
return done(error) if error?
|
||||
@@ -41,38 +43,26 @@ module.exports = (gruntObject) ->
|
||||
return done(error) if error?
|
||||
uploadAssets(release, buildDir, assets, done)
|
||||
|
||||
getAssets = ->
|
||||
if process.platform is 'darwin'
|
||||
[
|
||||
{assetName: 'atom-mac.zip', sourcePath: 'Atom.app'}
|
||||
{assetName: 'atom-mac-symbols.zip', sourcePath: 'Atom.breakpad.syms'}
|
||||
{assetName: 'atom-docs.zip', sourcePath: 'atom-docs'}
|
||||
]
|
||||
else
|
||||
[
|
||||
{assetName: 'atom-windows.zip', sourcePath: 'Atom'}
|
||||
]
|
||||
|
||||
logError = (message, error, details) ->
|
||||
grunt.log.error(message)
|
||||
grunt.log.error(error.message ? error) if error?
|
||||
grunt.log.error(details) if details
|
||||
|
||||
zipAssets = (buildDir, assets, callback) ->
|
||||
zip = (directory, sourcePath, assetName, callback) ->
|
||||
zipApps = (buildDir, assets, callback) ->
|
||||
zip = (directory, sourceName, assetName, callback) ->
|
||||
if process.platform is 'win32'
|
||||
zipCommand = "C:/psmodules/7z.exe a -r #{assetName} #{sourcePath}"
|
||||
zipCommand = "C:/psmodules/7z.exe a -r #{assetName} #{sourceName}"
|
||||
else
|
||||
zipCommand = "zip -r --symlinks #{assetName} #{sourcePath}"
|
||||
zipCommand = "zip -r --symlinks #{assetName} #{sourceName}"
|
||||
options = {cwd: directory, maxBuffer: Infinity}
|
||||
child_process.exec zipCommand, options, (error, stdout, stderr) ->
|
||||
logError("Zipping #{sourcePath} failed", error, stderr) if error?
|
||||
logError("Zipping #{sourceName} failed", error, stderr) if error?
|
||||
callback(error)
|
||||
|
||||
tasks = []
|
||||
for {assetName, sourcePath} in assets
|
||||
for {assetName, sourceName} in assets
|
||||
fs.removeSync(path.join(buildDir, assetName))
|
||||
tasks.push(zip.bind(this, buildDir, sourcePath, assetName))
|
||||
tasks.push(zip.bind(this, buildDir, sourceName, assetName))
|
||||
async.parallel(tasks, callback)
|
||||
|
||||
getAtomDraftRelease = (callback) ->
|
||||
@@ -137,7 +127,7 @@ uploadAssets = (release, buildDir, assets, callback) ->
|
||||
fs.createReadStream(assetPath).pipe(assetRequest)
|
||||
|
||||
tasks = []
|
||||
for {assetName} in assets
|
||||
for {assetName, sourceName} in assets
|
||||
assetPath = path.join(buildDir, assetName)
|
||||
tasks.push(upload.bind(this, release, assetName, assetPath))
|
||||
async.parallel(tasks, callback)
|
||||
|
||||
@@ -11,31 +11,41 @@ value of a namespaced config key with `atom.config.get`:
|
||||
@showInvisibles() if atom.config.get "editor.showInvisibles"
|
||||
```
|
||||
|
||||
Or you can use the `::subscribe` with `atom.config.observe` to track changes
|
||||
from any view object.
|
||||
Or you can use the `::observeConfig` to track changes from any view object.
|
||||
|
||||
```coffeescript
|
||||
class MyView extends View
|
||||
initialize: ->
|
||||
@subscribe atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
|
||||
@observeConfig 'editor.fontSize', () =>
|
||||
@adjustFontSize()
|
||||
```
|
||||
|
||||
The `atom.config.observe` method will call the given callback immediately with
|
||||
the current value for the specified key path, and it will also call it in the
|
||||
future whenever the value of that key path changes.
|
||||
The `::observeConfig` method will call the given callback immediately with the
|
||||
current value for the specified key path, and it will also call it in the future
|
||||
whenever the value of that key path changes.
|
||||
|
||||
Subscriptions made with `::subscribe` are automatically canceled when the
|
||||
Subscriptions made with `observeConfig` are automatically canceled when the
|
||||
view is removed. You can cancel config subscriptions manually via the
|
||||
`off` method on the subscription object that `atom.config.observe` returns.
|
||||
`unobserveConfig` method.
|
||||
|
||||
```coffeescript
|
||||
fontSizeSubscription = atom.config.observe 'editor.fontSize', (newValue, {previous}) =>
|
||||
@adjustFontSize()
|
||||
view1.unobserveConfig() # unobserve all properties
|
||||
```
|
||||
|
||||
# ... later on
|
||||
You can add the ability to observe config values to non-view classes by
|
||||
extending their prototype with the `ConfigObserver` mixin:
|
||||
|
||||
fontSizeSubscription.off() # Stop observing
|
||||
```coffeescript
|
||||
{ConfigObserver} = require 'atom'
|
||||
|
||||
class MyClass
|
||||
ConfigObserver.includeInto(this)
|
||||
|
||||
constructor: ->
|
||||
@observeConfig 'editor.showInvisibles', -> # ...
|
||||
|
||||
destroy: ->
|
||||
@unobserveConfig()
|
||||
```
|
||||
|
||||
### Writing Config Settings
|
||||
|
||||
+2
-15
@@ -198,19 +198,6 @@ Unstar a package; requires authentication.
|
||||
|
||||
Returns 204 No Content.
|
||||
|
||||
#### GET /api/packages/:name/stargazers
|
||||
|
||||
List the users that have starred a package.
|
||||
|
||||
Returns a list of user objects:
|
||||
|
||||
```json
|
||||
[
|
||||
{"login":"aperson"},
|
||||
{"login":"anotherperson"},
|
||||
]
|
||||
```
|
||||
|
||||
### Atom updates
|
||||
|
||||
#### GET /api/updates
|
||||
@@ -219,10 +206,10 @@ Atom update feed, following the format expected by [Squirrel](https://github.com
|
||||
|
||||
Returns:
|
||||
|
||||
```json
|
||||
```
|
||||
{
|
||||
"name": "0.96.0",
|
||||
"notes": "[HTML release notes]",
|
||||
"notes": "[HTML release notes]"
|
||||
"pub_date": "2014-05-19T15:52:06.000Z",
|
||||
"url": "https://www.atom.io/api/updates/download"
|
||||
}
|
||||
|
||||
@@ -61,13 +61,6 @@ and restart Atom. If Atom now works fine, you can make this setting permanent:
|
||||
|
||||
See also https://github.com/atom/atom/issues/2082.
|
||||
|
||||
### /usr/bin/env: node: No such file or directory
|
||||
|
||||
If you get this notice when attempting to `script/build`, you either do not
|
||||
have nodejs installed, or node isn't identified as nodejs on your machine.
|
||||
If it's the latter, entering `sudo ln -s /usr/bin/nodejs /usr/bin/node` into
|
||||
your terminal may fix the issue.
|
||||
|
||||
### Linux build error reports in atom/atom
|
||||
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Alinux&type=Issues)
|
||||
to get a list of reports about build errors on Linux.
|
||||
|
||||
+1
-69
@@ -38,7 +38,7 @@ Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec
|
||||
|
||||
0. Add one or more expectations
|
||||
|
||||
The best way to learn about expectations is to read the [jasmine documentation](http://jasmine.github.io/1.3/introduction.html#section-Expectations) about them. Below is a simple example.
|
||||
The best way to learn about expectations is to read the [jasmine documentation](http://jasmine.github.io/2.0/introduction.html#section-Expectations) about them. Below is a simple example.
|
||||
|
||||
```coffee
|
||||
describe "when a test is written", ->
|
||||
@@ -47,74 +47,6 @@ Atom uses [Jasmine](http://jasmine.github.io/2.0/introduction.html) as its spec
|
||||
expect("oranges").not.toEqual("apples")
|
||||
```
|
||||
|
||||
## Asynchronous specs
|
||||
|
||||
Writing Asynchronous specs can be tricky at first. Some examples.
|
||||
|
||||
0. Promises
|
||||
|
||||
Working with promises is rather easy in Atom. You can use our `waitsForPromise` function.
|
||||
|
||||
```coffee
|
||||
describe "when we open a file", ->
|
||||
it "should be opened in an editor", ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('c.coffee').then (editor) ->
|
||||
expect(editor.getPath()).toContain 'c.coffee'
|
||||
```
|
||||
|
||||
This method can be used in the `describe`, `it`, `beforeEach` and `afterEach` functions.
|
||||
|
||||
```coffee
|
||||
describe "when we open a file", ->
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open 'c.coffee'
|
||||
|
||||
it "should be opened in an editor", ->
|
||||
expect(atom.workspace.getActiveEditor().getPath()).toContain 'c.coffee'
|
||||
|
||||
```
|
||||
|
||||
If you need to wait for multiple promises use a new `waitsForPromise` function for each promise. (Caution: Without `beforeEach` this example will fail!)
|
||||
|
||||
```coffee
|
||||
describe "waiting for the packages to load", ->
|
||||
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.js')
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('tabs')
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('tree-view')
|
||||
|
||||
it 'should have waited long enough', ->
|
||||
expect(atom.packages.isPackageActive('tabs')).toBe true
|
||||
expect(atom.packages.isPackageActive('tree-view')).toBe true
|
||||
```
|
||||
|
||||
0. Asynchronous functions with callbacks
|
||||
|
||||
Specs for asynchronous functions can be done using the `waitsFor` and `runs` functions. A simple example.
|
||||
|
||||
```coffee
|
||||
describe "fs.readdir(path, cb)", ->
|
||||
it "is async", ->
|
||||
spy = jasmine.createSpy('fs.readdirSpy')
|
||||
|
||||
fs.readdir('/tmp/example', spy)
|
||||
waitsFor ->
|
||||
spy.callCount > 0
|
||||
runs ->
|
||||
exp = [null, ['example.coffee']]
|
||||
expect(spy.mostRecentCall.args).toEqual exp
|
||||
expect(spy).toHaveBeenCalledWith(null, ['example.coffee'])
|
||||
```
|
||||
|
||||
For a more detailed documentation on asynchronous tests please visit the [jasmine documentation](http://jasmine.github.io/1.3/introduction.html#section-Asynchronous_Support).
|
||||
|
||||
|
||||
## Running specs
|
||||
|
||||
Most of the time you'll want to run specs by triggering the `window:run-package-specs` command. This command is not only to run package specs, it is also for Atom core specs. This will run all the specs in the current project's spec directory. If you want to run the Atom core specs and **all** the default package specs trigger the `window:run-all-specs` command.
|
||||
|
||||
@@ -69,8 +69,6 @@
|
||||
'cmd-}': 'pane:show-next-item'
|
||||
'cmd-alt-left': 'pane:show-previous-item'
|
||||
'cmd-alt-right': 'pane:show-next-item'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'cmd-=': 'window:increase-font-size'
|
||||
|
||||
@@ -45,8 +45,6 @@
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
'ctrl-shift-down': 'core:move-down'
|
||||
'ctrl-=': 'window:increase-font-size'
|
||||
|
||||
@@ -47,8 +47,6 @@
|
||||
'shift-backspace': 'core:backspace'
|
||||
'ctrl-tab': 'pane:show-next-item'
|
||||
'ctrl-shift-tab': 'pane:show-previous-item'
|
||||
'ctrl-pageup': 'pane:show-previous-item'
|
||||
'ctrl-pagedown': 'pane:show-next-item'
|
||||
'ctrl-shift-up': 'core:move-up'
|
||||
'ctrl-shift-down': 'core:move-down'
|
||||
'ctrl-alt-up': 'editor:add-selection-above'
|
||||
|
||||
+29
-30
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.108.0",
|
||||
"version": "0.107.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,7 +17,7 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.13.3",
|
||||
"atomShellVersion": "0.13.2",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^0.27.0",
|
||||
@@ -27,7 +27,7 @@
|
||||
"coffeestack": "0.7.0",
|
||||
"delegato": "^1",
|
||||
"emissary": "^1.2.1",
|
||||
"first-mate": "^1.7.1",
|
||||
"first-mate": "^1.7",
|
||||
"fs-plus": "^2.2.3",
|
||||
"fstream": "0.1.24",
|
||||
"fuzzaldrin": "^1.1",
|
||||
@@ -47,8 +47,8 @@
|
||||
"random-words": "0.0.1",
|
||||
"react-atom-fork": "^0.10.0",
|
||||
"reactionary-atom-fork": "^0.9.0",
|
||||
"runas": "0.5.4",
|
||||
"scandal": "0.16.0",
|
||||
"runas": "^0.5",
|
||||
"scandal": "0.15.3",
|
||||
"scoped-property-store": "^0.9.0",
|
||||
"scrollbar-style": "^0.4.0",
|
||||
"season": "^1.0.2",
|
||||
@@ -63,9 +63,9 @@
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.17.0",
|
||||
"atom-dark-ui": "0.30.0",
|
||||
"atom-dark-ui": "0.29.0",
|
||||
"atom-light-syntax": "0.18.0",
|
||||
"atom-light-ui": "0.26.0",
|
||||
"atom-light-ui": "0.25.0",
|
||||
"base16-tomorrow-dark-theme": "0.17.0",
|
||||
"solarized-dark-syntax": "0.18.0",
|
||||
"solarized-light-syntax": "0.9.0",
|
||||
@@ -73,53 +73,52 @@
|
||||
"autocomplete": "0.28.0",
|
||||
"autoflow": "0.17.0",
|
||||
"autosave": "0.14.0",
|
||||
"background-tips": "0.15.0",
|
||||
"bookmarks": "0.26.0",
|
||||
"background-tips": "0.14.0",
|
||||
"bookmarks": "0.25.0",
|
||||
"bracket-matcher": "0.47.0",
|
||||
"command-palette": "0.24.0",
|
||||
"command-palette": "0.23.0",
|
||||
"deprecation-cop": "0.7.0",
|
||||
"dev-live-reload": "0.31.0",
|
||||
"exception-reporting": "0.18.0",
|
||||
"feedback": "0.33.0",
|
||||
"find-and-replace": "0.122.0",
|
||||
"fuzzy-finder": "0.56.0",
|
||||
"find-and-replace": "0.120.0",
|
||||
"fuzzy-finder": "0.55.0",
|
||||
"git-diff": "0.34.0",
|
||||
"go-to-line": "0.23.0",
|
||||
"grammar-selector": "0.27.0",
|
||||
"image-view": "0.36.0",
|
||||
"image-view": "0.35.0",
|
||||
"keybinding-resolver": "0.18.0",
|
||||
"link": "0.24.0",
|
||||
"markdown-preview": "0.86.0",
|
||||
"markdown-preview": "0.83.0",
|
||||
"metrics": "0.32.0",
|
||||
"open-on-github": "0.29.0",
|
||||
"open-on-github": "0.28.0",
|
||||
"package-generator": "0.31.0",
|
||||
"release-notes": "0.32.0",
|
||||
"settings-view": "0.129.0",
|
||||
"snippets": "0.47.0",
|
||||
"settings-view": "0.128.0",
|
||||
"snippets": "0.46.0",
|
||||
"spell-check": "0.38.0",
|
||||
"status-bar": "0.41.0",
|
||||
"styleguide": "0.29.0",
|
||||
"symbols-view": "0.59.0",
|
||||
"symbols-view": "0.56.0",
|
||||
"tabs": "0.42.0",
|
||||
"timecop": "0.21.0",
|
||||
"tree-view": "0.108.0",
|
||||
"timecop": "0.19.0",
|
||||
"tree-view": "0.104.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.17.0",
|
||||
"whitespace": "0.23.0",
|
||||
"welcome": "0.16.0",
|
||||
"whitespace": "0.22.0",
|
||||
"wrap-guide": "0.19.0",
|
||||
|
||||
"language-c": "0.21.0",
|
||||
"language-coffee-script": "0.22.0",
|
||||
"language-css": "0.17.0",
|
||||
"language-gfm": "0.42.0",
|
||||
"language-gfm": "0.40.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.13.0",
|
||||
"language-go": "0.12.0",
|
||||
"language-html": "0.22.0",
|
||||
"language-hyperlink": "0.10.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.30.0",
|
||||
"language-java": "0.10.0",
|
||||
"language-javascript": "0.28.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.11.0",
|
||||
"language-less": "0.9.0",
|
||||
"language-make": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.9.0",
|
||||
@@ -127,7 +126,7 @@
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.18.0",
|
||||
"language-ruby": "0.30.0",
|
||||
"language-ruby-on-rails": "0.15.0",
|
||||
"language-ruby-on-rails": "0.14.0",
|
||||
"language-sass": "0.13.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.7.0",
|
||||
@@ -136,7 +135,7 @@
|
||||
"language-todo": "0.10.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-xml": "0.15.0",
|
||||
"language-yaml": "0.11.0"
|
||||
"language-yaml": "0.7.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
+6
-22
@@ -31,7 +31,7 @@ function bootstrap() {
|
||||
fs.mkdirSync(path.join(apmInstallPath, 'node_modules'));
|
||||
|
||||
var apmPath = path.resolve(__dirname, '..', 'apm', 'node_modules', 'atom-package-manager', 'bin', 'apm')
|
||||
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? ' --no-color' : '';
|
||||
var apmFlags = process.env.JANKY_SHA1 || process.argv.indexOf('--no-color') !== -1 ? '--no-color' : '';
|
||||
|
||||
var npmPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'npm');
|
||||
var initialNpmCommand = fs.existsSync(npmPath) ? npmPath : 'npm';
|
||||
@@ -39,28 +39,12 @@ function bootstrap() {
|
||||
|
||||
var packagesToDedupe = ['fs-plus', 'humanize-plus', 'oniguruma', 'roaster', 'season', 'grim'];
|
||||
|
||||
var buildInstallCommand = initialNpmCommand + npmFlags + 'install';
|
||||
var buildInstallOptions = {cwd: path.resolve(__dirname, '..', 'build')};
|
||||
var apmInstallCommand = npmPath + npmFlags + 'install';
|
||||
var apmInstallOptions = {cwd: apmInstallPath};
|
||||
var moduleInstallCommand = apmPath + ' install' + apmFlags;
|
||||
var dedupeCommand = apmPath + ' dedupe' + apmFlags;
|
||||
|
||||
if (process.argv.indexOf('--no-quiet') === -1) {
|
||||
buildInstallCommand += ' --quiet';
|
||||
apmInstallCommand += ' --quiet';
|
||||
moduleInstallCommand += ' --quiet';
|
||||
dedupeCommand += ' --quiet';
|
||||
buildInstallOptions.ignoreStdout = true;
|
||||
apmInstallOptions.ignoreStdout = true;
|
||||
}
|
||||
|
||||
var commands = [
|
||||
{command: buildInstallCommand, message: 'Installing build modules...', options: buildInstallOptions},
|
||||
{command: apmInstallCommand, message: 'Installing apm...', options: apmInstallOptions},
|
||||
apmPath + ' clean' + apmFlags,
|
||||
moduleInstallCommand,
|
||||
dedupeCommand + ' ' + packagesToDedupe.join(' '),
|
||||
{command: initialNpmCommand + npmFlags + 'install --quiet', message: 'Installing build modules...', options: {cwd: path.resolve(__dirname, '..', 'build'), ignoreStdout: true}},
|
||||
{command: npmPath + npmFlags + 'install --quiet', message: 'Installing apm...', options: {cwd: apmInstallPath, ignoreStdout: true}},
|
||||
apmPath + ' clean ' + apmFlags,
|
||||
apmPath + ' install --quiet ' + apmFlags,
|
||||
apmPath + ' dedupe --quiet ' + apmFlags + ' ' + packagesToDedupe.join(' '),
|
||||
];
|
||||
|
||||
process.chdir(path.dirname(__dirname));
|
||||
|
||||
@@ -17,33 +17,6 @@ describe "ContextMenuManager", ->
|
||||
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
|
||||
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
|
||||
|
||||
it 'does not add duplicate menu items', ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'label': 'command'
|
||||
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'label': 'command'
|
||||
|
||||
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
|
||||
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
|
||||
expect(contextMenu.definitions['.selector'].length).toBe 1
|
||||
|
||||
it 'allows duplicate commands with different labels', ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'label': 'command'
|
||||
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
'another label': 'command'
|
||||
|
||||
expect(contextMenu.definitions['.selector'][0].label).toEqual 'label'
|
||||
expect(contextMenu.definitions['.selector'][0].command).toEqual 'command'
|
||||
expect(contextMenu.definitions['.selector'][1].label).toEqual 'another label'
|
||||
expect(contextMenu.definitions['.selector'][1].command).toEqual 'command'
|
||||
|
||||
it "loads submenus", ->
|
||||
contextMenu.add 'file-path',
|
||||
'.selector':
|
||||
|
||||
@@ -47,15 +47,6 @@ describe "DisplayBuffer", ->
|
||||
buffer.insert([0,0], oneHundredLines)
|
||||
expect(displayBuffer.getLineCount()).toBe 100 + originalLineCount
|
||||
|
||||
it "reassigns the scrollTop if it exceeds the max possible value after lines are removed", ->
|
||||
displayBuffer.manageScrollPosition = true
|
||||
displayBuffer.setHeight(50)
|
||||
displayBuffer.setLineHeightInPixels(10)
|
||||
displayBuffer.setScrollTop(80)
|
||||
|
||||
buffer.delete([[8, 0], [10, 0]])
|
||||
expect(displayBuffer.getScrollTop()).toBe 60
|
||||
|
||||
describe "soft wrapping", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setSoftWrap(true)
|
||||
@@ -324,16 +315,6 @@ describe "DisplayBuffer", ->
|
||||
expect(line0.fold).toBe outerFold
|
||||
expect(line1.fold).toBeUndefined()
|
||||
|
||||
describe "when a fold ends where another fold begins", ->
|
||||
it "continues to hide the lines inside the second fold", ->
|
||||
fold2 = displayBuffer.createFold(4, 9)
|
||||
fold1 = displayBuffer.createFold(0, 4)
|
||||
|
||||
displayBuffer.logLines(0, 20)
|
||||
|
||||
expect(displayBuffer.lineForRow(0).text).toMatch /^0/
|
||||
expect(displayBuffer.lineForRow(1).text).toMatch /^10/
|
||||
|
||||
describe "when there is another display buffer pointing to the same buffer", ->
|
||||
it "does not create folds in the other display buffer", ->
|
||||
otherDisplayBuffer = new DisplayBuffer({buffer, tabLength})
|
||||
@@ -1005,9 +986,7 @@ describe "DisplayBuffer", ->
|
||||
|
||||
displayBuffer.setLineHeightInPixels(20)
|
||||
displayBuffer.setDefaultCharWidth(10)
|
||||
|
||||
for char in ['r', 'e', 't', 'u', 'r', 'n']
|
||||
displayBuffer.setScopedCharWidth(["source.js", "keyword.control.js"], char, 11)
|
||||
displayBuffer.setScopedCharWidths(["source.js", "keyword.control.js"], r: 11, e: 11, t: 11, u: 11, n: 11)
|
||||
|
||||
{start, end} = marker.getPixelRange()
|
||||
expect(start.top).toBe 5 * 20
|
||||
@@ -1088,38 +1067,3 @@ describe "DisplayBuffer", ->
|
||||
it "does not scroll vertically if the position is already in view", ->
|
||||
displayBuffer.scrollToScreenPosition([4, 20], center: true)
|
||||
expect(displayBuffer.getScrollTop()).toBe 0
|
||||
|
||||
describe "scroll width", ->
|
||||
cursorWidth = 1
|
||||
beforeEach ->
|
||||
displayBuffer.setDefaultCharWidth(10)
|
||||
|
||||
it "recomputes the scroll width when the default character width changes", ->
|
||||
expect(displayBuffer.getScrollWidth()).toBe 10 * 65 + cursorWidth
|
||||
|
||||
displayBuffer.setDefaultCharWidth(12)
|
||||
expect(displayBuffer.getScrollWidth()).toBe 12 * 65 + cursorWidth
|
||||
|
||||
it "recomputes the scroll width when the max line length changes", ->
|
||||
buffer.insert([6, 12], ' ')
|
||||
expect(displayBuffer.getScrollWidth()).toBe 10 * 66 + cursorWidth
|
||||
|
||||
buffer.delete([[6, 10], [6, 12]], ' ')
|
||||
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + cursorWidth
|
||||
|
||||
it "recomputes the scroll width when the scoped character widths change", ->
|
||||
operatorWidth = 20
|
||||
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
|
||||
expect(displayBuffer.getScrollWidth()).toBe 10 * 64 + operatorWidth + cursorWidth
|
||||
|
||||
it "recomputes the scroll width when the scoped character widths change in a batch", ->
|
||||
operatorWidth = 20
|
||||
|
||||
displayBuffer.on 'character-widths-changed', changedSpy = jasmine.createSpy()
|
||||
|
||||
displayBuffer.batchCharacterMeasurement ->
|
||||
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '<', operatorWidth)
|
||||
displayBuffer.setScopedCharWidth(['source.js', 'keyword.operator.js'], '?', operatorWidth)
|
||||
|
||||
expect(displayBuffer.getScrollWidth()).toBe 10 * 63 + operatorWidth * 2 + cursorWidth
|
||||
expect(changedSpy.callCount).toBe 1
|
||||
|
||||
+420
-458
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1196,7 +1196,6 @@ describe "Editor", ->
|
||||
editor.setHeight(50)
|
||||
editor.setWidth(50)
|
||||
editor.setHorizontalScrollbarHeight(0)
|
||||
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
|
||||
editor.setSelectedBufferRange([[5, 6], [6, 8]], autoscroll: true)
|
||||
@@ -1483,17 +1482,6 @@ describe "Editor", ->
|
||||
expect(cursor1.getBufferPosition()).toEqual [1, 5]
|
||||
expect(cursor2.getBufferPosition()).toEqual [2, 7]
|
||||
|
||||
it "autoscrolls to the last cursor", ->
|
||||
editor.manageScrollPosition = true
|
||||
editor.setCursorScreenPosition([1, 2])
|
||||
editor.addCursorAtScreenPosition([10, 4])
|
||||
editor.setLineHeightInPixels(10)
|
||||
editor.setHeight(50)
|
||||
|
||||
expect(editor.getScrollTop()).toBe 0
|
||||
editor.insertText('a')
|
||||
expect(editor.getScrollTop()).toBe 80
|
||||
|
||||
describe "when there are multiple non-empty selections", ->
|
||||
describe "when the selections are on the same line", ->
|
||||
it "replaces each selection range with the inserted characters", ->
|
||||
|
||||
@@ -205,17 +205,6 @@ describe "Project", ->
|
||||
fs.writeFileSync(filePath, sampleContent)
|
||||
fs.writeFileSync(commentFilePath, sampleCommentContent)
|
||||
|
||||
describe "when a file doesn't exist", ->
|
||||
it "calls back with an error", ->
|
||||
errors = []
|
||||
waitsForPromise ->
|
||||
atom.project.replace /items/gi, 'items', ['/not-a-file.js'], (result, error) ->
|
||||
errors.push(error)
|
||||
|
||||
runs ->
|
||||
expect(errors).toHaveLength 1
|
||||
expect(errors[0].path).toBe '/not-a-file.js'
|
||||
|
||||
describe "when called with unopened files", ->
|
||||
it "replaces properly", ->
|
||||
results = []
|
||||
|
||||
@@ -335,13 +335,12 @@ describe "TokenizedBuffer", ->
|
||||
expect(screenLine0.text).toBe "# Econ 101#{tabAsSpaces}"
|
||||
{ tokens } = screenLine0
|
||||
|
||||
expect(tokens.length).toBe 4
|
||||
expect(tokens.length).toBe 3
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[1].value).toBe " Econ 101"
|
||||
expect(tokens[2].value).toBe tabAsSpaces
|
||||
expect(tokens[2].scopes).toEqual tokens[1].scopes
|
||||
expect(tokens[2].isAtomic).toBeTruthy()
|
||||
expect(tokens[3].value).toBe ""
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).text).toBe "#{tabAsSpaces} buy()#{tabAsSpaces}while supply > demand"
|
||||
|
||||
@@ -412,7 +411,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].bufferDelta).toBe 1
|
||||
expect(tokenizedBuffer.lineForScreenRow(2).tokens[1].screenDelta).toBe 1
|
||||
|
||||
describe "when the buffer contains UTF-8 surrogate pairs", ->
|
||||
describe "when the buffer contains surrogate pairs", ->
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
@@ -430,7 +429,7 @@ describe "TokenizedBuffer", ->
|
||||
tokenizedBuffer.destroy()
|
||||
buffer.release()
|
||||
|
||||
it "renders each UTF-8 surrogate pair as its own atomic token", ->
|
||||
it "renders each surrogate pair as its own atomic token", ->
|
||||
screenLine0 = tokenizedBuffer.lineForScreenRow(0)
|
||||
expect(screenLine0.text).toBe "'abc\uD835\uDF97def'"
|
||||
{ tokens } = screenLine0
|
||||
@@ -447,12 +446,11 @@ describe "TokenizedBuffer", ->
|
||||
expect(screenLine1.text).toBe "//\uD835\uDF97xyz"
|
||||
{ tokens } = screenLine1
|
||||
|
||||
expect(tokens.length).toBe 4
|
||||
expect(tokens.length).toBe 3
|
||||
expect(tokens[0].value).toBe '//'
|
||||
expect(tokens[1].value).toBe '\uD835\uDF97'
|
||||
expect(tokens[1].value).toBeTruthy()
|
||||
expect(tokens[2].value).toBe 'xyz'
|
||||
expect(tokens[3].value).toBe ''
|
||||
|
||||
describe "when the grammar is tokenized", ->
|
||||
it "emits the `tokenized` event", ->
|
||||
@@ -657,65 +655,3 @@ describe "TokenizedBuffer", ->
|
||||
|
||||
buffer.setText('\n\n\n')
|
||||
expect(tokenizedBuffer.lineForScreenRow(1).indentLevel).toBe 0
|
||||
|
||||
describe "when the changed lines are surrounded by whitespace-only lines", ->
|
||||
it "updates the indentLevel of empty lines that precede the change", ->
|
||||
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 0
|
||||
|
||||
buffer.insert([12, 0], '\n')
|
||||
buffer.insert([13, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 1
|
||||
|
||||
it "updates empty line indent guides when the empty line is the last line", ->
|
||||
buffer.insert([12, 2], '\n')
|
||||
|
||||
# The newline and he tab need to be in two different operations to surface the bug
|
||||
buffer.insert([12, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 1
|
||||
|
||||
buffer.insert([12, 0], ' ')
|
||||
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(14)).not.toBeDefined()
|
||||
|
||||
it "updates the indentLevel of empty lines surrounding a change that inserts lines", ->
|
||||
# create some new lines
|
||||
buffer.insert([7, 0], '\n\n')
|
||||
buffer.insert([5, 0], '\n\n')
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 3
|
||||
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 3
|
||||
expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 2
|
||||
|
||||
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
|
||||
|
||||
buffer.setTextInRange([[7, 0], [8, 65]], ' one\n two\n three\n four')
|
||||
|
||||
delete changeHandler.argsForCall[0][0].bufferChange
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 8, delta: 2)
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 4
|
||||
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 4
|
||||
expect(tokenizedBuffer.lineForScreenRow(11).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(12).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(13).indentLevel).toBe 2
|
||||
|
||||
it "updates the indentLevel of empty lines surrounding a change that removes lines", ->
|
||||
# create some new lines
|
||||
buffer.insert([7, 0], '\n\n')
|
||||
buffer.insert([5, 0], '\n\n')
|
||||
|
||||
tokenizedBuffer.on "changed", changeHandler = jasmine.createSpy('changeHandler')
|
||||
|
||||
buffer.setTextInRange([[7, 0], [8, 65]], ' ok')
|
||||
|
||||
delete changeHandler.argsForCall[0][0].bufferChange
|
||||
expect(changeHandler).toHaveBeenCalledWith(start: 5, end: 8, delta: -1)
|
||||
|
||||
expect(tokenizedBuffer.lineForScreenRow(5).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(6).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(7).indentLevel).toBe 2 # new text
|
||||
expect(tokenizedBuffer.lineForScreenRow(8).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(9).indentLevel).toBe 2
|
||||
expect(tokenizedBuffer.lineForScreenRow(10).indentLevel).toBe 2 # }
|
||||
|
||||
@@ -4,20 +4,6 @@ describe "TokenizedLine", ->
|
||||
beforeEach ->
|
||||
waitsForPromise -> atom.packages.activatePackage('language-coffee-script')
|
||||
|
||||
describe "::isOnlyWhitespace()", ->
|
||||
beforeEach ->
|
||||
waitsForPromise ->
|
||||
atom.project.open('coffee.coffee').then (o) -> editor = o
|
||||
|
||||
it "returns true when the line is only whitespace", ->
|
||||
expect(editor.lineForScreenRow(3).isOnlyWhitespace()).toBe true
|
||||
expect(editor.lineForScreenRow(7).isOnlyWhitespace()).toBe true
|
||||
expect(editor.lineForScreenRow(23).isOnlyWhitespace()).toBe true
|
||||
|
||||
it "returns false when the line is not only whitespace", ->
|
||||
expect(editor.lineForScreenRow(0).isOnlyWhitespace()).toBe false
|
||||
expect(editor.lineForScreenRow(2).isOnlyWhitespace()).toBe false
|
||||
|
||||
describe "::getScopeTree()", ->
|
||||
it "returns a tree whose inner nodes are scopes and whose leaf nodes are tokens in those scopes", ->
|
||||
[tokens, tokenIndex] = []
|
||||
|
||||
@@ -309,28 +309,3 @@ describe "Workspace", ->
|
||||
expect(handler.callCount).toBe 1
|
||||
editorCopy = editor.copy()
|
||||
expect(handler.callCount).toBe 2
|
||||
|
||||
it "stores the active grammars used by all the open editors", ->
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-javascript')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-coffee-script')
|
||||
|
||||
waitsForPromise ->
|
||||
atom.workspace.open('sample.coffee')
|
||||
|
||||
runs ->
|
||||
atom.workspace.getActiveEditor().setText('i = /test/;')
|
||||
|
||||
state = atom.workspace.serialize()
|
||||
expect(state.packagesWithActiveGrammars).toEqual ['language-coffee-script', 'language-javascript']
|
||||
|
||||
jsPackage = atom.packages.getLoadedPackage('language-javascript')
|
||||
coffeePackage = atom.packages.getLoadedPackage('language-coffee-script')
|
||||
spyOn(jsPackage, 'loadGrammarsSync')
|
||||
spyOn(coffeePackage, 'loadGrammarsSync')
|
||||
|
||||
workspace2 = Workspace.deserialize(state)
|
||||
expect(jsPackage.loadGrammarsSync.callCount).toBe 1
|
||||
expect(coffeePackage.loadGrammarsSync.callCount).toBe 1
|
||||
|
||||
+7
-8
@@ -135,6 +135,13 @@ class Atom extends Model
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
@emit 'uncaught-error', arguments...
|
||||
|
||||
nativeConsoleError = console.error
|
||||
|
||||
console.error = =>
|
||||
@openDevTools()
|
||||
@executeJavaScriptInDevTools('InspectorFrontendAPI.showConsole()')
|
||||
nativeConsoleError.call console, arguments...
|
||||
|
||||
@unsubscribe()
|
||||
@setBodyPlatformClass()
|
||||
|
||||
@@ -258,20 +265,13 @@ class Atom extends Model
|
||||
|
||||
deserializeProject: ->
|
||||
Project = require './project'
|
||||
|
||||
startTime = Date.now()
|
||||
@project ?= @deserializers.deserialize(@state.project) ? new Project(path: @getLoadSettings().initialPath)
|
||||
@deserializeTimings.project = Date.now() - startTime
|
||||
|
||||
deserializeWorkspaceView: ->
|
||||
Workspace = require './workspace'
|
||||
WorkspaceView = require './workspace-view'
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = new WorkspaceView(@workspace)
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
@keymaps.defaultTarget = @workspaceView[0]
|
||||
$(@workspaceViewParentSelector).append(@workspaceView)
|
||||
|
||||
@@ -280,7 +280,6 @@ class Atom extends Model
|
||||
delete @state.packageStates
|
||||
|
||||
deserializeEditorWindow: ->
|
||||
@deserializeTimings = {}
|
||||
@deserializePackageStates()
|
||||
@deserializeProject()
|
||||
@deserializeWorkspaceView()
|
||||
|
||||
@@ -60,8 +60,7 @@ class ContextMenuManager
|
||||
# editor is in dev mode.
|
||||
addBySelector: (selector, definition, {devMode}={}) ->
|
||||
definitions = if devMode then @devModeDefinitions else @definitions
|
||||
unless _.findWhere(definitions[selector], definition)
|
||||
(definitions[selector] ?= []).push(definition)
|
||||
(definitions[selector] ?= []).push(definition)
|
||||
|
||||
# Returns definitions which match the element and devMode.
|
||||
definitionsForElement: (element, {devMode}={}) ->
|
||||
|
||||
@@ -1,29 +1,16 @@
|
||||
React = require 'react-atom-fork'
|
||||
{div} = require 'reactionary-atom-fork'
|
||||
{isEqualForProperties} = require 'underscore-plus'
|
||||
|
||||
module.exports =
|
||||
CursorComponent = React.createClass
|
||||
displayName: 'CursorComponent'
|
||||
|
||||
render: ->
|
||||
{pixelRect, defaultCharWidth} = @props
|
||||
{height, width} = pixelRect
|
||||
width = defaultCharWidth if width is 0
|
||||
WebkitTransform = @getTransform()
|
||||
|
||||
div className: 'cursor', style: {height, width, WebkitTransform}
|
||||
|
||||
getTransform: ->
|
||||
{pixelRect, scrollTop, scrollLeft, useHardwareAcceleration} = @props
|
||||
{top, left} = pixelRect
|
||||
{editor, screenRange, scrollTop, scrollLeft, defaultCharWidth} = @props
|
||||
{top, left, height, width} = editor.pixelRectForScreenRange(screenRange)
|
||||
top -= scrollTop
|
||||
left -= scrollLeft
|
||||
width = defaultCharWidth if width is 0
|
||||
WebkitTransform = "translate3d(#{left}px, #{top}px, 0px)"
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(#{left}px, #{top}px, 0px)"
|
||||
else
|
||||
"translate(#{left}px, #{top}px)"
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
not isEqualForProperties(newProps, @props, 'pixelRect', 'scrollTop', 'scrollLeft', 'defaultCharWidth')
|
||||
div className: 'cursor', style: {height, width, WebkitTransform}
|
||||
|
||||
+5
-4
@@ -29,6 +29,9 @@ class Cursor extends Model
|
||||
# Supports old editor view
|
||||
@needsAutoscroll ?= @isLastCursor() and !textChanged
|
||||
|
||||
# Supports react editor view
|
||||
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition
|
||||
|
||||
@goalColumn = null
|
||||
|
||||
movedEvent =
|
||||
@@ -52,10 +55,8 @@ class Cursor extends Model
|
||||
changePosition: (options, fn) ->
|
||||
@clearSelection()
|
||||
@needsAutoscroll = options.autoscroll ? @isLastCursor()
|
||||
fn()
|
||||
if @needsAutoscroll
|
||||
@emit 'autoscrolled' # Support legacy editor
|
||||
@autoscroll() if @needsAutoscroll and @editor.manageScrollPosition # Support react editor view
|
||||
unless fn()
|
||||
@emit 'autoscrolled' if @needsAutoscroll
|
||||
|
||||
getPixelRect: ->
|
||||
@editor.pixelRectForScreenRange(@getScreenRange())
|
||||
|
||||
@@ -12,7 +12,7 @@ CursorsComponent = React.createClass
|
||||
cursorBlinkIntervalHandle: null
|
||||
|
||||
render: ->
|
||||
{cursorPixelRects, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration} = @props
|
||||
{editor, cursorScreenRanges, scrollTop, scrollLeft, defaultCharWidth} = @props
|
||||
{blinkOff} = @state
|
||||
|
||||
className = 'cursors'
|
||||
@@ -20,8 +20,8 @@ CursorsComponent = React.createClass
|
||||
|
||||
div {className},
|
||||
if @isMounted()
|
||||
for key, pixelRect of cursorPixelRects
|
||||
CursorComponent({key, pixelRect, scrollTop, scrollLeft, defaultCharWidth, useHardwareAcceleration})
|
||||
for key, screenRange of cursorScreenRanges
|
||||
CursorComponent({key, editor, screenRange, scrollTop, scrollLeft, defaultCharWidth})
|
||||
|
||||
getInitialState: ->
|
||||
blinkOff: false
|
||||
@@ -34,14 +34,13 @@ CursorsComponent = React.createClass
|
||||
|
||||
shouldComponentUpdate: (newProps, newState) ->
|
||||
not newState.blinkOff is @state.blinkOff or
|
||||
not isEqualForProperties(newProps, @props, 'cursorPixelRects', 'scrollTop', 'scrollLeft', 'defaultCharWidth', 'useHardwareAcceleration')
|
||||
not isEqualForProperties(newProps, @props,
|
||||
'cursorScreenRanges', 'scrollTop', 'scrollLeft', 'lineHeightInPixels',
|
||||
'defaultCharWidth', 'scopedCharacterWidthsChangeCount'
|
||||
)
|
||||
|
||||
componentWillUpdate: (newProps) ->
|
||||
cursorsMoved = @props.cursorPixelRects? and
|
||||
isEqualForProperties(newProps, @props, 'defaultCharWidth', 'scopedCharacterWidthsChangeCount') and
|
||||
not isEqual(newProps.cursorPixelRects, @props.cursorPixelRects)
|
||||
|
||||
@pauseCursorBlinking() if cursorsMoved
|
||||
@pauseCursorBlinking() if @props.cursorScreenRanges and not isEqual(newProps.cursorScreenRanges, @props.cursorScreenRanges)
|
||||
|
||||
startBlinkingCursors: ->
|
||||
@toggleCursorBlinkHandle = setInterval(@toggleCursorBlink, @props.cursorBlinkPeriod / 2) if @isMounted()
|
||||
|
||||
+16
-54
@@ -29,7 +29,6 @@ class DisplayBuffer extends Model
|
||||
width: null
|
||||
scrollTop: 0
|
||||
scrollLeft: 0
|
||||
scrollWidth: 0
|
||||
|
||||
verticalScrollMargin: 2
|
||||
horizontalScrollMargin: 6
|
||||
@@ -46,8 +45,7 @@ class DisplayBuffer extends Model
|
||||
@markers = {}
|
||||
@foldsByMarkerId = {}
|
||||
@decorationsByMarkerId = {}
|
||||
@decorationMarkerChangedSubscriptions = {}
|
||||
@decorationMarkerDestroyedSubscriptions = {}
|
||||
@decorationMarkerSubscriptions = {}
|
||||
@updateAllScreenLines()
|
||||
@createFoldForMarker(marker) for marker in @buffer.findMarkers(@getFoldMarkerAttributes())
|
||||
@subscribe @tokenizedBuffer, 'grammar-changed', (grammar) => @emit 'grammar-changed', grammar
|
||||
@@ -182,12 +180,9 @@ class DisplayBuffer extends Model
|
||||
getScrollTop: -> @scrollTop
|
||||
setScrollTop: (scrollTop) ->
|
||||
if @manageScrollPosition
|
||||
@scrollTop = Math.round(Math.max(0, Math.min(@getMaxScrollTop(), scrollTop)))
|
||||
@scrollTop = Math.max(0, Math.min(@getScrollHeight() - @getClientHeight(), scrollTop))
|
||||
else
|
||||
@scrollTop = Math.round(scrollTop)
|
||||
|
||||
getMaxScrollTop: ->
|
||||
@getScrollHeight() - @getClientHeight()
|
||||
@scrollTop = scrollTop
|
||||
|
||||
getScrollBottom: -> @scrollTop + @height
|
||||
setScrollBottom: (scrollBottom) ->
|
||||
@@ -197,10 +192,10 @@ class DisplayBuffer extends Model
|
||||
getScrollLeft: -> @scrollLeft
|
||||
setScrollLeft: (scrollLeft) ->
|
||||
if @manageScrollPosition
|
||||
@scrollLeft = Math.round(Math.max(0, Math.min(@getScrollWidth() - @getClientWidth(), scrollLeft)))
|
||||
@scrollLeft = Math.max(0, Math.min(@getScrollWidth() - @getClientWidth(), scrollLeft))
|
||||
@scrollLeft
|
||||
else
|
||||
@scrollLeft = Math.round(scrollLeft)
|
||||
@scrollLeft = scrollLeft
|
||||
|
||||
getScrollRight: -> @scrollLeft + @width
|
||||
setScrollRight: (scrollRight) ->
|
||||
@@ -211,11 +206,7 @@ class DisplayBuffer extends Model
|
||||
setLineHeightInPixels: (@lineHeightInPixels) -> @lineHeightInPixels
|
||||
|
||||
getDefaultCharWidth: -> @defaultCharWidth
|
||||
setDefaultCharWidth: (defaultCharWidth) ->
|
||||
if defaultCharWidth isnt @defaultCharWidth
|
||||
@defaultCharWidth = defaultCharWidth
|
||||
@computeScrollWidth()
|
||||
defaultCharWidth
|
||||
setDefaultCharWidth: (@defaultCharWidth) -> @defaultCharWidth
|
||||
|
||||
getCursorWidth: -> 1
|
||||
|
||||
@@ -230,21 +221,13 @@ class DisplayBuffer extends Model
|
||||
scope.charWidths ?= {}
|
||||
scope.charWidths
|
||||
|
||||
batchCharacterMeasurement: (fn) ->
|
||||
oldChangeCount = @scopedCharacterWidthsChangeCount
|
||||
@batchingCharacterMeasurement = true
|
||||
fn()
|
||||
@batchingCharacterMeasurement = false
|
||||
@characterWidthsChanged() if oldChangeCount isnt @scopedCharacterWidthsChangeCount
|
||||
|
||||
setScopedCharWidth: (scopeNames, char, width) ->
|
||||
@getScopedCharWidths(scopeNames)[char] = width
|
||||
@scopedCharacterWidthsChangeCount++
|
||||
@characterWidthsChanged() unless @batchingCharacterMeasurement
|
||||
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount++
|
||||
|
||||
characterWidthsChanged: ->
|
||||
@computeScrollWidth()
|
||||
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount
|
||||
setScopedCharWidths: (scopeNames, charWidths) ->
|
||||
_.extend(@getScopedCharWidths(scopeNames), charWidths)
|
||||
@emit 'character-widths-changed', @scopedCharacterWidthsChangeCount++
|
||||
|
||||
clearScopedCharWidths: ->
|
||||
@charWidthsByScope = {}
|
||||
@@ -255,7 +238,7 @@ class DisplayBuffer extends Model
|
||||
@getLineCount() * @getLineHeightInPixels()
|
||||
|
||||
getScrollWidth: ->
|
||||
@scrollWidth
|
||||
(@getMaxLineLength() * @getDefaultCharWidth()) + @getCursorWidth()
|
||||
|
||||
getVisibleRowRange: ->
|
||||
return [0, 0] unless @getLineHeightInPixels() > 0
|
||||
@@ -772,18 +755,7 @@ class DisplayBuffer extends Model
|
||||
return
|
||||
|
||||
marker = @getMarker(marker.id)
|
||||
|
||||
@decorationMarkerDestroyedSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', =>
|
||||
@removeAllDecorationsForMarker(marker)
|
||||
|
||||
@decorationMarkerChangedSubscriptions[marker.id] ?= @subscribe marker, 'changed', (event) =>
|
||||
decorations = @decorationsByMarkerId[marker.id]
|
||||
|
||||
# Why check existence? Markers may get destroyed or decorations removed
|
||||
# in the change handler. Bookmarks does this.
|
||||
if decorations?
|
||||
for decoration in decorations
|
||||
@emit 'decoration-changed', marker, decoration, event
|
||||
@decorationMarkerSubscriptions[marker.id] ?= @subscribe marker, 'destroyed', => @removeAllDecorationsForMarker(marker)
|
||||
|
||||
@decorationsByMarkerId[marker.id] ?= []
|
||||
@decorationsByMarkerId[marker.id].push(decoration)
|
||||
@@ -794,8 +766,9 @@ class DisplayBuffer extends Model
|
||||
console.warn 'A decoration cannot be removed from a null marker'
|
||||
return
|
||||
|
||||
return unless decorations = @decorationsByMarkerId[marker.id]
|
||||
return unless @decorationMarkerSubscriptions[marker.id]?
|
||||
|
||||
decorations = @decorationsByMarkerId[marker.id]
|
||||
for i in [decorations.length - 1..0]
|
||||
decoration = decorations[i]
|
||||
if @decorationMatchesPattern(decoration, decorationPattern)
|
||||
@@ -811,12 +784,9 @@ class DisplayBuffer extends Model
|
||||
@removedAllMarkerDecorations(marker)
|
||||
|
||||
removedAllMarkerDecorations: (marker) ->
|
||||
@decorationMarkerChangedSubscriptions[marker.id].off()
|
||||
@decorationMarkerDestroyedSubscriptions[marker.id].off()
|
||||
|
||||
@decorationMarkerSubscriptions[marker.id].off()
|
||||
delete @decorationsByMarkerId[marker.id]
|
||||
delete @decorationMarkerChangedSubscriptions[marker.id]
|
||||
delete @decorationMarkerDestroyedSubscriptions[marker.id]
|
||||
delete @decorationMarkerSubscriptions[marker.id]
|
||||
|
||||
# Retrieves a {DisplayBufferMarker} based on its id.
|
||||
#
|
||||
@@ -984,7 +954,6 @@ class DisplayBuffer extends Model
|
||||
handleTokenizedBufferChange: (tokenizedBufferChange) =>
|
||||
{start, end, delta, bufferChange} = tokenizedBufferChange
|
||||
@updateScreenLines(start, end + 1, delta, delayChangeEvent: bufferChange?)
|
||||
@setScrollTop(Math.min(@getScrollTop(), @getMaxScrollTop())) if @manageScrollPosition and delta < 0
|
||||
|
||||
updateScreenLines: (startBufferRow, endBufferRow, bufferDelta=0, options={}) ->
|
||||
startBufferRow = @rowMap.bufferRowRangeForBufferRow(startBufferRow)[0]
|
||||
@@ -1058,8 +1027,6 @@ class DisplayBuffer extends Model
|
||||
{screenLines, regions}
|
||||
|
||||
findMaxLineLength: (startScreenRow, endScreenRow, newScreenLines) ->
|
||||
oldMaxLineLength = @maxLineLength
|
||||
|
||||
if startScreenRow <= @longestScreenRow < endScreenRow
|
||||
@longestScreenRow = 0
|
||||
@maxLineLength = 0
|
||||
@@ -1075,11 +1042,6 @@ class DisplayBuffer extends Model
|
||||
@longestScreenRow = maxLengthCandidatesStartRow + screenRow
|
||||
@maxLineLength = length
|
||||
|
||||
@computeScrollWidth() if oldMaxLineLength isnt @maxLineLength
|
||||
|
||||
computeScrollWidth: ->
|
||||
@scrollWidth = @pixelPositionForScreenPosition([@longestScreenRow, @maxLineLength]).left + 1
|
||||
|
||||
handleBufferMarkersUpdated: =>
|
||||
if event = @pendingChangeEvent
|
||||
@pendingChangeEvent = null
|
||||
|
||||
+35
-101
@@ -12,7 +12,7 @@ ScrollbarComponent = require './scrollbar-component'
|
||||
ScrollbarCornerComponent = require './scrollbar-corner-component'
|
||||
SubscriberMixin = require './subscriber-mixin'
|
||||
|
||||
DummyHighlightDecoration = {id: 'dummy', startPixelPosition: {top: 0, left: 0}, endPixelPosition: {top: 0, left: 0}, decorations: [{class: 'dummy'}]}
|
||||
DummyHighlightDecoration = {id: 'dummy', screenRange: new Range(new Point(0, 0), new Point(0, 0)), decorations: [{class: 'dummy'}]}
|
||||
|
||||
module.exports =
|
||||
EditorComponent = React.createClass
|
||||
@@ -26,8 +26,6 @@ EditorComponent = React.createClass
|
||||
pendingScrollLeft: null
|
||||
selectOnMouseMove: false
|
||||
updateRequested: false
|
||||
updatesPaused: false
|
||||
updateRequestedWhilePaused: false
|
||||
cursorsMoved: false
|
||||
selectionChanged: false
|
||||
selectionAdded: false
|
||||
@@ -46,10 +44,9 @@ EditorComponent = React.createClass
|
||||
inputEnabled: true
|
||||
scrollViewMeasurementInterval: 100
|
||||
scopedCharacterWidthsChangeCount: null
|
||||
scrollViewMeasurementPaused: false
|
||||
|
||||
render: ->
|
||||
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, showLineNumbers, visible} = @state
|
||||
{focused, fontSize, lineHeight, fontFamily, showIndentGuide, showInvisibles, visible} = @state
|
||||
{editor, cursorBlinkPeriod, cursorBlinkResumeDelay} = @props
|
||||
maxLineNumberDigits = editor.getLineCount().toString().length
|
||||
invisibles = if showInvisibles then @state.invisibles else {}
|
||||
@@ -58,7 +55,7 @@ EditorComponent = React.createClass
|
||||
if @isMounted()
|
||||
renderedRowRange = @getRenderedRowRange()
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
cursorPixelRects = @getCursorPixelRects(renderedRowRange)
|
||||
cursorScreenRanges = @getCursorScreenRanges(renderedRowRange)
|
||||
|
||||
decorations = editor.decorationsForScreenRowRange(renderedStartRow, renderedEndRow)
|
||||
highlightDecorations = @getHighlightDecorations(decorations)
|
||||
@@ -71,13 +68,12 @@ EditorComponent = React.createClass
|
||||
lineHeightInPixels = editor.getLineHeightInPixels()
|
||||
defaultCharWidth = editor.getDefaultCharWidth()
|
||||
scrollViewHeight = editor.getHeight()
|
||||
lineWidth = Math.max(scrollWidth, editor.getWidth())
|
||||
horizontalScrollbarHeight = editor.getHorizontalScrollbarHeight()
|
||||
verticalScrollbarWidth = editor.getVerticalScrollbarWidth()
|
||||
verticallyScrollable = editor.verticallyScrollable()
|
||||
horizontallyScrollable = editor.horizontallyScrollable()
|
||||
hiddenInputStyle = @getHiddenInputPosition()
|
||||
hiddenInputStyle.WebkitTransform = 'translateZ(0)' if @useHardwareAcceleration
|
||||
hiddenInputStyle.WebkitTransform = 'translateZ(0)'
|
||||
if @mouseWheelScreenRow? and not (renderedStartRow <= @mouseWheelScreenRow < renderedEndRow)
|
||||
mouseWheelScreenRow = @mouseWheelScreenRow
|
||||
|
||||
@@ -86,12 +82,11 @@ EditorComponent = React.createClass
|
||||
className += ' has-selection' if hasSelection
|
||||
|
||||
div className: className, style: {fontSize, lineHeight, fontFamily}, tabIndex: -1,
|
||||
if showLineNumbers
|
||||
GutterComponent {
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
|
||||
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
|
||||
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow, @useHardwareAcceleration
|
||||
}
|
||||
GutterComponent {
|
||||
ref: 'gutter', onMouseDown: @onGutterMouseDown, onWidthChanged: @onGutterWidthChanged,
|
||||
lineDecorations, defaultCharWidth, editor, renderedRowRange, maxLineNumberDigits, scrollViewHeight,
|
||||
scrollTop, scrollHeight, lineHeightInPixels, @pendingChanges, mouseWheelScreenRow
|
||||
}
|
||||
|
||||
div ref: 'scrollView', className: 'scroll-view', onMouseDown: @onMouseDown,
|
||||
InputComponent
|
||||
@@ -102,15 +97,15 @@ EditorComponent = React.createClass
|
||||
onBlur: @onInputBlurred
|
||||
|
||||
CursorsComponent {
|
||||
scrollTop, scrollLeft, cursorPixelRects, cursorBlinkPeriod, cursorBlinkResumeDelay,
|
||||
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount, @useHardwareAcceleration
|
||||
editor, scrollTop, scrollLeft, cursorScreenRanges, cursorBlinkPeriod, cursorBlinkResumeDelay,
|
||||
lineHeightInPixels, defaultCharWidth, @scopedCharacterWidthsChangeCount
|
||||
}
|
||||
LinesComponent {
|
||||
ref: 'lines',
|
||||
editor, lineHeightInPixels, defaultCharWidth, lineDecorations, highlightDecorations,
|
||||
showIndentGuide, renderedRowRange, @pendingChanges, scrollTop, scrollLeft,
|
||||
@scrollingVertically, scrollHeight, scrollWidth, mouseWheelScreenRow, invisibles,
|
||||
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount, lineWidth, @useHardwareAcceleration
|
||||
visible, scrollViewHeight, @scopedCharacterWidthsChangeCount
|
||||
}
|
||||
|
||||
ScrollbarComponent
|
||||
@@ -166,7 +161,7 @@ EditorComponent = React.createClass
|
||||
componentDidMount: ->
|
||||
{editor} = @props
|
||||
|
||||
@scrollViewMeasurementIntervalId = setInterval(@measureScrollView, @scrollViewMeasurementInterval)
|
||||
@scrollViewMeasurementIntervalId = setInterval(@requestScrollViewMeasurement, @scrollViewMeasurementInterval)
|
||||
|
||||
@observeEditor()
|
||||
@listenForDOMEvents()
|
||||
@@ -186,6 +181,8 @@ EditorComponent = React.createClass
|
||||
clearInterval(@scrollViewMeasurementIntervalId)
|
||||
@scrollViewMeasurementIntervalId = null
|
||||
|
||||
componentWillUpdate: ->
|
||||
|
||||
componentDidUpdate: (prevProps, prevState) ->
|
||||
cursorsMoved = @cursorsMoved
|
||||
selectionChanged = @selectionChanged
|
||||
@@ -205,28 +202,14 @@ EditorComponent = React.createClass
|
||||
@remeasureCharacterWidthsIfNeeded(prevState)
|
||||
|
||||
requestUpdate: ->
|
||||
if @updatesPaused
|
||||
@updateRequestedWhilePaused = true
|
||||
return
|
||||
|
||||
if @performSyncUpdates ? EditorComponent.performSyncUpdates
|
||||
@forceUpdate()
|
||||
else unless @updateRequested
|
||||
@updateRequested = true
|
||||
setImmediate =>
|
||||
process.nextTick =>
|
||||
@updateRequested = false
|
||||
@forceUpdate() if @isMounted()
|
||||
|
||||
requestAnimationFrame: (fn) ->
|
||||
@updatesPaused = true
|
||||
@pauseScrollViewMeasurement()
|
||||
requestAnimationFrame =>
|
||||
fn()
|
||||
@updatesPaused = false
|
||||
if @updateRequestedWhilePaused and @isMounted()
|
||||
@updateRequestedWhilePaused = false
|
||||
@forceUpdate()
|
||||
|
||||
getRenderedRowRange: ->
|
||||
{editor, lineOverdrawMargin} = @props
|
||||
[visibleStartRow, visibleEndRow] = editor.getVisibleRowRange()
|
||||
@@ -259,40 +242,20 @@ EditorComponent = React.createClass
|
||||
cursorScreenRanges[cursor.id] = screenRange
|
||||
cursorScreenRanges
|
||||
|
||||
getCursorPixelRects: (renderedRowRange) ->
|
||||
{editor} = @props
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
|
||||
cursorPixelRects = {}
|
||||
for selection in editor.getSelections() when selection.isEmpty()
|
||||
{cursor} = selection
|
||||
screenRange = cursor.getScreenRange()
|
||||
if renderedStartRow <= screenRange.start.row < renderedEndRow
|
||||
cursorPixelRects[cursor.id] = editor.pixelRectForScreenRange(screenRange)
|
||||
cursorPixelRects
|
||||
|
||||
getLineDecorations: (decorationsByMarkerId) ->
|
||||
{editor} = @props
|
||||
decorationsByScreenRow = {}
|
||||
for markerId, decorations of decorationsByMarkerId
|
||||
marker = editor.getMarker(markerId)
|
||||
screenRange = null
|
||||
headScreenRow = null
|
||||
if marker.isValid()
|
||||
for decoration in decorations
|
||||
if editor.decorationMatchesType(decoration, 'gutter') or editor.decorationMatchesType(decoration, 'line')
|
||||
screenRange ?= marker.getScreenRange()
|
||||
headScreenRow ?= marker.getHeadScreenPosition().row
|
||||
startRow = screenRange.start.row
|
||||
endRow = screenRange.end.row
|
||||
endRow-- if not screenRange.isEmpty() and screenRange.end.column == 0
|
||||
for screenRow in [startRow..endRow]
|
||||
continue if decoration.onlyHead and screenRow isnt headScreenRow
|
||||
if screenRange.isEmpty()
|
||||
continue if decoration.onlyNonEmpty
|
||||
else
|
||||
continue if decoration.onlyEmpty
|
||||
|
||||
decorationsByScreenRow[screenRow] ?= []
|
||||
decorationsByScreenRow[screenRow].push decoration
|
||||
|
||||
@@ -303,15 +266,10 @@ EditorComponent = React.createClass
|
||||
filteredDecorations = {}
|
||||
for markerId, decorations of decorationsByMarkerId
|
||||
marker = editor.getMarker(markerId)
|
||||
screenRange = marker.getScreenRange()
|
||||
if marker.isValid() and not screenRange.isEmpty()
|
||||
if marker.isValid() and not marker.getScreenRange().isEmpty()
|
||||
for decoration in decorations
|
||||
if editor.decorationMatchesType(decoration, 'highlight')
|
||||
filteredDecorations[markerId] ?=
|
||||
id: markerId
|
||||
startPixelPosition: editor.pixelPositionForScreenPosition(screenRange.start)
|
||||
endPixelPosition: editor.pixelPositionForScreenPosition(screenRange.end)
|
||||
decorations: []
|
||||
filteredDecorations[markerId] ?= {id: markerId, screenRange: marker.getScreenRange(), decorations: []}
|
||||
filteredDecorations[markerId].decorations.push decoration
|
||||
|
||||
# At least in Chromium 31, removing the last highlight causes a rendering
|
||||
@@ -329,7 +287,6 @@ EditorComponent = React.createClass
|
||||
@subscribe editor, 'selection-added', @onSelectionAdded
|
||||
@subscribe editor, 'decoration-added', @onDecorationChanged
|
||||
@subscribe editor, 'decoration-removed', @onDecorationChanged
|
||||
@subscribe editor, 'decoration-changed', @onDecorationChanged
|
||||
@subscribe editor, 'character-widths-changed', @onCharacterWidthsChanged
|
||||
@subscribe editor.$scrollTop.changes, @onScrollTopChanged
|
||||
@subscribe editor.$scrollLeft.changes, @requestUpdate
|
||||
@@ -368,13 +325,12 @@ EditorComponent = React.createClass
|
||||
# 5. textInput fired; event.data == the completion string
|
||||
|
||||
selectedText = null
|
||||
node.addEventListener 'compositionstart', ->
|
||||
node.addEventListener 'compositionstart', =>
|
||||
selectedText = editor.getSelectedText()
|
||||
node.addEventListener 'compositionupdate', (event) ->
|
||||
node.addEventListener 'compositionupdate', (event) =>
|
||||
editor.insertText(event.data, select: true, undo: 'skip')
|
||||
node.addEventListener 'compositionend', (event) ->
|
||||
node.addEventListener 'compositionend', =>
|
||||
editor.insertText(selectedText, select: true, undo: 'skip')
|
||||
event.target.value = ''
|
||||
|
||||
listenForCommands: ->
|
||||
{parentView, editor, mini} = @props
|
||||
@@ -494,9 +450,7 @@ EditorComponent = React.createClass
|
||||
@subscribe atom.config.observe 'editor.showIndentGuide', @setShowIndentGuide
|
||||
@subscribe atom.config.observe 'editor.invisibles', @setInvisibles
|
||||
@subscribe atom.config.observe 'editor.showInvisibles', @setShowInvisibles
|
||||
@subscribe atom.config.observe 'editor.showLineNumbers', @setShowLineNumbers
|
||||
@subscribe atom.config.observe 'editor.scrollSensitivity', @setScrollSensitivity
|
||||
@subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration
|
||||
|
||||
onFocus: ->
|
||||
@refs.input.focus()
|
||||
@@ -530,25 +484,24 @@ EditorComponent = React.createClass
|
||||
onVerticalScroll: (scrollTop) ->
|
||||
{editor} = @props
|
||||
|
||||
return if @updateRequested or scrollTop is editor.getScrollTop()
|
||||
return if scrollTop is editor.getScrollTop()
|
||||
|
||||
animationFramePending = @pendingScrollTop?
|
||||
@pendingScrollTop = scrollTop
|
||||
unless animationFramePending
|
||||
@requestAnimationFrame =>
|
||||
pendingScrollTop = @pendingScrollTop
|
||||
requestAnimationFrame =>
|
||||
@props.editor.setScrollTop(@pendingScrollTop)
|
||||
@pendingScrollTop = null
|
||||
@props.editor.setScrollTop(pendingScrollTop)
|
||||
|
||||
onHorizontalScroll: (scrollLeft) ->
|
||||
{editor} = @props
|
||||
|
||||
return if @updateRequested or scrollLeft is editor.getScrollLeft()
|
||||
return if scrollLeft is editor.getScrollLeft()
|
||||
|
||||
animationFramePending = @pendingScrollLeft?
|
||||
@pendingScrollLeft = scrollLeft
|
||||
unless animationFramePending
|
||||
@requestAnimationFrame =>
|
||||
requestAnimationFrame =>
|
||||
@props.editor.setScrollLeft(@pendingScrollLeft)
|
||||
@pendingScrollLeft = null
|
||||
|
||||
@@ -569,7 +522,7 @@ EditorComponent = React.createClass
|
||||
@clearMouseWheelScreenRowAfterDelay()
|
||||
|
||||
unless animationFramePending
|
||||
@requestAnimationFrame =>
|
||||
requestAnimationFrame =>
|
||||
{editor} = @props
|
||||
editor.setScrollTop(editor.getScrollTop() + @pendingVerticalScrollDelta)
|
||||
editor.setScrollLeft(editor.getScrollLeft() + @pendingHorizontalScrollDelta)
|
||||
@@ -587,7 +540,7 @@ EditorComponent = React.createClass
|
||||
return unless event.button is 0 # only handle the left mouse button
|
||||
|
||||
{editor} = @props
|
||||
{detail, shiftKey, metaKey, ctrlKey} = event
|
||||
{detail, shiftKey, metaKey} = event
|
||||
screenPosition = @screenPositionForMouseEvent(event)
|
||||
|
||||
if event.target?.classList.contains('fold-marker')
|
||||
@@ -597,7 +550,7 @@ EditorComponent = React.createClass
|
||||
|
||||
if shiftKey
|
||||
editor.selectToScreenPosition(screenPosition)
|
||||
else if metaKey or (ctrlKey and process.platform isnt 'darwin')
|
||||
else if metaKey
|
||||
editor.addCursorAtScreenPosition(screenPosition)
|
||||
else
|
||||
editor.setCursorScreenPosition(screenPosition)
|
||||
@@ -670,7 +623,7 @@ EditorComponent = React.createClass
|
||||
onScrollTopChanged: ->
|
||||
@scrollingVertically = true
|
||||
@requestUpdate()
|
||||
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 200)
|
||||
@onStoppedScrollingAfterDelay ?= debounce(@onStoppedScrolling, 100)
|
||||
@onStoppedScrollingAfterDelay()
|
||||
|
||||
onStoppedScrolling: ->
|
||||
@@ -697,7 +650,7 @@ EditorComponent = React.createClass
|
||||
dragging = false
|
||||
lastMousePosition = {}
|
||||
animationLoop = =>
|
||||
@requestAnimationFrame =>
|
||||
requestAnimationFrame =>
|
||||
if dragging
|
||||
screenPosition = @screenPositionForMouseEvent(lastMousePosition)
|
||||
dragHandler(screenPosition)
|
||||
@@ -724,18 +677,8 @@ EditorComponent = React.createClass
|
||||
window.addEventListener('mousemove', onMouseMove)
|
||||
window.addEventListener('mouseup', onMouseUp)
|
||||
|
||||
pauseScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = true
|
||||
@resumeScrollViewMeasurementAfterDelay ?= debounce(@resumeScrollViewMeasurement, 100)
|
||||
@resumeScrollViewMeasurementAfterDelay()
|
||||
|
||||
resumeScrollViewMeasurement: ->
|
||||
@scrollViewMeasurementPaused = false
|
||||
|
||||
resumeScrollViewMeasurementAfterDelay: null # created lazily
|
||||
|
||||
requestScrollViewMeasurement: ->
|
||||
return if @scrollViewMeasurementRequested
|
||||
return if @measurementPending
|
||||
|
||||
@scrollViewMeasurementRequested = true
|
||||
requestAnimationFrame =>
|
||||
@@ -747,7 +690,6 @@ EditorComponent = React.createClass
|
||||
# and use the scrollHeight / scrollWidth as its height and width in
|
||||
# calculations.
|
||||
measureScrollView: ->
|
||||
return if @scrollViewMeasurementPaused
|
||||
return unless @isMounted()
|
||||
|
||||
{editor} = @props
|
||||
@@ -893,18 +835,10 @@ EditorComponent = React.createClass
|
||||
setShowInvisibles: (showInvisibles) ->
|
||||
@setState({showInvisibles})
|
||||
|
||||
setShowLineNumbers: (showLineNumbers) ->
|
||||
@setState({showLineNumbers})
|
||||
|
||||
setScrollSensitivity: (scrollSensitivity) ->
|
||||
if scrollSensitivity = parseInt(scrollSensitivity)
|
||||
@scrollSensitivity = Math.abs(scrollSensitivity) / 100
|
||||
|
||||
setUseHardwareAcceleration: (useHardwareAcceleration=true) ->
|
||||
unless @useHardwareAcceleration is useHardwareAcceleration
|
||||
@useHardwareAcceleration = useHardwareAcceleration
|
||||
@requestUpdate()
|
||||
|
||||
screenPositionForMouseEvent: (event) ->
|
||||
pixelPosition = @pixelPositionForMouseEvent(event)
|
||||
@props.editor.screenPositionForPixelPosition(pixelPosition)
|
||||
@@ -913,9 +847,9 @@ EditorComponent = React.createClass
|
||||
{editor} = @props
|
||||
{clientX, clientY} = event
|
||||
|
||||
linesClientRect = @refs.lines.getDOMNode().getBoundingClientRect()
|
||||
top = clientY - linesClientRect.top
|
||||
left = clientX - linesClientRect.left
|
||||
scrollViewClientRect = @refs.scrollView.getDOMNode().getBoundingClientRect()
|
||||
top = clientY - scrollViewClientRect.top + editor.getScrollTop()
|
||||
left = clientX - scrollViewClientRect.left + editor.getScrollLeft()
|
||||
{top, left}
|
||||
|
||||
getModel: ->
|
||||
|
||||
@@ -57,7 +57,6 @@ class EditorView extends View
|
||||
softTabs: true
|
||||
softWrapAtPreferredLineLength: false
|
||||
scrollSensitivity: 40
|
||||
useHardwareAcceleration: true
|
||||
|
||||
@nextEditorId: 1
|
||||
|
||||
|
||||
+11
-28
@@ -217,7 +217,6 @@ class Editor extends Model
|
||||
@subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args...
|
||||
@subscribe @displayBuffer, "decoration-added", (args...) => @emit 'decoration-added', args...
|
||||
@subscribe @displayBuffer, "decoration-removed", (args...) => @emit 'decoration-removed', args...
|
||||
@subscribe @displayBuffer, "decoration-changed", (args...) => @emit 'decoration-changed', args...
|
||||
@subscribe @displayBuffer, "character-widths-changed", (changeCount) => @emit 'character-widths-changed', changeCount
|
||||
|
||||
getViewClass: ->
|
||||
@@ -1085,29 +1084,17 @@ class Editor extends Model
|
||||
@displayBuffer.decorationsForScreenRowRange(startScreenRow, endScreenRow)
|
||||
|
||||
# Public: Adds a decoration that tracks a {Marker}. When the marker moves,
|
||||
# is invalidated, or is destroyed, the decoration will be updated to reflect
|
||||
# the marker's state.
|
||||
# is invalidated, or is destroyed, the decoration will be updated to reflect the marker's state.
|
||||
#
|
||||
# marker - A {Marker} you want this decoration to follow.
|
||||
# decoration - An {Object} representing the decoration eg. `{type: 'gutter', class: 'linter-error'}`
|
||||
# The decoration can contain the following keys:
|
||||
# * type: There are a few supported decoration types:
|
||||
# * `gutter`: Applies the decoration to the line numbers spanned by the
|
||||
# marker.
|
||||
# * `line`: Applies the decoration to the lines spanned by the marker.
|
||||
# * `highlight`: Applies the decoration to a "highlight" behind the
|
||||
# marked range. When the user selects text, the selection is
|
||||
# visualized with a highlight decoration internally.
|
||||
# * class: This CSS class will be applied to the decorated line number,
|
||||
# line, or highlight.
|
||||
# * onlyHead: If `true`, the decoration will only be applied to the head
|
||||
# of the marker. Only applicable to the `line` and `gutter` types.
|
||||
# * onlyEmpty: If `true`, the decoration will only be applied if the
|
||||
# associated marker is empty. Only applicable to the `line` and
|
||||
# `gutter` types.
|
||||
# * onlyNonEmpty: If `true`, the decoration will only be applied if the
|
||||
# associated marker is non-empty. Only applicable to the `line` and
|
||||
# gutter types.
|
||||
# There are a few supported decoration types:
|
||||
# * `gutter`: `{type: 'gutter', class: 'linter-error'}` Will add a class to the gutter rows associated with the marker.
|
||||
# * `line`: `{type: 'line', class: 'linter-error'}` Will add a class to the editor lines associated with the marker.
|
||||
# * `highlight`: `{type: 'highlight', class: 'linter-error'}` Will highlight the region of the buffer associated with the marker. Your specified class will be added to the highlight.
|
||||
#
|
||||
# marker - the {Marker} you want this decoration to follow
|
||||
# decoration - the {Object} decoration eg. `{type: 'gutter', class: 'linter-error'}`
|
||||
#
|
||||
# Returns nothing
|
||||
addDecorationForMarker: (marker, decoration) ->
|
||||
@displayBuffer.addDecorationForMarker(marker, decoration)
|
||||
|
||||
@@ -1250,9 +1237,7 @@ class Editor extends Model
|
||||
addCursor: (marker) ->
|
||||
cursor = new Cursor(editor: this, marker: marker)
|
||||
@cursors.push(cursor)
|
||||
@addDecorationForMarker(marker, type: 'gutter', class: 'cursor-line')
|
||||
@addDecorationForMarker(marker, type: 'gutter', class: 'cursor-line-no-selection', onlyHead: true, onlyEmpty: true)
|
||||
@addDecorationForMarker(marker, type: 'line', class: 'cursor-line', onlyEmpty: true)
|
||||
@addDecorationForMarker(marker, type: ['gutter', 'line'], class: 'cursor-line')
|
||||
@emit 'cursor-added', cursor
|
||||
cursor
|
||||
|
||||
@@ -1989,8 +1974,6 @@ class Editor extends Model
|
||||
getLineHeightInPixels: -> @displayBuffer.getLineHeightInPixels()
|
||||
setLineHeightInPixels: (lineHeightInPixels) -> @displayBuffer.setLineHeightInPixels(lineHeightInPixels)
|
||||
|
||||
batchCharacterMeasurement: (fn) -> @displayBuffer.batchCharacterMeasurement(fn)
|
||||
|
||||
getScopedCharWidth: (scopeNames, char) -> @displayBuffer.getScopedCharWidth(scopeNames, char)
|
||||
setScopedCharWidth: (scopeNames, char, width) -> @displayBuffer.setScopedCharWidth(scopeNames, char, width)
|
||||
|
||||
|
||||
@@ -35,11 +35,6 @@ class Fold
|
||||
# Returns a {Range}.
|
||||
getBufferRange: ({includeNewline}={}) ->
|
||||
range = @marker.getRange()
|
||||
|
||||
if range.end.row > range.start.row and nextFold = @displayBuffer.largestFoldStartingAtBufferRow(range.end.row)
|
||||
nextRange = nextFold.getBufferRange()
|
||||
range = new Range(range.start, nextRange.end)
|
||||
|
||||
if includeNewline
|
||||
range = range.copy()
|
||||
range.end.row++
|
||||
|
||||
@@ -15,22 +15,14 @@ GutterComponent = React.createClass
|
||||
measuredWidth: null
|
||||
|
||||
render: ->
|
||||
{scrollHeight, scrollViewHeight, onMouseDown} = @props
|
||||
{scrollHeight, scrollViewHeight, scrollTop, onMouseDown} = @props
|
||||
|
||||
div className: 'gutter', onClick: @onClick, onMouseDown: onMouseDown,
|
||||
# The line-numbers div must have the 'editor-colors' class so it has an
|
||||
# opaque background to avoid sub-pixel anti-aliasing problems on the GPU
|
||||
div className: 'gutter line-numbers editor-colors', ref: 'lineNumbers', style:
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
WebkitTransform: @getTransform()
|
||||
|
||||
getTransform: ->
|
||||
{scrollTop, useHardwareAcceleration} = @props
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(0px, #{-scrollTop}px, 0px)"
|
||||
else
|
||||
"translate(0px, #{-scrollTop}px)"
|
||||
WebkitTransform: "translate3d(0px, #{-scrollTop}px, 0px)"
|
||||
|
||||
componentWillMount: ->
|
||||
@lineNumberNodesById = {}
|
||||
@@ -47,7 +39,7 @@ GutterComponent = React.createClass
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'scrollTop', 'lineHeightInPixels', 'mouseWheelScreenRow', 'lineDecorations',
|
||||
'scrollViewHeight', 'useHardwareAcceleration'
|
||||
'scrollViewHeight'
|
||||
)
|
||||
|
||||
{renderedRowRange, pendingChanges, lineDecorations} = newProps
|
||||
|
||||
@@ -1,24 +1,27 @@
|
||||
React = require 'react-atom-fork'
|
||||
{div} = require 'reactionary-atom-fork'
|
||||
{isEqualForProperties} = require 'underscore-plus'
|
||||
|
||||
module.exports =
|
||||
HighlightComponent = React.createClass
|
||||
displayName: 'HighlightComponent'
|
||||
|
||||
render: ->
|
||||
{startPixelPosition, endPixelPosition, decoration} = @props
|
||||
{editor, screenRange, decoration} = @props
|
||||
{start, end} = screenRange
|
||||
rowCount = end.row - start.row + 1
|
||||
startPixelPosition = editor.pixelPositionForScreenPosition(start)
|
||||
endPixelPosition = editor.pixelPositionForScreenPosition(end)
|
||||
|
||||
className = 'highlight'
|
||||
className += " #{decoration.class}" if decoration.class?
|
||||
div {className},
|
||||
if endPixelPosition.top is startPixelPosition.top
|
||||
@renderSingleLineRegions()
|
||||
if rowCount is 1
|
||||
@renderSingleLineRegions(startPixelPosition, endPixelPosition)
|
||||
else
|
||||
@renderMultiLineRegions()
|
||||
@renderMultiLineRegions(startPixelPosition, endPixelPosition, rowCount)
|
||||
|
||||
renderSingleLineRegions: ->
|
||||
{startPixelPosition, endPixelPosition, lineHeightInPixels} = @props
|
||||
renderSingleLineRegions: (startPixelPosition, endPixelPosition) ->
|
||||
{lineHeightInPixels} = @props
|
||||
|
||||
[
|
||||
div className: 'region', key: 0, style:
|
||||
@@ -28,8 +31,8 @@ HighlightComponent = React.createClass
|
||||
width: endPixelPosition.left - startPixelPosition.left
|
||||
]
|
||||
|
||||
renderMultiLineRegions: ->
|
||||
{startPixelPosition, endPixelPosition, lineHeightInPixels} = @props
|
||||
renderMultiLineRegions: (startPixelPosition, endPixelPosition, rowCount) ->
|
||||
{lineHeightInPixels} = @props
|
||||
regions = []
|
||||
index = 0
|
||||
|
||||
@@ -43,11 +46,11 @@ HighlightComponent = React.createClass
|
||||
)
|
||||
|
||||
# Middle rows, extending from left side to right side of screen
|
||||
if endPixelPosition.top - startPixelPosition.top > lineHeightInPixels
|
||||
if rowCount > 2
|
||||
regions.push(
|
||||
div className: 'region', key: index++, style:
|
||||
top: startPixelPosition.top + lineHeightInPixels
|
||||
height: endPixelPosition.top - startPixelPosition.top - lineHeightInPixels
|
||||
height: (rowCount - 2) * lineHeightInPixels
|
||||
left: 0
|
||||
right: 0
|
||||
)
|
||||
@@ -62,6 +65,3 @@ HighlightComponent = React.createClass
|
||||
)
|
||||
|
||||
regions
|
||||
|
||||
shouldComponentUpdate: (newProps) ->
|
||||
not isEqualForProperties(newProps, @props, 'startPixelPosition', 'endPixelPosition', 'lineHeightInPixels')
|
||||
|
||||
@@ -8,16 +8,15 @@ HighlightsComponent = React.createClass
|
||||
displayName: 'HighlightsComponent'
|
||||
|
||||
render: ->
|
||||
div className: 'highlights',
|
||||
@renderHighlights() if @isMounted()
|
||||
div className: 'highlights', @renderHighlights()
|
||||
|
||||
renderHighlights: ->
|
||||
{highlightDecorations, lineHeightInPixels} = @props
|
||||
{editor, highlightDecorations, lineHeightInPixels} = @props
|
||||
|
||||
highlightComponents = []
|
||||
for markerId, {startPixelPosition, endPixelPosition, decorations} of highlightDecorations
|
||||
for markerId, {screenRange, decorations} of highlightDecorations
|
||||
for decoration in decorations
|
||||
highlightComponents.push(HighlightComponent({key: "#{markerId}-#{decoration.class}", startPixelPosition, endPixelPosition, decoration, lineHeightInPixels}))
|
||||
highlightComponents.push(HighlightComponent({key: "#{markerId}-#{decoration.class}", screenRange, decoration, editor, lineHeightInPixels}))
|
||||
|
||||
highlightComponents
|
||||
|
||||
|
||||
@@ -16,25 +16,17 @@ LinesComponent = React.createClass
|
||||
|
||||
render: ->
|
||||
if @isMounted()
|
||||
{editor, highlightDecorations, scrollHeight, scrollWidth} = @props
|
||||
{editor, highlightDecorations, scrollTop, scrollLeft, scrollHeight, scrollWidth} = @props
|
||||
{lineHeightInPixels, defaultCharWidth, scrollViewHeight, scopedCharacterWidthsChangeCount} = @props
|
||||
style =
|
||||
height: Math.max(scrollHeight, scrollViewHeight)
|
||||
width: scrollWidth
|
||||
WebkitTransform: @getTransform()
|
||||
WebkitTransform: "translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
|
||||
|
||||
# The lines div must have the 'editor-colors' class so it has an opaque
|
||||
# background to avoid sub-pixel anti-aliasing problems on the GPU
|
||||
div {className: 'lines editor-colors', style},
|
||||
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount})
|
||||
|
||||
getTransform: ->
|
||||
{scrollTop, scrollLeft, useHardwareAcceleration} = @props
|
||||
|
||||
if useHardwareAcceleration
|
||||
"translate3d(#{-scrollLeft}px, #{-scrollTop}px, 0px)"
|
||||
else
|
||||
"translate(#{-scrollLeft}px, #{-scrollTop}px)"
|
||||
HighlightsComponent({editor, highlightDecorations, lineHeightInPixels, defaultCharWidth, scopedCharacterWidthsChangeCount}) if @isMounted()
|
||||
|
||||
componentWillMount: ->
|
||||
@measuredLines = new WeakSet
|
||||
@@ -47,7 +39,7 @@ LinesComponent = React.createClass
|
||||
return true unless isEqualForProperties(newProps, @props,
|
||||
'renderedRowRange', 'lineDecorations', 'highlightDecorations', 'lineHeightInPixels', 'defaultCharWidth',
|
||||
'scrollTop', 'scrollLeft', 'showIndentGuide', 'scrollingVertically', 'invisibles', 'visible',
|
||||
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount', 'lineWidth', 'useHardwareAcceleration'
|
||||
'scrollViewHeight', 'mouseWheelScreenRow', 'scopedCharacterWidthsChangeCount'
|
||||
)
|
||||
|
||||
{renderedRowRange, pendingChanges} = newProps
|
||||
@@ -62,20 +54,20 @@ LinesComponent = React.createClass
|
||||
|
||||
@clearScreenRowCaches() unless prevProps.lineHeightInPixels is @props.lineHeightInPixels
|
||||
@removeLineNodes() unless isEqualForProperties(prevProps, @props, 'showIndentGuide', 'invisibles')
|
||||
@updateLines(@props.lineWidth isnt prevProps.lineWidth)
|
||||
@updateLines()
|
||||
@measureCharactersInNewLines() if visible and not scrollingVertically
|
||||
|
||||
clearScreenRowCaches: ->
|
||||
@screenRowsByLineId = {}
|
||||
@lineIdsByScreenRow = {}
|
||||
|
||||
updateLines: (updateWidth) ->
|
||||
updateLines: ->
|
||||
{editor, renderedRowRange, showIndentGuide, selectionChanged, lineDecorations} = @props
|
||||
[startRow, endRow] = renderedRowRange
|
||||
|
||||
visibleLines = editor.linesForScreenRows(startRow, endRow - 1)
|
||||
@removeLineNodes(visibleLines)
|
||||
@appendOrUpdateVisibleLineNodes(visibleLines, startRow, updateWidth)
|
||||
@appendOrUpdateVisibleLineNodes(visibleLines, startRow)
|
||||
|
||||
removeLineNodes: (visibleLines=[]) ->
|
||||
{mouseWheelScreenRow} = @props
|
||||
@@ -91,7 +83,7 @@ LinesComponent = React.createClass
|
||||
delete @renderedDecorationsByLineId[lineId]
|
||||
node.removeChild(lineNode)
|
||||
|
||||
appendOrUpdateVisibleLineNodes: (visibleLines, startRow, updateWidth) ->
|
||||
appendOrUpdateVisibleLineNodes: (visibleLines, startRow) ->
|
||||
{lineDecorations} = @props
|
||||
|
||||
newLines = null
|
||||
@@ -101,7 +93,7 @@ LinesComponent = React.createClass
|
||||
screenRow = startRow + index
|
||||
|
||||
if @hasLineNode(line.id)
|
||||
@updateLineNode(line, screenRow, updateWidth)
|
||||
@updateLineNode(line, screenRow)
|
||||
else
|
||||
newLines ?= []
|
||||
newLinesHTML ?= ""
|
||||
@@ -126,7 +118,7 @@ LinesComponent = React.createClass
|
||||
@lineNodesByLineId.hasOwnProperty(lineId)
|
||||
|
||||
buildLineHTML: (line, screenRow) ->
|
||||
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations, lineWidth} = @props
|
||||
{editor, mini, showIndentGuide, lineHeightInPixels, lineDecorations} = @props
|
||||
{tokens, text, lineEnding, fold, isSoftWrapped, indentLevel} = line
|
||||
|
||||
classes = ''
|
||||
@@ -137,7 +129,7 @@ LinesComponent = React.createClass
|
||||
classes += 'line'
|
||||
|
||||
top = screenRow * lineHeightInPixels
|
||||
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px; width: #{lineWidth}px;\" data-screen-row=\"#{screenRow}\">"
|
||||
lineHTML = "<div class=\"#{classes}\" style=\"position: absolute; top: #{top}px;\" data-screen-row=\"#{screenRow}\">"
|
||||
|
||||
if text is ""
|
||||
lineHTML += @buildEmptyLineInnerHTML(line)
|
||||
@@ -211,8 +203,8 @@ LinesComponent = React.createClass
|
||||
scopeStack.push(scope)
|
||||
"<span class=\"#{scope.replace(/\.+/g, ' ')}\">"
|
||||
|
||||
updateLineNode: (line, screenRow, updateWidth) ->
|
||||
{editor, lineHeightInPixels, lineDecorations, lineWidth} = @props
|
||||
updateLineNode: (line, screenRow) ->
|
||||
{editor, lineHeightInPixels, lineDecorations} = @props
|
||||
lineNode = @lineNodesByLineId[line.id]
|
||||
|
||||
decorations = lineDecorations[screenRow]
|
||||
@@ -227,8 +219,6 @@ LinesComponent = React.createClass
|
||||
if editor.decorationMatchesType(decoration, 'line') and not _.deepContains(previousDecorations, decoration)
|
||||
lineNode.classList.add(decoration.class)
|
||||
|
||||
lineNode.style.width = lineWidth + 'px' if updateWidth
|
||||
|
||||
unless @screenRowsByLineId[line.id] is screenRow
|
||||
lineNode.style.top = screenRow * lineHeightInPixels + 'px'
|
||||
lineNode.dataset.screenRow = screenRow
|
||||
@@ -258,12 +248,10 @@ LinesComponent = React.createClass
|
||||
[visibleStartRow, visibleEndRow] = @props.renderedRowRange
|
||||
node = @getDOMNode()
|
||||
|
||||
editor.batchCharacterMeasurement =>
|
||||
for tokenizedLine in editor.linesForScreenRows(visibleStartRow, visibleEndRow - 1)
|
||||
unless @measuredLines.has(tokenizedLine)
|
||||
lineNode = @lineNodesByLineId[tokenizedLine.id]
|
||||
@measureCharactersInLine(tokenizedLine, lineNode)
|
||||
return
|
||||
for tokenizedLine in editor.linesForScreenRows(visibleStartRow, visibleEndRow - 1)
|
||||
unless @measuredLines.has(tokenizedLine)
|
||||
lineNode = @lineNodesByLineId[tokenizedLine.id]
|
||||
@measureCharactersInLine(tokenizedLine, lineNode)
|
||||
|
||||
measureCharactersInLine: (tokenizedLine, lineNode) ->
|
||||
{editor} = @props
|
||||
|
||||
+4
-24
@@ -67,6 +67,7 @@ class Package
|
||||
@loadKeymaps()
|
||||
@loadMenus()
|
||||
@loadStylesheets()
|
||||
@grammarsPromise = @loadGrammars()
|
||||
@scopedPropertiesPromise = @loadScopedProperties()
|
||||
@requireMainModule() unless @hasActivationEvents()
|
||||
|
||||
@@ -82,8 +83,6 @@ class Package
|
||||
@scopedProperties = []
|
||||
|
||||
activate: ->
|
||||
@grammarsPromise ?= @loadGrammars()
|
||||
|
||||
unless @activationDeferred?
|
||||
@activationDeferred = Q.defer()
|
||||
@measure 'activateTime', =>
|
||||
@@ -129,9 +128,8 @@ class Package
|
||||
atom.contextMenu.add(menuPath, map['context-menu']) for [menuPath, map] in @menus
|
||||
atom.menu.add(map.menu) for [menuPath, map] in @menus when map.menu
|
||||
|
||||
unless @grammarsActivated
|
||||
grammar.activate() for grammar in @grammars
|
||||
@grammarsActivated = true
|
||||
grammar.activate() for grammar in @grammars
|
||||
@grammarsActivated = true
|
||||
|
||||
scopedProperties.activate() for scopedProperties in @scopedProperties
|
||||
@scopedPropertiesActivated = true
|
||||
@@ -175,32 +173,14 @@ class Package
|
||||
else
|
||||
fs.listSync(stylesheetDirPath, ['css', 'less'])
|
||||
|
||||
loadGrammarsSync: ->
|
||||
return if @grammarsLoaded
|
||||
|
||||
grammarsDirPath = path.join(@path, 'grammars')
|
||||
grammarPaths = fs.listSync(grammarsDirPath, ['json', 'cson'])
|
||||
for grammarPath in grammarPaths
|
||||
try
|
||||
grammar = atom.syntax.readGrammarSync(grammarPath)
|
||||
grammar.packageName = @name
|
||||
@grammars.push(grammar)
|
||||
grammar.activate()
|
||||
catch error
|
||||
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
|
||||
|
||||
@grammarsLoaded = true
|
||||
@grammarsActivated = true
|
||||
|
||||
loadGrammars: ->
|
||||
return Q() if @grammarsLoaded
|
||||
@grammars = []
|
||||
|
||||
loadGrammar = (grammarPath, callback) =>
|
||||
atom.syntax.readGrammar grammarPath, (error, grammar) =>
|
||||
if error?
|
||||
console.warn("Failed to load grammar: #{grammarPath}", error.stack ? error)
|
||||
else
|
||||
grammar.packageName = @name
|
||||
@grammars.push(grammar)
|
||||
grammar.activate() if @grammarsActivated
|
||||
callback()
|
||||
|
||||
@@ -239,9 +239,6 @@ class Project extends Model
|
||||
task.on 'scan:result-found', (result) =>
|
||||
iterator(result) unless @isPathModified(result.filePath)
|
||||
|
||||
task.on 'scan:file-error', (error) ->
|
||||
iterator(null, error)
|
||||
|
||||
if _.isFunction(options.onPathsSearched)
|
||||
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
|
||||
options.onPathsSearched(numberOfPathsSearched)
|
||||
@@ -286,7 +283,6 @@ class Project extends Model
|
||||
checkFinished()
|
||||
|
||||
task.on 'replace:path-replaced', iterator
|
||||
task.on 'replace:file-error', (error) -> iterator(null, error)
|
||||
|
||||
for buffer in @getBuffers()
|
||||
continue unless buffer.getPath() in filePaths
|
||||
|
||||
@@ -202,6 +202,4 @@ class ReactEditorView extends View
|
||||
|
||||
updateDisplay: -> # No-op shim for package specs
|
||||
|
||||
resetDisplay: -> # No-op shim for package specs
|
||||
|
||||
redraw: -> # No-op shim
|
||||
|
||||
@@ -6,10 +6,8 @@ module.exports = (filePaths, regexSource, regexFlags, replacementText) ->
|
||||
replacer = new PathReplacer()
|
||||
regex = new RegExp(regexSource, regexFlags)
|
||||
|
||||
replacer.on 'file-error', ({code, path, message}) ->
|
||||
emit('replace:file-error', {code, path, message})
|
||||
|
||||
replacer.on 'path-replaced', (result) ->
|
||||
emit('replace:path-replaced', result)
|
||||
|
||||
replacer.replacePaths(regex, replacementText, filePaths, -> callback())
|
||||
replacer.replacePaths regex, replacementText, filePaths, ->
|
||||
callback()
|
||||
|
||||
@@ -9,9 +9,6 @@ module.exports = (rootPath, regexSource, options) ->
|
||||
searcher = new PathSearcher()
|
||||
scanner = new PathScanner(rootPath, options)
|
||||
|
||||
searcher.on 'file-error', ({code, path, message}) ->
|
||||
emit('scan:file-error', {code, path, message})
|
||||
|
||||
searcher.on 'results-found', (result) ->
|
||||
emit('scan:result-found', result)
|
||||
|
||||
|
||||
@@ -315,7 +315,6 @@ class Selection extends Model
|
||||
wasReversed = @isReversed()
|
||||
@clear()
|
||||
@cursor.needsAutoscroll = @cursor.isLastCursor()
|
||||
@cursor.autoscroll() if @editor.manageScrollPosition and @cursor.isLastCursor()
|
||||
|
||||
if options.indentBasis? and not options.autoIndent
|
||||
text = @normalizeIndents(text, options.indentBasis)
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@ _ = require 'underscore-plus'
|
||||
textUtils = require './text-utils'
|
||||
|
||||
WhitespaceRegexesByTabLength = {}
|
||||
LeadingSpaceRegex = /^[ ]+/
|
||||
TrailingSpaceRegex = /[ ]+$/
|
||||
LeadingWhitespaceRegex = /^[ ]+/
|
||||
TrailingWhitespaceRegex = /[ ]+$/
|
||||
EscapeRegex = /[&"'<>]/g
|
||||
CharacterRegex = /./g
|
||||
StartCharacterRegex = /^./
|
||||
@@ -151,7 +151,7 @@ class Token
|
||||
leadingHtml = ''
|
||||
trailingHtml = ''
|
||||
|
||||
if @hasLeadingWhitespace and match = LeadingSpaceRegex.exec(@value)
|
||||
if @hasLeadingWhitespace and match = LeadingWhitespaceRegex.exec(@value)
|
||||
classes = 'leading-whitespace'
|
||||
classes += ' indent-guide' if hasIndentGuide
|
||||
classes += ' invisible-character' if invisibles.space
|
||||
@@ -161,7 +161,7 @@ class Token
|
||||
|
||||
startIndex = match[0].length
|
||||
|
||||
if @hasTrailingWhitespace and match = TrailingSpaceRegex.exec(@value)
|
||||
if @hasTrailingWhitespace and match = TrailingWhitespaceRegex.exec(@value)
|
||||
tokenIsOnlyWhitespace = match[0].length is @value.length
|
||||
classes = 'trailing-whitespace'
|
||||
classes += ' indent-guide' if hasIndentGuide and not @hasLeadingWhitespace and tokenIsOnlyWhitespace
|
||||
|
||||
@@ -161,26 +161,13 @@ class TokenizedBuffer extends Model
|
||||
previousEndStack = @stackForRow(end) # used in spill detection below
|
||||
newTokenizedLines = @buildTokenizedLinesForRows(start, end + delta, @stackForRow(start - 1))
|
||||
_.spliceWithArray(@tokenizedLines, start, end - start + 1, newTokenizedLines)
|
||||
|
||||
start = @retokenizeWhitespaceRowsIfIndentLevelChanged(start - 1, -1)
|
||||
end = @retokenizeWhitespaceRowsIfIndentLevelChanged(newRange.end.row + 1, 1) - delta
|
||||
|
||||
newEndStack = @stackForRow(end + delta)
|
||||
|
||||
if newEndStack and not _.isEqual(newEndStack, previousEndStack)
|
||||
@invalidateRow(end + delta + 1)
|
||||
|
||||
@emit "changed", { start, end, delta, bufferChange: e }
|
||||
|
||||
retokenizeWhitespaceRowsIfIndentLevelChanged: (row, increment) ->
|
||||
line = @tokenizedLines[row]
|
||||
if line?.isOnlyWhitespace() and @indentLevelForRow(row) isnt line.indentLevel
|
||||
while line?.isOnlyWhitespace()
|
||||
@tokenizedLines[row] = @buildTokenizedTokenizedLineForRow(row, @stackForRow(row - 1))
|
||||
row += increment
|
||||
line = @tokenizedLines[row]
|
||||
|
||||
row - increment
|
||||
|
||||
buildTokenizedLinesForRows: (startRow, endRow, startingStack) ->
|
||||
ruleStack = startingStack
|
||||
stopTokenizingAt = startRow + @chunkSize
|
||||
|
||||
@@ -152,14 +152,6 @@ class TokenizedLine
|
||||
break
|
||||
false
|
||||
|
||||
isOnlyWhitespace: ->
|
||||
if @text == ''
|
||||
true
|
||||
else
|
||||
for token in @tokens
|
||||
return false unless token.isOnlyWhitespace()
|
||||
true
|
||||
|
||||
tokenAtIndex: (index) ->
|
||||
@tokens[index]
|
||||
|
||||
|
||||
@@ -46,9 +46,6 @@ class Workspace extends Model
|
||||
|
||||
# Called by the Serializable mixin during deserialization
|
||||
deserializeParams: (params) ->
|
||||
for packageName in params.packagesWithActiveGrammars ? []
|
||||
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
|
||||
|
||||
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
|
||||
params
|
||||
|
||||
@@ -56,21 +53,6 @@ class Workspace extends Model
|
||||
serializeParams: ->
|
||||
paneContainer: @paneContainer.serialize()
|
||||
fullScreen: atom.isFullScreen()
|
||||
packagesWithActiveGrammars: @getPackageNamesWithActiveGrammars()
|
||||
|
||||
getPackageNamesWithActiveGrammars: ->
|
||||
packageNames = []
|
||||
addGrammar = ({includedGrammarScopes, packageName}={}) ->
|
||||
return unless packageName
|
||||
# Prevent cycles
|
||||
return if packageNames.indexOf(packageName) isnt -1
|
||||
|
||||
packageNames.push(packageName)
|
||||
for scopeName in includedGrammarScopes ? []
|
||||
addGrammar(atom.syntax.grammarForScopeName(scopeName))
|
||||
|
||||
addGrammar(editor.getGrammar()) for editor in @getEditors()
|
||||
_.uniq(packageNames)
|
||||
|
||||
editorAdded: (editor) ->
|
||||
@emit 'editor-created', editor
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário