Comparar commits
173 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 57a0febbef | |||
| b274955539 | |||
| a9f72ed535 | |||
| 4991df24df | |||
| baf2de8f26 | |||
| ce97372cfb | |||
| 710b1033fe | |||
| f4082d5ae6 | |||
| 0c12d9f5de | |||
| eabca9422d | |||
| 2728ae9fa6 | |||
| bf90940a83 | |||
| 20d06d0a09 | |||
| 753e295660 | |||
| ebc579af6f | |||
| 1d9d31ffd3 | |||
| f9d146c6d4 | |||
| ae576a9202 | |||
| 25556e1d08 | |||
| c95b638b57 | |||
| 223afada7f | |||
| 9b04b82dc1 | |||
| ef24886243 | |||
| 25922872f0 | |||
| 15a1982e8c | |||
| fcca61c2b2 | |||
| ee4116536d | |||
| c217c6544a | |||
| 205095a198 | |||
| 4326898d5f | |||
| b8285a00b0 | |||
| 025967193a | |||
| 75627f50a2 | |||
| 9fca1d26f1 | |||
| 6e827434fd | |||
| b3f6b3af4b | |||
| 63a33bd1e7 | |||
| a153f1e244 | |||
| 037a7f435c | |||
| 7641f1d1e4 | |||
| 05c1ae71e1 | |||
| cefabd4eb8 | |||
| 9f80be4570 | |||
| 61f75b0764 | |||
| ae2f4ac36e | |||
| d20e91897a | |||
| 2e0bb66a9a | |||
| d205c4d664 | |||
| 8db5ea7bc7 | |||
| 3c7eecbb6a | |||
| 8dab3d90b3 | |||
| 44bc470a00 | |||
| 498631725a | |||
| 945345b0c7 | |||
| 6576ec5cde | |||
| ce8143f8e6 | |||
| e993175205 | |||
| 4242ac0911 | |||
| f22e741a9b | |||
| a41b582032 | |||
| a24279d0b9 | |||
| 5985175b07 | |||
| d2ef888f22 | |||
| 35925ed349 | |||
| 490ec1aac7 | |||
| 25eea7d19b | |||
| 4c9e71770a | |||
| 4032d96b13 | |||
| c5aa3eb441 | |||
| 68bb765304 | |||
| bd7996e071 | |||
| 1eaba0cb52 | |||
| 0c590d6170 | |||
| 3df72ec173 | |||
| 1456bf0d91 | |||
| edec6b9b0a | |||
| 9abc4580f4 | |||
| 54260230c6 | |||
| 9bd11fc2f7 | |||
| 81586d22f4 | |||
| dc824485aa | |||
| d1fcfabf0b | |||
| ea8a3a78da | |||
| 62f5d0f7f3 | |||
| b3f4d03a82 | |||
| c2d51858b1 | |||
| a5bca03a46 | |||
| 02d20e3155 | |||
| 2910e017bb | |||
| 248e164de2 | |||
| 4d796f614c | |||
| a8be05bb3b | |||
| 101904e261 | |||
| c0622e8bb5 | |||
| ce5b755438 | |||
| 86781e6f9a | |||
| a7f4a5b08e | |||
| 2b8167da53 | |||
| bb0ee8a78b | |||
| d1115d4c7c | |||
| a71d7115bf | |||
| af14a26625 | |||
| dadd56f7a0 | |||
| 0e99b70650 | |||
| 2965398062 | |||
| 55ace0fe99 | |||
| 03f7511229 | |||
| 5f7976cada | |||
| fa074431f9 | |||
| b9239ffc57 | |||
| 06698c880f | |||
| 05dc9aad89 | |||
| e5660e5e83 | |||
| e928447eab | |||
| 9b0f622ffb | |||
| b6cc7273a1 | |||
| 232be1f876 | |||
| ddeec5d4d5 | |||
| dc83f8bac7 | |||
| ae2a7769ed | |||
| d0d6af7e55 | |||
| 137df72a60 | |||
| 2e187d3ec1 | |||
| 9f74250333 | |||
| de70a181c5 | |||
| 0272b2f281 | |||
| 365b7bfaf9 | |||
| 937ef321bd | |||
| 80a302df9e | |||
| 381ee353a3 | |||
| de3703d1ea | |||
| 0b8c4a0c7f | |||
| d299692237 | |||
| eaf435bd9a | |||
| 8d71cbd510 | |||
| 534ace6250 | |||
| 89157cdf29 | |||
| ef2795ea0d | |||
| 11b5bcff74 | |||
| d7019509e3 | |||
| 0417458fbb | |||
| ff32fff483 | |||
| f776678b83 | |||
| edacf02222 | |||
| 4b3d3701d5 | |||
| dcbd1723b7 | |||
| 6c00dbd5ec | |||
| 14fd4a9f7d | |||
| b65c6da948 | |||
| 1c1adf5beb | |||
| c1197d6390 | |||
| 7713720ba7 | |||
| 4f1ec786f0 | |||
| 27ff02ad0e | |||
| 738cdb6e66 | |||
| 0818e6d736 | |||
| 6b57030bda | |||
| b64a5c93e3 | |||
| 317001b435 | |||
| 4e3d15592e | |||
| f4c40c2932 | |||
| 9cfc451a79 | |||
| 198d3e90c7 | |||
| 00da8a9df6 | |||
| 293bd3ad3d | |||
| bd0564e30d | |||
| 953940c757 | |||
| 4ff6366d2b | |||
| 4db441f4df | |||
| 71ef21bb70 | |||
| de5e443329 | |||
| 6e15d68163 | |||
| 6a3c7bcd50 |
+8
-13
@@ -25,6 +25,8 @@ propose changes to this document in a pull request.
|
||||
full stack trace and include it in the issue.
|
||||
* On Mac, check Console.app for stack traces to include if reporting a crash.
|
||||
* Perform a cursory search to see if a similar issue has already been submitted.
|
||||
* Please setup a [profile picture](https://help.github.com/articles/how-do-i-set-up-my-profile-picture)
|
||||
to make yourself recognizable and so we can all get to know each other better.
|
||||
|
||||
### Package Repositories
|
||||
|
||||
@@ -99,30 +101,23 @@ For more information on how to work with Atom's official packages, see
|
||||
|
||||
## Documentation Styleguide
|
||||
|
||||
* Use [TomDoc](http://tomdoc.org).
|
||||
* Use [AtomDoc](https://github.com/atom/atomdoc).
|
||||
* Use [Markdown](https://daringfireball.net/projects/markdown).
|
||||
* Reference methods and classes in markdown with the custom `{}` notation:
|
||||
* Reference classes with `{ClassName}`
|
||||
* Reference instance methods with `{ClassName::methodName}`
|
||||
* Reference class methods with `{ClassName.methodName}`
|
||||
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
|
||||
style notation.
|
||||
|
||||
### Example
|
||||
|
||||
```coffee
|
||||
# Public: Disable the package with the given name.
|
||||
#
|
||||
# This method emits multiple events:
|
||||
#
|
||||
# * `package-will-be-disabled` - before the package is disabled.
|
||||
# * `package-disabled` - after the package is disabled.
|
||||
#
|
||||
# name - The {String} name of the package to disable.
|
||||
# options - The {Object} with disable options (default: {}):
|
||||
# :trackTime - `true` to track the amount of time disabling took.
|
||||
# :ignoreErrors - `true` to catch and ignore errors thrown.
|
||||
# callback - The {Function} to call after the package has been disabled.
|
||||
# * `name` The {String} name of the package to disable.
|
||||
# * `options` (optional) The {Object} with disable options (default: {}):
|
||||
# * `trackTime` A {Boolean}, `true` to track the amount of time taken.
|
||||
# * `ignoreErrors` A {Boolean}, `true` to catch and ignore errors thrown.
|
||||
# * `callback` The {Function} to call after the package has been disabled.
|
||||
#
|
||||
# Returns `undefined`.
|
||||
disablePackage: (name, options, callback) ->
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# VERSION: 0.1
|
||||
# DESCRIPTION: Image to build Atom and create a .rpm file
|
||||
|
||||
# Base docker image
|
||||
FROM fedora:20
|
||||
|
||||
# Install dependencies
|
||||
RUN yum install -y \
|
||||
make \
|
||||
gcc \
|
||||
gcc-c++ \
|
||||
glibc-devel \
|
||||
git-core \
|
||||
libgnome-keyring-devel \
|
||||
rpmdevtools
|
||||
|
||||
# Install node
|
||||
RUN curl -sL https://rpm.nodesource.com/setup | bash -
|
||||
RUN yum install -y nodejs
|
||||
|
||||
ADD . /atom
|
||||
WORKDIR /atom
|
||||
+14
@@ -4,6 +4,9 @@ Atom is a hackable text editor for the 21st century, built on [atom-shell](http:
|
||||
|
||||
Visit [atom.io](https://atom.io) to learn more.
|
||||
|
||||
Visit [issue #3684](https://github.com/atom/atom/issues/3684) to learn more
|
||||
about the Atom 1.0 roadmap.
|
||||
|
||||
## Installing
|
||||
|
||||
### Mac OS X
|
||||
@@ -36,6 +39,17 @@ Currently only a 64-bit version is available.
|
||||
The Linux version does not currently automatically update so you will need to
|
||||
repeat these steps to upgrade to future releases.
|
||||
|
||||
### Red Hat Linux (Fedora, CentOS, Red Hat)
|
||||
|
||||
Currently only a 64-bit version is available.
|
||||
|
||||
1. Download `atom.x86_64.rpm` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
|
||||
2. Run `sudo yum localinstall atom.x86_64.rpm` on the downloaded package.
|
||||
3. Launch Atom using the installed `atom` command.
|
||||
|
||||
The Linux version does not currently automatically update so you will need to
|
||||
repeat these steps to upgrade to future releases.
|
||||
|
||||
## Building
|
||||
|
||||
* [Linux](docs/build-instructions/linux.md)
|
||||
|
||||
+1
-1
@@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "0.106.0"
|
||||
"atom-package-manager": "0.109.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ describe "editorView.", ->
|
||||
|
||||
beforeEach ->
|
||||
atom.workspaceViewParentSelector = '#jasmine-content'
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
atom.workspaceView.width(1024)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
# VERSION: 0.1
|
||||
# DESCRIPTION: Create the atom editor in a container
|
||||
# AUTHOR: Jessica Frazelle <jessie@docker.com>
|
||||
# COMMENTS:
|
||||
# This file describes how to build the atom editor
|
||||
# in a container with all dependencies installed.
|
||||
# Tested on Debian Jessie.
|
||||
# USAGE:
|
||||
# # Download atom Dockerfile
|
||||
# wget http://raw.githubusercontent.com/atom/atom/master/Dockerfile
|
||||
#
|
||||
# # Build atom image
|
||||
# docker build -t atom .
|
||||
#
|
||||
# docker run -v /tmp/.X11-unix:/tmp/.X11-unix \
|
||||
# -e DISPLAY=unix$DISPLAY atom
|
||||
#
|
||||
|
||||
DOCKER-VERSION 1.3
|
||||
|
||||
# Base docker image
|
||||
FROM debian:jessie
|
||||
MAINTAINER Jessica Frazelle <jessie@docker.com>
|
||||
|
||||
# Install dependencies
|
||||
RUN apt-get update && apt-get install -y \
|
||||
build-essential \
|
||||
ca-certificates \
|
||||
curl \
|
||||
git \
|
||||
libasound2 \
|
||||
libgconf-2-4 \
|
||||
libgnome-keyring-dev \
|
||||
libgtk2.0-0 \
|
||||
libnss3 \
|
||||
libxtst6 \
|
||||
--no-install-recommends
|
||||
|
||||
# install node
|
||||
RUN curl -sL https://deb.nodesource.com/setup | bash -
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# clone atom
|
||||
RUN git clone https://github.com/atom/atom /src
|
||||
WORKDIR /src
|
||||
RUN git fetch && git checkout $(git describe --tags `git rev-list --tags --max-count=1`)
|
||||
RUN script/build && script/grunt install
|
||||
|
||||
# Autorun atom
|
||||
CMD /usr/local/bin/atom --foreground --log-file /var/log/atom.log && tail -f /var/log/atom.log
|
||||
@@ -60,3 +60,18 @@ module.exports =
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
||||
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
"""
|
||||
|
||||
'jschardet@1.1.0':
|
||||
license: 'LGPL'
|
||||
source: 'README.md in the repository'
|
||||
sourceText: """
|
||||
JsChardet
|
||||
=========
|
||||
|
||||
Port of python's chardet (http://chardet.feedparser.org/).
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
LGPL
|
||||
"""
|
||||
|
||||
@@ -3,7 +3,7 @@ path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{spawn} = require('./task-helpers')(grunt)
|
||||
{spawn, rm, mkdir} = require('./task-helpers')(grunt)
|
||||
|
||||
fillTemplate = (filePath, data) ->
|
||||
template = _.template(String(fs.readFileSync("#{filePath}.in")))
|
||||
@@ -25,6 +25,11 @@ module.exports = (grunt) ->
|
||||
|
||||
{name, version, description} = grunt.file.readJSON('package.json')
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
|
||||
rpmDir = path.join(buildDir, 'rpm')
|
||||
rm rpmDir
|
||||
mkdir rpmDir
|
||||
|
||||
installDir = grunt.config.get('atom.installDir')
|
||||
shareDir = path.join(installDir, 'share', 'atom')
|
||||
iconName = path.join(shareDir, 'resources', 'app', 'resources', 'atom.png')
|
||||
@@ -39,5 +44,5 @@ module.exports = (grunt) ->
|
||||
if error?
|
||||
done(error)
|
||||
else
|
||||
grunt.log.ok "Created rpm package in #{buildDir}"
|
||||
grunt.log.ok "Created rpm package in #{rpmDir}"
|
||||
done()
|
||||
|
||||
@@ -38,6 +38,9 @@ module.exports = (gruntObject) ->
|
||||
grunt.log.ok("Upload time: #{elapsedTime}s")
|
||||
doneCallback(args...)
|
||||
|
||||
unless token
|
||||
return done(new Error('ATOM_ACCESS_TOKEN environment variable not set'))
|
||||
|
||||
buildDir = grunt.config.get('atom.buildDir')
|
||||
assets = getAssets()
|
||||
|
||||
@@ -69,9 +72,21 @@ getAssets = ->
|
||||
else
|
||||
arch = 'amd64'
|
||||
{version} = grunt.file.readJSON('package.json')
|
||||
|
||||
# Check for a Debian build
|
||||
sourcePath = "#{buildDir}/atom-#{version}-#{arch}.deb"
|
||||
assetName = "atom-#{arch}.deb"
|
||||
|
||||
# Check for a Fedora build
|
||||
unless fs.isFileSync(sourcePath)
|
||||
rpmName = fs.readdirSync("#{buildDir}/rpm")[0]
|
||||
sourcePath = "#{buildDir}/rpm/#{rpmName}"
|
||||
if process.arch is 'ia32'
|
||||
arch = 'i386'
|
||||
else
|
||||
arch = 'x86_64'
|
||||
assetName = "atom.#{arch}.rpm"
|
||||
|
||||
{cp} = require('./task-helpers')(grunt)
|
||||
cp sourcePath, path.join(buildDir, assetName)
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@ Ubuntu LTS 12.04 64-bit is the recommended platform.
|
||||
* `sudo apt-get install build-essential git libgnome-keyring-dev fakeroot`
|
||||
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#ubuntu-mint-elementary-os).
|
||||
|
||||
### Fedora
|
||||
### Fedora / CentOS / RHEL
|
||||
|
||||
* `sudo yum --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel`
|
||||
* `sudo yum --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools`
|
||||
* Instructions for [Node.js](https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager#fedora).
|
||||
|
||||
### Arch
|
||||
|
||||
* `sudo pacman -S base-devel git nodejs libgnome-keyring`
|
||||
* `sudo pacman -S base-devel git nodejs libgnome-keyring python2`
|
||||
* `export PYTHON=/usr/bin/python2` before building Atom.
|
||||
|
||||
## Instructions
|
||||
@@ -61,13 +61,19 @@ If you have problems with permissions don't forget to prefix with `sudo`
|
||||
sudo script/grunt install
|
||||
```
|
||||
|
||||
5. *Optionally*, you may generate a `.deb` package at `$TMPDIR/atom-build`:
|
||||
To use the newly installed Atom, quit and restart all running Atom instances.
|
||||
|
||||
5. *Optionally*, you may generate distributable packages of Atom at `$TMPDIR/atom-build`. Currenty, `.deb` and `.rpm` package types are supported. To create a `.deb` package run:
|
||||
|
||||
```sh
|
||||
script/grunt mkdeb
|
||||
```
|
||||
|
||||
Use the newly installed Atom by fully quitting Atom and then reopening.
|
||||
To create an `.rpm` package run
|
||||
|
||||
```sh
|
||||
script/grunt mkrpm
|
||||
```
|
||||
|
||||
## Advanced Options
|
||||
|
||||
@@ -85,7 +91,7 @@ script/build --build-dir /build/atom/here
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Exception: "TypeError: Unable to watch path"
|
||||
### TypeError: Unable to watch path
|
||||
|
||||
If you get following error with a big traceback right after Atom starts:
|
||||
|
||||
@@ -115,6 +121,22 @@ have Node.js installed, or node isn't identified as Node.js 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.
|
||||
|
||||
### AttributeError: 'module' object has no attribute 'script_main'
|
||||
|
||||
If you get following error with a big traceback while building Atom:
|
||||
|
||||
```
|
||||
sys.exit(gyp.script_main()) AttributeError: 'module' object has no attribute 'script_main' gyp ERR!
|
||||
```
|
||||
|
||||
you need to uninstall the system version of gyp.
|
||||
|
||||
On Fedora you would do the following:
|
||||
|
||||
```sh
|
||||
sudo yum remove gyp
|
||||
```
|
||||
|
||||
#### You can also use Alternatives
|
||||
|
||||
On some variants (mostly Debian based distros) it's preferable for you to use
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
## Why do I have to use GitHub for Windows?
|
||||
|
||||
You don't. You can use your existing Git! GitHub for Windows's Git Shell is just
|
||||
easier to set up.
|
||||
easier to set up.
|
||||
|
||||
If you _prefer_ using your existing Git installation, make sure git's cmd directory is in your PATH env variable (e.g. `C:\Program Files (x86)\Git\cmd`) before you open your powershell or command window.
|
||||
Note that you may have to open your command window as administrator. For powershell that doesn't seem to always be the case, though.
|
||||
@@ -67,11 +67,11 @@ If none of this works, do install Github for Windows and use its Git shell. Make
|
||||
* https://code.google.com/p/gyp/issues/detail?id=393
|
||||
|
||||
* `script/build` stops at installing runas with 'Failed at the runas@0.5.4 install script.'
|
||||
|
||||
|
||||
See the next item.
|
||||
|
||||
* `error MSB8020: The build tools for Visual Studio 2010 (Platform Toolset = 'v100') cannot be found.`
|
||||
|
||||
|
||||
* If you're building atom with Visual Studio 2013 try executing the following
|
||||
command in your Git shell and then re-run `script/build`:
|
||||
|
||||
|
||||
+35
-4
@@ -1,4 +1,5 @@
|
||||
{Point, Range} = require 'text-buffer'
|
||||
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
module.exports =
|
||||
@@ -13,19 +14,49 @@ module.exports =
|
||||
unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
{$, $$, $$$, View} = require '../src/space-pen-extensions'
|
||||
|
||||
module.exports.Emitter = Emitter
|
||||
module.exports.Disposable = Disposable
|
||||
module.exports.CompositeDisposable = CompositeDisposable
|
||||
|
||||
module.exports.$ = $
|
||||
module.exports.$$ = $$
|
||||
module.exports.$$$ = $$$
|
||||
module.exports.TextEditorView = require '../src/text-editor-view'
|
||||
module.exports.ScrollView = require '../src/scroll-view'
|
||||
module.exports.SelectListView = require '../src/select-list-view'
|
||||
module.exports.Task = require '../src/task'
|
||||
module.exports.View = View
|
||||
module.exports.TextEditorElement = require '../src/text-editor-element'
|
||||
|
||||
module.exports.Task = require '../src/task'
|
||||
module.exports.WorkspaceView = require '../src/workspace-view'
|
||||
module.exports.Workspace = require '../src/workspace'
|
||||
module.exports.React = require 'react-atom-fork'
|
||||
module.exports.Reactionary = require 'reactionary-atom-fork'
|
||||
|
||||
# Export deprecated SpacePen views.
|
||||
# Adjust their prototype chain to inherit from our extend version of SpacePen
|
||||
#
|
||||
# We avoid using/assigning a cached module for these classes in order to
|
||||
# prevent polluting every required version with these changes. The only
|
||||
# versions that should get their prototypes adjusted are the ones exported
|
||||
# here.
|
||||
uncachedRequire = (id) ->
|
||||
modulePath = require.resolve(id)
|
||||
delete require.cache[modulePath]
|
||||
loadedModule = require(modulePath)
|
||||
delete require.cache[modulePath]
|
||||
loadedModule
|
||||
|
||||
TextEditorView = uncachedRequire 'atom-space-pen-views/lib/text-editor-view'
|
||||
ScrollView = uncachedRequire 'atom-space-pen-views/lib/scroll-view'
|
||||
SelectListView = uncachedRequire 'atom-space-pen-views/lib/select-list-view'
|
||||
|
||||
# Make Atom's modified SpacePen View prototype the prototype of the imported View
|
||||
TextEditorView.prototype.__proto__.__proto__ = View.prototype
|
||||
TextEditorView.prototype.__proto__.useLegacyAttachHooks = true
|
||||
|
||||
module.exports.TextEditorView = TextEditorView
|
||||
module.exports.ScrollView = ScrollView
|
||||
module.exports.SelectListView = SelectListView
|
||||
|
||||
|
||||
Object.defineProperty module.exports, 'Git', get: ->
|
||||
deprecate "Please require `GitRepository` instead of `Git`: `{GitRepository} = require 'atom'`"
|
||||
module.exports.GitRepository
|
||||
|
||||
@@ -190,6 +190,12 @@
|
||||
submenu: [
|
||||
{ label: 'Terms of Use', command: 'application:open-terms-of-use' }
|
||||
{ label: 'Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -147,6 +147,12 @@
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
@@ -165,6 +165,12 @@
|
||||
{ label: "VERSION", enabled: false }
|
||||
{ type: 'separator' }
|
||||
{ label: '&Documentation', command: 'application:open-documentation' }
|
||||
{ label: 'Roadmap', command: 'application:open-roadmap' }
|
||||
{ label: 'Frequently Asked Questions', command: 'application:open-faq' }
|
||||
{ type: 'separator' }
|
||||
{ label: 'Community Discussions', command: 'application:open-discussions' }
|
||||
{ label: 'Report Issue', command: 'application:report-issue' }
|
||||
{ label: 'Search Issues', command: 'application:search-issues' }
|
||||
{ type: 'separator' }
|
||||
]
|
||||
}
|
||||
|
||||
+27
-26
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.139.0",
|
||||
"version": "0.142.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -21,6 +21,7 @@
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.2.1",
|
||||
"atom-space-pen-views": "^0.11.0",
|
||||
"bootstrap": "git+https://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||
"clear-cut": "0.4.0",
|
||||
"coffee-script": "1.7.0",
|
||||
@@ -43,30 +44,30 @@
|
||||
"nslog": "^1.0.1",
|
||||
"oniguruma": "^3.0.4",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "^2.1.3",
|
||||
"pathwatcher": "^2.3.2",
|
||||
"property-accessors": "^1",
|
||||
"q": "^1.0.1",
|
||||
"random-words": "0.0.1",
|
||||
"react-atom-fork": "^0.11.1",
|
||||
"reactionary-atom-fork": "^1.0.0",
|
||||
"runas": "1.0.1",
|
||||
"scandal": "1.0.2",
|
||||
"scoped-property-store": "^0.14.0",
|
||||
"scandal": "1.0.3",
|
||||
"scoped-property-store": "^0.15.0",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^1.0.2",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.8.0",
|
||||
"space-pen": "^3.8.1",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.2.9",
|
||||
"text-buffer": "^3.4",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.6.1",
|
||||
"vm-compatibility-layer": "0.1.0"
|
||||
},
|
||||
"packageDependencies": {
|
||||
"atom-dark-syntax": "0.19.0",
|
||||
"atom-dark-syntax": "0.20.0",
|
||||
"atom-dark-ui": "0.35.0",
|
||||
"atom-light-syntax": "0.20.0",
|
||||
"atom-light-syntax": "0.21.0",
|
||||
"atom-light-ui": "0.30.0",
|
||||
"base16-tomorrow-dark-theme": "0.21.0",
|
||||
"base16-tomorrow-light-theme": "0.4.0",
|
||||
@@ -78,29 +79,29 @@
|
||||
"autosave": "0.18.0",
|
||||
"background-tips": "0.17.0",
|
||||
"bookmarks": "0.28.0",
|
||||
"bracket-matcher": "0.61.0",
|
||||
"bracket-matcher": "0.62.0",
|
||||
"command-palette": "0.27.0",
|
||||
"deprecation-cop": "0.11.0",
|
||||
"dev-live-reload": "0.34.0",
|
||||
"dev-live-reload": "0.35.0",
|
||||
"encoding-selector": "0.5.0",
|
||||
"exception-reporting": "0.20.0",
|
||||
"feedback": "0.33.0",
|
||||
"find-and-replace": "0.140.0",
|
||||
"fuzzy-finder": "0.58.0",
|
||||
"git-diff": "0.40.0",
|
||||
"go-to-line": "0.25.0",
|
||||
"grammar-selector": "0.35.0",
|
||||
"image-view": "0.37.0",
|
||||
"find-and-replace": "0.141.0",
|
||||
"fuzzy-finder": "0.60.0",
|
||||
"git-diff": "0.42.0",
|
||||
"go-to-line": "0.26.0",
|
||||
"grammar-selector": "0.37.0",
|
||||
"image-view": "0.40.0",
|
||||
"incompatible-packages": "0.10.0",
|
||||
"keybinding-resolver": "0.20.0",
|
||||
"link": "0.26.0",
|
||||
"markdown-preview": "0.105.0",
|
||||
"markdown-preview": "0.107.0",
|
||||
"metrics": "0.36.0",
|
||||
"open-on-github": "0.30.0",
|
||||
"package-generator": "0.31.0",
|
||||
"release-notes": "0.36.0",
|
||||
"settings-view": "0.153.0",
|
||||
"settings-view": "0.154.0",
|
||||
"snippets": "0.56.0",
|
||||
"spell-check": "0.42.0",
|
||||
"spell-check": "0.43.0",
|
||||
"status-bar": "0.46.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.66.0",
|
||||
@@ -109,10 +110,10 @@
|
||||
"tree-view": "0.131.0",
|
||||
"update-package-dependencies": "0.6.0",
|
||||
"welcome": "0.19.0",
|
||||
"whitespace": "0.25.0",
|
||||
"whitespace": "0.26.0",
|
||||
"wrap-guide": "0.23.0",
|
||||
"language-c": "0.29.0",
|
||||
"language-coffee-script": "0.36.0",
|
||||
"language-coffee-script": "0.37.0",
|
||||
"language-css": "0.21.0",
|
||||
"language-gfm": "0.53.0",
|
||||
"language-git": "0.9.0",
|
||||
@@ -122,17 +123,17 @@
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.42.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.16.0",
|
||||
"language-less": "0.18.0",
|
||||
"language-make": "0.12.0",
|
||||
"language-mustache": "0.10.0",
|
||||
"language-objective-c": "0.11.0",
|
||||
"language-perl": "0.9.0",
|
||||
"language-php": "0.16.0",
|
||||
"language-php": "0.17.0",
|
||||
"language-property-list": "0.7.0",
|
||||
"language-python": "0.21.0",
|
||||
"language-ruby": "0.40.0",
|
||||
"language-ruby": "0.41.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.23.0",
|
||||
"language-sass": "0.24.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
|
||||
Arquivo executável
+10
@@ -0,0 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
docker build -t atom-rpm .
|
||||
docker run \
|
||||
--env JANKY_SHA1="$JANKY_SHA1" \
|
||||
--env JANKY_BRANCH="$JANKY_BRANCH" \
|
||||
--env ATOM_ACCESS_TOKEN="$BUILD_ATOM_RPM_ACCESS_TOKEN" \
|
||||
atom-rpm /atom/script/rpmbuild
|
||||
+1
-1
@@ -17,6 +17,6 @@ cp ./atom.sh $RPM_BUILD_ROOT/BUILD
|
||||
cp $DESKTOP_FILE $RPM_BUILD_ROOT/BUILD
|
||||
|
||||
rpmbuild -ba $SPEC_FILE
|
||||
cp $RPM_BUILD_ROOT/RPMS/$ARCH/atom-*.rpm $BUILD_DIRECTORY
|
||||
cp $RPM_BUILD_ROOT/RPMS/$ARCH/atom-*.rpm $BUILD_DIRECTORY/rpm
|
||||
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
Arquivo executável
+6
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -e
|
||||
|
||||
script/build
|
||||
script/grunt mkrpm publish-build --stack
|
||||
@@ -6,7 +6,7 @@ ThemeManager = require '../src/theme-manager'
|
||||
|
||||
describe "the `atom` global", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
describe 'window sizing methods', ->
|
||||
describe '::getPosition and ::setPosition', ->
|
||||
|
||||
@@ -1075,6 +1075,13 @@ describe "Config", ->
|
||||
atom.config.setDefaults("foo", hasDefault: 'ok')
|
||||
expect(atom.config.get([".source.coffee", ".string.quoted.single"], "foo.hasDefault")).toBe 'ok'
|
||||
|
||||
describe 'setting priority', ->
|
||||
describe 'when package settings are added after user settings', ->
|
||||
it "returns the user's setting because the user's setting has higher priority", ->
|
||||
atom.config.set(".source.coffee", "foo.bar.baz", 100)
|
||||
atom.config.addScopedSettings("some-package", ".source.coffee", foo: bar: baz: 1)
|
||||
expect(atom.config.get([".source.coffee"], "foo.bar.baz")).toBe 100
|
||||
|
||||
describe ".set(scope, keyPath, value)", ->
|
||||
it "sets the value and overrides the others", ->
|
||||
atom.config.addScopedSettings("config", ".source.coffee .string.quoted.double.coffee", foo: bar: baz: 42)
|
||||
|
||||
@@ -56,6 +56,11 @@ describe "DisplayBuffer", ->
|
||||
buffer.delete([[8, 0], [10, 0]])
|
||||
expect(displayBuffer.getScrollTop()).toBe 60
|
||||
|
||||
it "updates the display buffer prior to invoking change handlers registered on the buffer", ->
|
||||
buffer.onDidChange -> expect(displayBuffer2.tokenizedLineForScreenRow(0).text).toBe "testing"
|
||||
displayBuffer2 = new DisplayBuffer({buffer, tabLength})
|
||||
buffer.setText("testing")
|
||||
|
||||
describe "soft wrapping", ->
|
||||
beforeEach ->
|
||||
displayBuffer.setSoftWrapped(true)
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"theme": "syntax",
|
||||
"stylesheets": ["editor.less"]
|
||||
}
|
||||
@@ -3,7 +3,7 @@ Package = require '../src/package'
|
||||
|
||||
describe "PackageManager", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
|
||||
describe "::loadPackage(name)", ->
|
||||
it "continues if the package has an invalid package.json", ->
|
||||
|
||||
@@ -19,7 +19,7 @@ describe "PaneContainerView", ->
|
||||
save: -> @saved = true
|
||||
isEqual: (other) -> @name is other?.name
|
||||
|
||||
container = atom.workspace.getView(atom.workspace.paneContainer).__spacePenView
|
||||
container = atom.views.getView(atom.workspace.paneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane2 = pane1.splitRight(new TestView('2'))
|
||||
@@ -73,7 +73,7 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "serialization", ->
|
||||
it "can be serialized and deserialized, and correctly adjusts dimensions of deserialized panes after attach", ->
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(2)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > :contains(3)')).toExist()
|
||||
@@ -89,14 +89,14 @@ describe "PaneContainerView", ->
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is false (the default)", ->
|
||||
it "leaves the empty panes intact", ->
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > :contains(1)')).toExist()
|
||||
expect(newContainer.find('atom-pane-axis.horizontal > atom-pane-axis.vertical > atom-pane').length).toBe 2
|
||||
|
||||
describe "if the 'core.destroyEmptyPanes' config option is true", ->
|
||||
it "removes empty panes on deserialization", ->
|
||||
atom.config.set('core.destroyEmptyPanes', true)
|
||||
newContainer = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
newContainer = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
expect(newContainer.find('atom-pane-axis.horizontal, atom-pane-axis.vertical')).not.toExist()
|
||||
expect(newContainer.find('> :contains(1)')).toExist()
|
||||
|
||||
@@ -109,7 +109,7 @@ describe "PaneContainerView", ->
|
||||
item2b = new TestView('2b')
|
||||
item3a = new TestView('3a')
|
||||
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(item1a)
|
||||
container.attachToDom()
|
||||
@@ -259,7 +259,7 @@ describe "PaneContainerView", ->
|
||||
# |7|8|9|
|
||||
# -------
|
||||
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
pane1 = container.getRoot()
|
||||
pane1.activateItem(new TestView('1'))
|
||||
pane4 = pane1.splitDown(new TestView('4'))
|
||||
|
||||
@@ -24,7 +24,7 @@ describe "PaneView", ->
|
||||
|
||||
beforeEach ->
|
||||
deserializerDisposable = atom.deserializers.add(TestView)
|
||||
container = atom.workspace.getView(new PaneContainer).__spacePenView
|
||||
container = atom.views.getView(new PaneContainer).__spacePenView
|
||||
containerModel = container.model
|
||||
view1 = new TestView(id: 'view-1', text: 'View 1')
|
||||
view2 = new TestView(id: 'view-2', text: 'View 2')
|
||||
@@ -311,13 +311,13 @@ describe "PaneView", ->
|
||||
container.attachToDom()
|
||||
pane.focus()
|
||||
|
||||
container2 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
container2 = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
pane2 = container2.getRoot()
|
||||
container2.attachToDom()
|
||||
expect(pane2).toMatchSelector(':has(:focus)')
|
||||
|
||||
$(document.activeElement).blur()
|
||||
container3 = atom.workspace.getView(container.model.testSerialization()).__spacePenView
|
||||
container3 = atom.views.getView(container.model.testSerialization()).__spacePenView
|
||||
pane3 = container3.getRoot()
|
||||
container3.attachToDom()
|
||||
expect(pane3).not.toMatchSelector(':has(:focus)')
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
SelectListView = require '../src/select-list-view'
|
||||
{$, $$} = require 'atom'
|
||||
|
||||
describe "SelectListView", ->
|
||||
[selectList, items, list, filterEditorView] = []
|
||||
|
||||
beforeEach ->
|
||||
items = [
|
||||
["A", "Alpha"], ["B", "Bravo"], ["C", "Charlie"],
|
||||
["D", "Delta"], ["E", "Echo"], ["F", "Foxtrot"]
|
||||
]
|
||||
|
||||
selectList = new SelectListView
|
||||
selectList.setMaxItems(4)
|
||||
selectList.getFilterKey = -> 1
|
||||
selectList.viewForItem = (item) ->
|
||||
$$ -> @li item[1], class: item[0]
|
||||
|
||||
selectList.confirmed = jasmine.createSpy('confirmed hook')
|
||||
selectList.cancelled = jasmine.createSpy('cancelled hook')
|
||||
|
||||
selectList.setItems(items)
|
||||
{list, filterEditorView} = selectList
|
||||
|
||||
describe "when an array is assigned", ->
|
||||
it "populates the list with up to maxItems items, based on the liForElement function", ->
|
||||
expect(list.find('li').length).toBe selectList.maxItems
|
||||
expect(list.find('li:eq(0)')).toHaveText 'Alpha'
|
||||
expect(list.find('li:eq(0)')).toHaveClass 'A'
|
||||
|
||||
describe "viewForItem(item)", ->
|
||||
it "allows raw DOM elements to be returned", ->
|
||||
selectList.viewForItem = (item) ->
|
||||
li = document.createElement('li')
|
||||
li.classList.add(item[0])
|
||||
li.innerText = item[1]
|
||||
li
|
||||
|
||||
selectList.setItems(items)
|
||||
|
||||
expect(list.find('li').length).toBe selectList.maxItems
|
||||
expect(list.find('li:eq(0)')).toHaveText 'Alpha'
|
||||
expect(list.find('li:eq(0)')).toHaveClass 'A'
|
||||
expect(selectList.getSelectedItem()).toBe items[0]
|
||||
|
||||
it "allows raw HTML to be returned", ->
|
||||
selectList.viewForItem = (item) ->
|
||||
"<li>#{item}</li>"
|
||||
|
||||
selectList.setItems(['Bermuda', 'Bahama'])
|
||||
|
||||
expect(list.find('li:eq(0)')).toHaveText 'Bermuda'
|
||||
expect(selectList.getSelectedItem()).toBe 'Bermuda'
|
||||
|
||||
describe "when the text of the mini editor changes", ->
|
||||
beforeEach ->
|
||||
selectList.attachToDom()
|
||||
|
||||
it "filters the elements in the list based on the scoreElement function and selects the first item", ->
|
||||
filterEditorView.getEditor().insertText('la')
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li').length).toBe 2
|
||||
expect(list.find('li:contains(Alpha)')).toExist()
|
||||
expect(list.find('li:contains(Delta)')).toExist()
|
||||
expect(list.find('li:first')).toHaveClass 'selected'
|
||||
expect(selectList.error).not.toBeVisible()
|
||||
|
||||
it "displays an error if there are no matches, removes error when there are matches", ->
|
||||
filterEditorView.getEditor().insertText('nothing will match this')
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li').length).toBe 0
|
||||
expect(selectList.error).not.toBeHidden()
|
||||
|
||||
filterEditorView.getEditor().setText('la')
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li').length).toBe 2
|
||||
expect(selectList.error).not.toBeVisible()
|
||||
|
||||
it "displays no elements until the array has been set on the list", ->
|
||||
selectList.items = null
|
||||
selectList.list.empty()
|
||||
filterEditorView.getEditor().insertText('la')
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li').length).toBe 0
|
||||
expect(selectList.error).toBeHidden()
|
||||
selectList.setItems(items)
|
||||
expect(list.find('li').length).toBe 2
|
||||
|
||||
describe "when core:move-up / core:move-down are triggered on the filterEditorView", ->
|
||||
it "selects the previous / next item in the list, or wraps around to the other side", ->
|
||||
expect(list.find('li:first')).toHaveClass 'selected'
|
||||
|
||||
filterEditorView.trigger 'core:move-up'
|
||||
|
||||
expect(list.find('li:first')).not.toHaveClass 'selected'
|
||||
expect(list.find('li:last')).toHaveClass 'selected'
|
||||
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
|
||||
expect(list.find('li:first')).toHaveClass 'selected'
|
||||
expect(list.find('li:last')).not.toHaveClass 'selected'
|
||||
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
|
||||
expect(list.find('li:eq(0)')).not.toHaveClass 'selected'
|
||||
expect(list.find('li:eq(1)')).toHaveClass 'selected'
|
||||
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
|
||||
expect(list.find('li:eq(1)')).not.toHaveClass 'selected'
|
||||
expect(list.find('li:eq(2)')).toHaveClass 'selected'
|
||||
|
||||
filterEditorView.trigger 'core:move-up'
|
||||
|
||||
expect(list.find('li:eq(2)')).not.toHaveClass 'selected'
|
||||
expect(list.find('li:eq(1)')).toHaveClass 'selected'
|
||||
|
||||
it "scrolls to keep the selected item in view", ->
|
||||
selectList.attachToDom()
|
||||
itemHeight = list.find('li').outerHeight()
|
||||
list.height(itemHeight * 2)
|
||||
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
expect(list.scrollBottom()).toBe itemHeight * 3
|
||||
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
expect(list.scrollBottom()).toBe itemHeight * 4
|
||||
|
||||
filterEditorView.trigger 'core:move-up'
|
||||
filterEditorView.trigger 'core:move-up'
|
||||
expect(list.scrollTop()).toBe itemHeight
|
||||
|
||||
describe "the core:confirm event", ->
|
||||
describe "when there is an item selected (because the list in not empty)", ->
|
||||
it "triggers the selected hook with the selected array element", ->
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
filterEditorView.trigger 'core:move-down'
|
||||
filterEditorView.trigger 'core:confirm'
|
||||
expect(selectList.confirmed).toHaveBeenCalledWith(items[2])
|
||||
|
||||
describe "when there is no item selected (because the list is empty)", ->
|
||||
beforeEach ->
|
||||
selectList.attachToDom()
|
||||
|
||||
it "does not trigger the confirmed hook", ->
|
||||
filterEditorView.getEditor().insertText("i will never match anything")
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li')).not.toExist()
|
||||
filterEditorView.trigger 'core:confirm'
|
||||
expect(selectList.confirmed).not.toHaveBeenCalled()
|
||||
|
||||
it "does trigger the cancelled hook", ->
|
||||
filterEditorView.getEditor().insertText("i will never match anything")
|
||||
window.advanceClock(selectList.inputThrottle)
|
||||
|
||||
expect(list.find('li')).not.toExist()
|
||||
filterEditorView.trigger 'core:confirm'
|
||||
expect(selectList.cancelled).toHaveBeenCalled()
|
||||
|
||||
describe "when a list item is clicked", ->
|
||||
it "selects the item on mousedown and confirms it on mouseup", ->
|
||||
item = list.find('li:eq(1)')
|
||||
|
||||
item.mousedown()
|
||||
expect(item).toHaveClass 'selected'
|
||||
item.mouseup()
|
||||
|
||||
expect(selectList.confirmed).toHaveBeenCalledWith(items[1])
|
||||
|
||||
describe "the core:cancel event", ->
|
||||
it "triggers the cancelled hook and detaches and empties the select list", ->
|
||||
spyOn(selectList, 'detach')
|
||||
filterEditorView.trigger 'core:cancel'
|
||||
expect(selectList.cancelled).toHaveBeenCalled()
|
||||
expect(selectList.detach).toHaveBeenCalled()
|
||||
expect(selectList.list).toBeEmpty()
|
||||
|
||||
describe "when the mini editor loses focus", ->
|
||||
it "triggers the cancelled hook and detaches the select list", ->
|
||||
spyOn(selectList, 'detach')
|
||||
filterEditorView.hiddenInput.trigger 'focusout'
|
||||
expect(selectList.cancelled).toHaveBeenCalled()
|
||||
expect(selectList.detach).toHaveBeenCalled()
|
||||
|
||||
describe "the core:move-to-top event", ->
|
||||
it "scrolls to the top, selects the first element, and does not bubble the event", ->
|
||||
selectList.attachToDom()
|
||||
moveToTopHandler = jasmine.createSpy("moveToTopHandler")
|
||||
selectList.parent().on 'core:move-to-top', moveToTopHandler
|
||||
|
||||
selectList.trigger 'core:move-down'
|
||||
expect(list.find('li:eq(1)')).toHaveClass 'selected'
|
||||
selectList.trigger 'core:move-to-top'
|
||||
expect(list.find('li:first')).toHaveClass 'selected'
|
||||
expect(moveToTopHandler).not.toHaveBeenCalled()
|
||||
|
||||
describe "the core:move-to-bottom event", ->
|
||||
it "scrolls to the bottom, selects the last element, and does not bubble the event", ->
|
||||
selectList.attachToDom()
|
||||
moveToBottomHandler = jasmine.createSpy("moveToBottomHandler")
|
||||
selectList.parent().on 'core:move-to-bottom', moveToBottomHandler
|
||||
|
||||
expect(list.find('li:first')).toHaveClass 'selected'
|
||||
selectList.trigger 'core:move-to-bottom'
|
||||
expect(list.find('li:last')).toHaveClass 'selected'
|
||||
expect(moveToBottomHandler).not.toHaveBeenCalled()
|
||||
@@ -14,7 +14,6 @@ Config = require '../src/config'
|
||||
{Point} = require 'text-buffer'
|
||||
Project = require '../src/project'
|
||||
TextEditor = require '../src/text-editor'
|
||||
TextEditorView = require '../src/text-editor-view'
|
||||
TokenizedBuffer = require '../src/tokenized-buffer'
|
||||
TextEditorComponent = require '../src/text-editor-component'
|
||||
pathwatcher = require 'pathwatcher'
|
||||
@@ -110,7 +109,6 @@ beforeEach ->
|
||||
config.save.reset()
|
||||
|
||||
# make editor display updates synchronous
|
||||
spyOn(TextEditorView.prototype, 'requestDisplayUpdate').andCallFake -> @updateDisplay()
|
||||
TextEditorComponent.performSyncUpdates = true
|
||||
|
||||
spyOn(atom, "setRepresentedFilename")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
_ = require 'underscore-plus'
|
||||
{extend, flatten, toArray, last} = _
|
||||
|
||||
TextEditorView = require '../src/text-editor-view'
|
||||
{TextEditorView} = require 'atom'
|
||||
TextEditorComponent = require '../src/text-editor-component'
|
||||
nbsp = String.fromCharCode(160)
|
||||
|
||||
@@ -698,6 +698,24 @@ describe "TextEditorComponent", ->
|
||||
expect(cursorRect.left).toBe rangeRect.left
|
||||
expect(cursorRect.width).toBe rangeRect.width
|
||||
|
||||
it "accounts for the width of paired characters when positioning cursors", ->
|
||||
atom.config.set('editor.fontFamily', 'sans-serif')
|
||||
editor.setText('he\u0301y') # e with an accent mark
|
||||
editor.setCursorBufferPosition([0, 3])
|
||||
nextAnimationFrame()
|
||||
|
||||
cursor = componentNode.querySelector('.cursor')
|
||||
cursorRect = cursor.getBoundingClientRect()
|
||||
|
||||
cursorLocationTextNode = component.lineNodeForScreenRow(0).querySelector('.source.js').firstChild
|
||||
range = document.createRange()
|
||||
range.setStart(cursorLocationTextNode, 3)
|
||||
range.setEnd(cursorLocationTextNode, 4)
|
||||
rangeRect = range.getBoundingClientRect()
|
||||
|
||||
expect(cursorRect.left).toBe rangeRect.left
|
||||
expect(cursorRect.width).toBe rangeRect.width
|
||||
|
||||
it "positions cursors correctly after character widths are changed via a stylesheet change", ->
|
||||
atom.config.set('editor.fontFamily', 'sans-serif')
|
||||
editor.setCursorScreenPosition([0, 16])
|
||||
@@ -2268,6 +2286,12 @@ describe "TextEditorComponent", ->
|
||||
editor.setGrammar(atom.syntax.nullGrammar)
|
||||
expect(wrapperNode.dataset.grammar).toBe 'text plain null-grammar'
|
||||
|
||||
describe "encoding data attributes", ->
|
||||
it "adds and updates the encoding data attribute based on the current encoding", ->
|
||||
expect(wrapperNode.dataset.encoding).toBe 'utf8'
|
||||
editor.setEncoding('utf16le')
|
||||
expect(wrapperNode.dataset.encoding).toBe 'utf16le'
|
||||
|
||||
describe "detaching and reattaching the editor (regression)", ->
|
||||
it "does not throw an exception", ->
|
||||
wrapperView.detach()
|
||||
|
||||
@@ -157,6 +157,19 @@ describe "TextEditor", ->
|
||||
|
||||
expect(observed).toEqual [__filename, undefined]
|
||||
|
||||
describe "encoding", ->
|
||||
it "notifies ::onDidChangeEncoding observers when the editor encoding changes", ->
|
||||
observed = []
|
||||
editor.onDidChangeEncoding (encoding) -> observed.push(encoding)
|
||||
|
||||
editor.setEncoding('utf16le')
|
||||
editor.setEncoding('utf16le')
|
||||
editor.setEncoding('utf16be')
|
||||
editor.setEncoding()
|
||||
editor.setEncoding()
|
||||
|
||||
expect(observed).toEqual ['utf16le', 'utf16be', 'utf8']
|
||||
|
||||
describe "cursor", ->
|
||||
describe ".getLastCursor()", ->
|
||||
it "returns the most recently created cursor", ->
|
||||
|
||||
@@ -2,18 +2,23 @@ textUtils = require '../src/text-utils'
|
||||
|
||||
describe 'text utilities', ->
|
||||
describe '.hasPairedCharacter(string)', ->
|
||||
it 'returns true when the string contains a surrogate pair or variation sequence', ->
|
||||
it 'returns true when the string contains a surrogate pair, variation sequence, or combined character', ->
|
||||
expect(textUtils.hasPairedCharacter('abc')).toBe false
|
||||
expect(textUtils.hasPairedCharacter('a\uD835\uDF97b\uD835\uDF97c')).toBe true
|
||||
expect(textUtils.hasPairedCharacter('\uD835\uDF97')).toBe true
|
||||
expect(textUtils.hasPairedCharacter('\u2714\uFE0E')).toBe true
|
||||
expect(textUtils.hasPairedCharacter('e\u0301')).toBe true
|
||||
|
||||
expect(textUtils.hasPairedCharacter('\uD835')).toBe false
|
||||
expect(textUtils.hasPairedCharacter('\uDF97')).toBe false
|
||||
expect(textUtils.hasPairedCharacter('\uFE0E')).toBe false
|
||||
expect(textUtils.hasPairedCharacter('\u0301')).toBe false
|
||||
|
||||
expect(textUtils.hasPairedCharacter('\uFE0E\uFE0E')).toBe false
|
||||
expect(textUtils.hasPairedCharacter('\u0301\u0301')).toBe false
|
||||
|
||||
describe '.isPairedCharacter(string, index)', ->
|
||||
it 'returns true when the index is the start of a high/low surrogate pair or variation sequence', ->
|
||||
it 'returns true when the index is the start of a high/low surrogate pair, variation sequence, or combined character', ->
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 0)).toBe false
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 1)).toBe true
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 2)).toBe false
|
||||
@@ -21,12 +26,21 @@ describe 'text utilities', ->
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 4)).toBe true
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 5)).toBe false
|
||||
expect(textUtils.isPairedCharacter('a\uD835\uDF97b\uD835\uDF97c', 6)).toBe false
|
||||
|
||||
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 0)).toBe false
|
||||
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 1)).toBe true
|
||||
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 2)).toBe false
|
||||
expect(textUtils.isPairedCharacter('a\u2714\uFE0E', 3)).toBe false
|
||||
|
||||
expect(textUtils.isPairedCharacter('\uD835')).toBe false
|
||||
expect(textUtils.isPairedCharacter('\uDF97')).toBe false
|
||||
expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
|
||||
expect(textUtils.isPairedCharacter('\uFE0E')).toBe false
|
||||
|
||||
expect(textUtils.isPairedCharacter('\uFE0E\uFE0E')).toBe false
|
||||
|
||||
expect(textUtils.isPairedCharacter('ae\u0301c', 0)).toBe false
|
||||
expect(textUtils.isPairedCharacter('ae\u0301c', 1)).toBe true
|
||||
expect(textUtils.isPairedCharacter('ae\u0301c', 2)).toBe false
|
||||
expect(textUtils.isPairedCharacter('ae\u0301c', 3)).toBe false
|
||||
expect(textUtils.isPairedCharacter('ae\u0301c', 4)).toBe false
|
||||
|
||||
@@ -92,8 +92,8 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 1
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-syntax/
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(1)').attr('source-path')).toMatch /atom-dark-syntax/
|
||||
atom.config.set('core.themes', ['atom-light-syntax', 'atom-dark-syntax'])
|
||||
|
||||
waitsFor ->
|
||||
@@ -111,7 +111,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style[group=theme]')).toHaveLength 0
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
# atom-dark-ui has an directory path, the syntax one doesn't
|
||||
atom.config.set('core.themes', ['theme-with-index-less', 'atom-dark-ui'])
|
||||
|
||||
@@ -208,7 +208,7 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "base stylesheet loading", ->
|
||||
beforeEach ->
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.append $('<atom-text-editor>')
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
@@ -217,7 +217,7 @@ describe "ThemeManager", ->
|
||||
|
||||
it "loads the correct values from the theme's ui-variables file", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -234,7 +234,7 @@ describe "ThemeManager", ->
|
||||
describe "when there is a theme with incomplete variables", ->
|
||||
it "loads the correct values from the fallback ui-variables", ->
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-incomplete-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-incomplete-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -251,7 +251,7 @@ describe "ThemeManager", ->
|
||||
expect(atom.workspaceView).toHaveClass 'theme-atom-dark-ui'
|
||||
|
||||
themeManager.onDidReloadAll reloadHandler = jasmine.createSpy()
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables'])
|
||||
atom.config.set('core.themes', ['theme-with-ui-variables', 'theme-with-syntax-variables'])
|
||||
|
||||
waitsFor ->
|
||||
reloadHandler.callCount > 0
|
||||
@@ -259,7 +259,9 @@ describe "ThemeManager", ->
|
||||
runs ->
|
||||
# `theme-` twice as it prefixes the name with `theme-`
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-ui-variables'
|
||||
expect(atom.workspaceView).toHaveClass 'theme-theme-with-syntax-variables'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-ui'
|
||||
expect(atom.workspaceView).not.toHaveClass 'theme-atom-dark-syntax'
|
||||
|
||||
describe "when the user stylesheet changes", ->
|
||||
it "reloads it", ->
|
||||
@@ -308,24 +310,19 @@ describe "ThemeManager", ->
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
describe "when a non-existent theme is present in the config", ->
|
||||
it "logs a warning but does not throw an exception (regression)", ->
|
||||
reloaded = false
|
||||
beforeEach ->
|
||||
spyOn(console, 'warn')
|
||||
atom.config.set('core.themes', ['non-existent-dark-ui', 'non-existent-dark-syntax'])
|
||||
|
||||
waitsForPromise ->
|
||||
themeManager.activateThemes()
|
||||
|
||||
runs ->
|
||||
disposable = themeManager.onDidReloadAll ->
|
||||
disposable.dispose()
|
||||
reloaded = true
|
||||
spyOn(console, 'warn')
|
||||
expect(-> atom.config.set('core.themes', ['atom-light-ui', 'theme-really-does-not-exist'])).not.toThrow()
|
||||
|
||||
waitsFor -> reloaded
|
||||
|
||||
runs ->
|
||||
expect(console.warn.callCount).toBe 1
|
||||
expect(console.warn.argsForCall[0][0].length).toBeGreaterThan 0
|
||||
it 'uses the default dark UI and syntax themes and logs a warning', ->
|
||||
activeThemeNames = themeManager.getActiveNames()
|
||||
expect(console.warn.callCount).toBe 2
|
||||
expect(activeThemeNames.length).toBe(2)
|
||||
expect(activeThemeNames).toContain('atom-dark-ui')
|
||||
expect(activeThemeNames).toContain('atom-dark-syntax')
|
||||
|
||||
describe "when in safe mode", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{$, $$, WorkspaceView, View} = require 'atom'
|
||||
{$, $$, WorkspaceView, View, TextEditorView} = require 'atom'
|
||||
Q = require 'q'
|
||||
path = require 'path'
|
||||
temp = require 'temp'
|
||||
TextEditorView = require '../src/text-editor-view'
|
||||
PaneView = require '../src/pane-view'
|
||||
Workspace = require '../src/workspace'
|
||||
|
||||
@@ -13,7 +12,7 @@ describe "WorkspaceView", ->
|
||||
atom.project.setPaths([atom.project.resolve('dir')])
|
||||
pathToOpen = atom.project.resolve('a')
|
||||
atom.workspace = new Workspace
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.enableKeymap()
|
||||
atom.workspaceView.focus()
|
||||
|
||||
@@ -29,7 +28,7 @@ describe "WorkspaceView", ->
|
||||
atom.workspaceView.remove()
|
||||
atom.project = atom.deserializers.deserialize(projectState)
|
||||
atom.workspace = Workspace.deserialize(workspaceState)
|
||||
atom.workspaceView = atom.workspace.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView = atom.views.getView(atom.workspace).__spacePenView
|
||||
atom.workspaceView.attachToDom()
|
||||
|
||||
describe "when the serialized WorkspaceView has an unsaved buffer", ->
|
||||
@@ -274,7 +273,7 @@ describe "WorkspaceView", ->
|
||||
describe 'panel containers', ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
workspaceElement = atom.workspace.getView(atom.workspace)
|
||||
workspaceElement = atom.views.getView(atom.workspace)
|
||||
|
||||
it 'inserts panel container elements in the correct places in the DOM', ->
|
||||
leftContainer = workspaceElement.querySelector('atom-panel-container[location="left"]')
|
||||
|
||||
+7
-2
@@ -107,7 +107,7 @@ class Atom extends Model
|
||||
Section: Properties
|
||||
###
|
||||
|
||||
# Experimental: A {CommandRegistry} instance
|
||||
# Public: A {CommandRegistry} instance
|
||||
commands: null
|
||||
|
||||
# Public: A {Config} instance
|
||||
@@ -140,6 +140,9 @@ class Atom extends Model
|
||||
# Public: A {DeserializerManager} instance
|
||||
deserializers: null
|
||||
|
||||
# Public: A {ViewRegistry} instance
|
||||
views: null
|
||||
|
||||
# Public: A {Workspace} instance
|
||||
workspace: null
|
||||
|
||||
@@ -182,6 +185,7 @@ class Atom extends Model
|
||||
|
||||
Config = require './config'
|
||||
KeymapManager = require './keymap-extensions'
|
||||
ViewRegistry = require './view-registry'
|
||||
CommandRegistry = require './command-registry'
|
||||
PackageManager = require './package-manager'
|
||||
Clipboard = require './clipboard'
|
||||
@@ -209,6 +213,7 @@ class Atom extends Model
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@commands = new CommandRegistry
|
||||
@views = new ViewRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager
|
||||
document.head.appendChild(new StylesElement)
|
||||
@@ -597,7 +602,7 @@ class Atom extends Model
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace = Workspace.deserialize(@state.workspace) ? new Workspace
|
||||
@workspaceView = @workspace.getView(@workspace).__spacePenView
|
||||
@workspaceView = @views.getView(@workspace).__spacePenView
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
@keymaps.defaultTarget = @workspaceView[0]
|
||||
|
||||
@@ -22,14 +22,10 @@ class ApplicationMenu
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
update: (window, template, keystrokesByCommand) ->
|
||||
return unless window is @lastFocusedWindow
|
||||
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@windowTemplates.set(window, template)
|
||||
@setActiveTemplate(template)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
@setActiveTemplate(template) if window is @lastFocusedWindow
|
||||
|
||||
setActiveTemplate: (template) ->
|
||||
unless _.isEqual(template, @activeTemplate)
|
||||
@@ -37,6 +33,8 @@ class ApplicationMenu
|
||||
@menu = Menu.buildFromTemplate(_.deepClone(template))
|
||||
Menu.setApplicationMenu(@menu)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
|
||||
# Register a BrowserWindow with this application menu.
|
||||
addWindow: (window) ->
|
||||
@lastFocusedWindow ?= window
|
||||
@@ -48,6 +46,7 @@ class ApplicationMenu
|
||||
|
||||
window.on 'focus', focusHandler
|
||||
window.once 'closed', =>
|
||||
@lastFocusedWindow = null if window is @lastFocusedWindow
|
||||
@windowTemplates.delete(window)
|
||||
window.removeListener 'focus', focusHandler
|
||||
|
||||
|
||||
@@ -155,7 +155,13 @@ class AtomApplication
|
||||
atomWindow?.browserWindow.inspectElement(x, y)
|
||||
|
||||
@on 'application:open-documentation', -> require('shell').openExternal('https://atom.io/docs/latest/?app')
|
||||
@on 'application:open-discussions', -> require('shell').openExternal('https://discuss.atom.io')
|
||||
@on 'application:open-roadmap', -> require('shell').openExternal('https://atom.io/roadmap?app')
|
||||
@on 'application:open-faq', -> require('shell').openExternal('https://atom.io/faq')
|
||||
@on 'application:open-terms-of-use', -> require('shell').openExternal('https://atom.io/terms')
|
||||
@on 'application:report-issue', -> require('shell').openExternal('https://github.com/atom/atom/issues/new')
|
||||
@on 'application:search-issues', -> require('shell').openExternal('https://github.com/issues?q=+is%3Aissue+user%3Aatom')
|
||||
|
||||
@on 'application:install-update', -> @autoUpdateManager.install()
|
||||
@on 'application:check-for-update', => @autoUpdateManager.check()
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@ _ = require 'underscore-plus'
|
||||
SequenceCount = 0
|
||||
SpecificityCache = {}
|
||||
|
||||
module.exports =
|
||||
|
||||
# Experimental: Associates listener functions with commands in a
|
||||
# Public: Associates listener functions with commands in a
|
||||
# context-sensitive way using CSS selectors. You can access a global instance of
|
||||
# this class via `atom.commands`, and commands registered there will be
|
||||
# presented in the command palette.
|
||||
@@ -42,6 +40,7 @@ module.exports =
|
||||
# # editor = @getModel()
|
||||
# editor.insertText(new Date().toLocaleString())
|
||||
# ```
|
||||
module.exports =
|
||||
class CommandRegistry
|
||||
constructor: (@rootNode) ->
|
||||
@registeredCommands = {}
|
||||
|
||||
+6
-5
@@ -314,6 +314,7 @@ class Config
|
||||
@settings = {}
|
||||
@scopedSettingsStore = new ScopedPropertyStore
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettingPriority = {priority: 1000}
|
||||
@configFileHasErrors = false
|
||||
@configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson'])
|
||||
@configFilePath ?= path.join(@configDirPath, 'config.cson')
|
||||
@@ -537,7 +538,7 @@ class Config
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
@addScopedSettings('user-config', scopeSelector, settings)
|
||||
@addScopedSettings('user-config', scopeSelector, settings, @usersScopedSettingPriority)
|
||||
@save() unless @configFileHasErrors
|
||||
@getDefault(scopeSelector, keyPath)
|
||||
else
|
||||
@@ -881,13 +882,13 @@ class Config
|
||||
resetUserScopedSettings: (newScopedSettings) ->
|
||||
@usersScopedSettings?.dispose()
|
||||
@usersScopedSettings = new CompositeDisposable
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', newScopedSettings)
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', newScopedSettings, @usersScopedSettingPriority)
|
||||
@emitter.emit 'did-change'
|
||||
|
||||
addScopedSettings: (source, selector, value) ->
|
||||
addScopedSettings: (source, selector, value, options) ->
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
disposable = @scopedSettingsStore.addProperties(source, settingsBySelector)
|
||||
disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
|
||||
@emitter.emit 'did-change'
|
||||
new Disposable =>
|
||||
disposable.dispose()
|
||||
@@ -901,7 +902,7 @@ class Config
|
||||
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', settingsBySelector)
|
||||
@usersScopedSettings.add @scopedSettingsStore.addProperties('user-config', settingsBySelector, @usersScopedSettingPriority)
|
||||
@emitter.emit 'did-change'
|
||||
|
||||
getRawScopedValue: (scopeDescriptor, keyPath) ->
|
||||
|
||||
@@ -651,10 +651,20 @@ class DisplayBuffer extends Model
|
||||
column = 0
|
||||
for token in @tokenizedLineForScreenRow(targetRow).tokens
|
||||
charWidths = @getScopedCharWidths(token.scopes)
|
||||
for char in token.value
|
||||
valueIndex = 0
|
||||
while valueIndex < token.value.length
|
||||
if token.hasPairedCharacter
|
||||
char = token.value.substr(valueIndex, 2)
|
||||
charLength = 2
|
||||
valueIndex += 2
|
||||
else
|
||||
char = token.value[valueIndex]
|
||||
charLength = 1
|
||||
valueIndex++
|
||||
|
||||
return {top, left} if column is targetColumn
|
||||
left += charWidths[char] ? defaultCharWidth unless char is '\0'
|
||||
column++
|
||||
column += charLength
|
||||
{top, left}
|
||||
|
||||
screenPositionForPixelPosition: (pixelPosition) ->
|
||||
@@ -670,11 +680,21 @@ class DisplayBuffer extends Model
|
||||
column = 0
|
||||
for token in @tokenizedLineForScreenRow(row).tokens
|
||||
charWidths = @getScopedCharWidths(token.scopes)
|
||||
for char in token.value
|
||||
valueIndex = 0
|
||||
while valueIndex < token.value.length
|
||||
if token.hasPairedCharacter
|
||||
char = token.value.substr(valueIndex, 2)
|
||||
charLength = 2
|
||||
valueIndex += 2
|
||||
else
|
||||
char = token.value[valueIndex]
|
||||
charLength = 1
|
||||
valueIndex++
|
||||
|
||||
charWidth = charWidths[char] ? defaultCharWidth
|
||||
break if targetLeft <= left + (charWidth / 2)
|
||||
left += charWidth
|
||||
column++
|
||||
column += charLength
|
||||
|
||||
new Point(row, column)
|
||||
|
||||
@@ -715,6 +735,10 @@ class DisplayBuffer extends Model
|
||||
#
|
||||
# Returns a {Point}.
|
||||
screenPositionForBufferPosition: (bufferPosition, options) ->
|
||||
# TODO: Expand this exception to cover all versions once we burn it in on non-release builds
|
||||
if @isDestroyed() and not atom.isReleasedVersion()
|
||||
throw new Error("This TextEditor has been destroyed")
|
||||
|
||||
{ row, column } = @buffer.clipPosition(bufferPosition)
|
||||
[startScreenRow, endScreenRow] = @rowMap.screenRowRangeForBufferRow(row)
|
||||
for screenRow in [startScreenRow...endScreenRow]
|
||||
@@ -1052,7 +1076,7 @@ class DisplayBuffer extends Model
|
||||
marker.notifyObservers(textChanged: false)
|
||||
|
||||
destroyed: ->
|
||||
marker.unsubscribe() for marker in @getMarkers()
|
||||
marker.unsubscribe() for id, marker of @markers
|
||||
@tokenizedBuffer.destroy()
|
||||
@unsubscribe()
|
||||
|
||||
|
||||
@@ -308,10 +308,20 @@ LinesComponent = React.createClass
|
||||
iterator = null
|
||||
charIndex = 0
|
||||
|
||||
for {value, scopes}, tokenIndex in tokenizedLine.tokens
|
||||
for {value, scopes, hasPairedCharacter} in tokenizedLine.tokens
|
||||
charWidths = editor.getScopedCharWidths(scopes)
|
||||
|
||||
for char in value
|
||||
valueIndex = 0
|
||||
while valueIndex < value.length
|
||||
if hasPairedCharacter
|
||||
char = value.substr(valueIndex, 2)
|
||||
charLength = 2
|
||||
valueIndex += 2
|
||||
else
|
||||
char = value[valueIndex]
|
||||
charLength = 1
|
||||
valueIndex++
|
||||
|
||||
continue if char is '\0'
|
||||
|
||||
unless charWidths[char]?
|
||||
@@ -329,11 +339,11 @@ LinesComponent = React.createClass
|
||||
|
||||
i = charIndex - textNodeIndex
|
||||
rangeForMeasurement.setStart(textNode, i)
|
||||
rangeForMeasurement.setEnd(textNode, i + 1)
|
||||
rangeForMeasurement.setEnd(textNode, i + charLength)
|
||||
charWidth = rangeForMeasurement.getBoundingClientRect().width
|
||||
editor.setScopedCharWidth(scopes, char, charWidth)
|
||||
|
||||
charIndex++
|
||||
charIndex += charLength
|
||||
|
||||
@measuredLines.add(tokenizedLine)
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ normalizeLabel = (label) ->
|
||||
label.replace(/\&/g, '')
|
||||
|
||||
cloneMenuItem = (item) ->
|
||||
item = _.pick(item, 'type', 'label', 'command', 'submenu', 'commandDetail')
|
||||
item = _.pick(item, 'type', 'label', 'enabled', 'command', 'submenu', 'commandDetail')
|
||||
if item.submenu?
|
||||
item.submenu = item.submenu.map (submenuItem) -> cloneMenuItem(submenuItem)
|
||||
item
|
||||
|
||||
@@ -192,7 +192,7 @@ resolveModulePath = (relativePath, parentModule) ->
|
||||
return
|
||||
|
||||
registerBuiltins = (devMode) ->
|
||||
if devMode
|
||||
if devMode or not cache.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}")
|
||||
fs = require 'fs-plus'
|
||||
atomCoffeePath = path.join(cache.resourcePath, 'exports', 'atom.coffee')
|
||||
cache.builtins.atom = atomCoffeePath if fs.isFileSync(atomCoffeePath)
|
||||
|
||||
@@ -107,8 +107,9 @@ class PaneElement extends HTMLElement
|
||||
|
||||
hideItemView: (itemView) ->
|
||||
inlineDisplayStyle = itemView.style.display
|
||||
@inlineDisplayStyles.set(itemView, inlineDisplayStyle) if inlineDisplayStyle?
|
||||
itemView.style.display = 'none'
|
||||
unless inlineDisplayStyle is 'none'
|
||||
@inlineDisplayStyles.set(itemView, inlineDisplayStyle) if inlineDisplayStyle?
|
||||
itemView.style.display = 'none'
|
||||
|
||||
itemRemoved: ({item, index, destroyed}) ->
|
||||
if viewToRemove = @model.getView(item)
|
||||
|
||||
+3
-2
@@ -63,8 +63,9 @@ class Pane extends Model
|
||||
getContainer: -> @container
|
||||
|
||||
setContainer: (container) ->
|
||||
container.didAddPane({pane: this}) unless container is @container
|
||||
@container = container
|
||||
unless container is @container
|
||||
@container = container
|
||||
container.didAddPane({pane: this})
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
{View} = require './space-pen-extensions'
|
||||
|
||||
# Extended: Represents a view that scrolls.
|
||||
#
|
||||
# Handles several core events to update scroll position:
|
||||
#
|
||||
# * `core:move-up` Scrolls the view up
|
||||
# * `core:move-down` Scrolls the view down
|
||||
# * `core:page-up` Scrolls the view up by the height of the page
|
||||
# * `core:page-down` Scrolls the view down by the height of the page
|
||||
# * `core:move-to-top` Scrolls the editor to the top
|
||||
# * `core:move-to-bottom` Scroll the editor to the bottom
|
||||
#
|
||||
# Subclasses must call `super` if overriding the `initialize` method.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ```coffee
|
||||
# {ScrollView} = require 'atom'
|
||||
#
|
||||
# class MyView extends ScrollView
|
||||
# @content: ->
|
||||
# @div()
|
||||
#
|
||||
# initialize: ->
|
||||
# super
|
||||
# @text('super long content that will scroll')
|
||||
# ```
|
||||
#
|
||||
module.exports =
|
||||
class ScrollView extends View
|
||||
initialize: ->
|
||||
@on 'core:move-up', => @scrollUp()
|
||||
@on 'core:move-down', => @scrollDown()
|
||||
@on 'core:page-up', => @pageUp()
|
||||
@on 'core:page-down', => @pageDown()
|
||||
@on 'core:move-to-top', => @scrollToTop()
|
||||
@on 'core:move-to-bottom', => @scrollToBottom()
|
||||
@@ -1,312 +0,0 @@
|
||||
{$, View} = require './space-pen-extensions'
|
||||
TextEditorView = require './text-editor-view'
|
||||
fuzzyFilter = require('fuzzaldrin').filter
|
||||
|
||||
# Essential: Provides a view that renders a list of items with an editor that
|
||||
# filters the items. Used by many packages such as the fuzzy-finder,
|
||||
# command-palette, symbols-view and autocomplete.
|
||||
#
|
||||
# Subclasses must implement the following methods:
|
||||
#
|
||||
# * {::viewForItem}
|
||||
# * {::confirmed}
|
||||
#
|
||||
# ## Requiring in packages
|
||||
#
|
||||
# ```coffee
|
||||
# {SelectListView} = require 'atom'
|
||||
#
|
||||
# class MySelectListView extends SelectListView
|
||||
# initialize: ->
|
||||
# super
|
||||
# @addClass('overlay from-top')
|
||||
# @setItems(['Hello', 'World'])
|
||||
# atom.workspaceView.append(this)
|
||||
# @focusFilterEditor()
|
||||
#
|
||||
# viewForItem: (item) ->
|
||||
# "<li>#{item}</li>"
|
||||
#
|
||||
# confirmed: (item) ->
|
||||
# console.log("#{item} was selected")
|
||||
# ```
|
||||
module.exports =
|
||||
class SelectListView extends View
|
||||
@content: ->
|
||||
@div class: 'select-list', =>
|
||||
@subview 'filterEditorView', new TextEditorView(mini: true)
|
||||
@div class: 'error-message', outlet: 'error'
|
||||
@div class: 'loading', outlet: 'loadingArea', =>
|
||||
@span class: 'loading-message', outlet: 'loading'
|
||||
@span class: 'badge', outlet: 'loadingBadge'
|
||||
@ol class: 'list-group', outlet: 'list'
|
||||
|
||||
maxItems: Infinity
|
||||
scheduleTimeout: null
|
||||
inputThrottle: 50
|
||||
cancelling: false
|
||||
|
||||
###
|
||||
Section: Construction
|
||||
###
|
||||
|
||||
# Essential: Initialize the select list view.
|
||||
#
|
||||
# This method can be overridden by subclasses but `super` should always
|
||||
# be called.
|
||||
initialize: ->
|
||||
@filterEditorView.getEditor().getBuffer().onDidChange =>
|
||||
@schedulePopulateList()
|
||||
@filterEditorView.hiddenInput.on 'focusout', =>
|
||||
@cancel() unless @cancelling
|
||||
|
||||
# This prevents the focusout event from firing on the filter editor view
|
||||
# when the list is scrolled by clicking the scrollbar and dragging.
|
||||
@list.on 'mousedown', ({target}) =>
|
||||
false if target is @list[0]
|
||||
|
||||
@on 'core:move-up', =>
|
||||
@selectPreviousItemView()
|
||||
@on 'core:move-down', =>
|
||||
@selectNextItemView()
|
||||
@on 'core:move-to-top', =>
|
||||
@selectItemView(@list.find('li:first'))
|
||||
@list.scrollToTop()
|
||||
false
|
||||
@on 'core:move-to-bottom', =>
|
||||
@selectItemView(@list.find('li:last'))
|
||||
@list.scrollToBottom()
|
||||
false
|
||||
|
||||
@on 'core:confirm', => @confirmSelection()
|
||||
@on 'core:cancel', => @cancel()
|
||||
|
||||
@list.on 'mousedown', 'li', (e) =>
|
||||
@selectItemView($(e.target).closest('li'))
|
||||
e.preventDefault()
|
||||
|
||||
@list.on 'mouseup', 'li', (e) =>
|
||||
@confirmSelection() if $(e.target).closest('li').hasClass('selected')
|
||||
e.preventDefault()
|
||||
|
||||
###
|
||||
Section: Methods that must be overridden
|
||||
###
|
||||
|
||||
# Essential: Create a view for the given model item.
|
||||
#
|
||||
# This method must be overridden by subclasses.
|
||||
#
|
||||
# This is called when the item is about to appended to the list view.
|
||||
#
|
||||
# * `item` The model item being rendered. This will always be one of the items
|
||||
# previously passed to {::setItems}.
|
||||
#
|
||||
# Returns a String of HTML, DOM element, jQuery object, or View.
|
||||
viewForItem: (item) ->
|
||||
throw new Error("Subclass must implement a viewForItem(item) method")
|
||||
|
||||
# Essential: Callback function for when an item is selected.
|
||||
#
|
||||
# This method must be overridden by subclasses.
|
||||
#
|
||||
# * `item` The selected model item. This will always be one of the items
|
||||
# previously passed to {::setItems}.
|
||||
#
|
||||
# Returns a DOM element, jQuery object, or {View}.
|
||||
confirmed: (item) ->
|
||||
throw new Error("Subclass must implement a confirmed(item) method")
|
||||
|
||||
###
|
||||
Section: Managing the list of items
|
||||
###
|
||||
|
||||
# Essential: Set the array of items to display in the list.
|
||||
#
|
||||
# This should be model items not actual views. {::viewForItem} will be
|
||||
# called to render the item when it is being appended to the list view.
|
||||
#
|
||||
# * `items` The {Array} of model items to display in the list (default: []).
|
||||
setItems: (@items=[]) ->
|
||||
@populateList()
|
||||
@setLoading()
|
||||
|
||||
# Essential: Get the model item that is currently selected in the list view.
|
||||
#
|
||||
# Returns a model item.
|
||||
getSelectedItem: ->
|
||||
@getSelectedItemView().data('select-list-item')
|
||||
|
||||
# Extended: Get the property name to use when filtering items.
|
||||
#
|
||||
# This method may be overridden by classes to allow fuzzy filtering based
|
||||
# on a specific property of the item objects.
|
||||
#
|
||||
# For example if the objects you pass to {::setItems} are of the type
|
||||
# `{"id": 3, "name": "Atom"}` then you would return `"name"` from this method
|
||||
# to fuzzy filter by that property when text is entered into this view's
|
||||
# editor.
|
||||
#
|
||||
# Returns the property name to fuzzy filter by.
|
||||
getFilterKey: ->
|
||||
|
||||
# Extended: Get the filter query to use when fuzzy filtering the visible
|
||||
# elements.
|
||||
#
|
||||
# By default this method returns the text in the mini editor but it can be
|
||||
# overridden by subclasses if needed.
|
||||
#
|
||||
# Returns a {String} to use when fuzzy filtering the elements to display.
|
||||
getFilterQuery: ->
|
||||
@filterEditorView.getEditor().getText()
|
||||
|
||||
# Extended: Set the maximum numbers of items to display in the list.
|
||||
#
|
||||
# * `maxItems` The maximum {Number} of items to display.
|
||||
setMaxItems: (@maxItems) ->
|
||||
|
||||
# Extended: Populate the list view with the model items previously set by
|
||||
# calling {::setItems}.
|
||||
#
|
||||
# Subclasses may override this method but should always call `super`.
|
||||
populateList: ->
|
||||
return unless @items?
|
||||
|
||||
filterQuery = @getFilterQuery()
|
||||
if filterQuery.length
|
||||
filteredItems = fuzzyFilter(@items, filterQuery, key: @getFilterKey())
|
||||
else
|
||||
filteredItems = @items
|
||||
|
||||
@list.empty()
|
||||
if filteredItems.length
|
||||
@setError(null)
|
||||
|
||||
for i in [0...Math.min(filteredItems.length, @maxItems)]
|
||||
item = filteredItems[i]
|
||||
itemView = $(@viewForItem(item))
|
||||
itemView.data('select-list-item', item)
|
||||
@list.append(itemView)
|
||||
|
||||
@selectItemView(@list.find('li:first'))
|
||||
else
|
||||
@setError(@getEmptyMessage(@items.length, filteredItems.length))
|
||||
|
||||
###
|
||||
Section: Messages to the user
|
||||
###
|
||||
|
||||
# Essential: Set the error message to display.
|
||||
#
|
||||
# * `message` The {String} error message (default: '').
|
||||
setError: (message='') ->
|
||||
if message.length is 0
|
||||
@error.text('').hide()
|
||||
else
|
||||
@setLoading()
|
||||
@error.text(message).show()
|
||||
|
||||
# Essential: Set the loading message to display.
|
||||
#
|
||||
# * `message` The {String} loading message (default: '').
|
||||
setLoading: (message='') ->
|
||||
if message.length is 0
|
||||
@loading.text("")
|
||||
@loadingBadge.text("")
|
||||
@loadingArea.hide()
|
||||
else
|
||||
@setError()
|
||||
@loading.text(message)
|
||||
@loadingArea.show()
|
||||
|
||||
# Extended: Get the message to display when there are no items.
|
||||
#
|
||||
# Subclasses may override this method to customize the message.
|
||||
#
|
||||
# * `itemCount` The {Number} of items in the array specified to {::setItems}
|
||||
# * `filteredItemCount` The {Number} of items that pass the fuzzy filter test.
|
||||
#
|
||||
# Returns a {String} message (default: 'No matches found').
|
||||
getEmptyMessage: (itemCount, filteredItemCount) -> 'No matches found'
|
||||
|
||||
###
|
||||
Section: View Actions
|
||||
###
|
||||
|
||||
# Essential: Cancel and close this select list view.
|
||||
#
|
||||
# This restores focus to the previously focused element if
|
||||
# {::storeFocusedElement} was called prior to this view being attached.
|
||||
cancel: ->
|
||||
@list.empty()
|
||||
@cancelling = true
|
||||
filterEditorViewFocused = @filterEditorView.isFocused
|
||||
@cancelled()
|
||||
@detach()
|
||||
@restoreFocus() if filterEditorViewFocused
|
||||
@cancelling = false
|
||||
clearTimeout(@scheduleTimeout)
|
||||
|
||||
# Extended: Focus the fuzzy filter editor view.
|
||||
focusFilterEditor: ->
|
||||
@filterEditorView.focus()
|
||||
|
||||
# Extended: Store the currently focused element. This element will be given
|
||||
# back focus when {::cancel} is called.
|
||||
storeFocusedElement: ->
|
||||
@previouslyFocusedElement = $(':focus')
|
||||
|
||||
###
|
||||
Section: Private
|
||||
###
|
||||
|
||||
selectPreviousItemView: ->
|
||||
view = @getSelectedItemView().prev()
|
||||
view = @list.find('li:last') unless view.length
|
||||
@selectItemView(view)
|
||||
|
||||
selectNextItemView: ->
|
||||
view = @getSelectedItemView().next()
|
||||
view = @list.find('li:first') unless view.length
|
||||
@selectItemView(view)
|
||||
|
||||
selectItemView: (view) ->
|
||||
return unless view.length
|
||||
@list.find('.selected').removeClass('selected')
|
||||
view.addClass('selected')
|
||||
@scrollToItemView(view)
|
||||
|
||||
scrollToItemView: (view) ->
|
||||
scrollTop = @list.scrollTop()
|
||||
desiredTop = view.position().top + scrollTop
|
||||
desiredBottom = desiredTop + view.outerHeight()
|
||||
|
||||
if desiredTop < scrollTop
|
||||
@list.scrollTop(desiredTop)
|
||||
else if desiredBottom > @list.scrollBottom()
|
||||
@list.scrollBottom(desiredBottom)
|
||||
|
||||
restoreFocus: ->
|
||||
if @previouslyFocusedElement?.isOnDom()
|
||||
@previouslyFocusedElement.focus()
|
||||
else
|
||||
atom.workspaceView.focus()
|
||||
|
||||
cancelled: ->
|
||||
@filterEditorView.getEditor().setText('')
|
||||
|
||||
getSelectedItemView: ->
|
||||
@list.find('li.selected')
|
||||
|
||||
confirmSelection: ->
|
||||
item = @getSelectedItem()
|
||||
if item?
|
||||
@confirmed(item)
|
||||
else
|
||||
@cancel()
|
||||
|
||||
schedulePopulateList: ->
|
||||
clearTimeout(@scheduleTimeout)
|
||||
populateCallback = =>
|
||||
@populateList() if @isOnDom()
|
||||
@scheduleTimeout = setTimeout(populateCallback, @inputThrottle)
|
||||
@@ -55,6 +55,8 @@ TextEditorComponent = React.createClass
|
||||
hasSelection = editor.getLastSelection()? and !editor.getLastSelection().isEmpty()
|
||||
style = {}
|
||||
|
||||
@performedInitialMeasurement = false if editor.isDestroyed()
|
||||
|
||||
if @performedInitialMeasurement
|
||||
renderedRowRange = @getRenderedRowRange()
|
||||
[renderedStartRow, renderedEndRow] = renderedRowRange
|
||||
@@ -195,6 +197,7 @@ TextEditorComponent = React.createClass
|
||||
|
||||
parentView.__spacePenView.trigger 'editor:will-be-removed', [parentView.__spacePenView]
|
||||
@unsubscribe()
|
||||
@scopedConfigSubscriptions.dispose()
|
||||
window.removeEventListener 'resize', @requestHeightAndWidthMeasurement
|
||||
clearInterval(@domPollingIntervalId)
|
||||
@domPollingIntervalId = null
|
||||
@@ -227,10 +230,10 @@ TextEditorComponent = React.createClass
|
||||
@props.editor.setVisible(true)
|
||||
@performedInitialMeasurement = true
|
||||
@updatesPaused = false
|
||||
@forceUpdate() if @updateRequestedWhilePaused
|
||||
@forceUpdate() if @updateRequestedWhilePaused and @canUpdate()
|
||||
|
||||
requestUpdate: ->
|
||||
return unless @isMounted()
|
||||
return unless @canUpdate()
|
||||
|
||||
if @updatesPaused
|
||||
@updateRequestedWhilePaused = true
|
||||
@@ -242,7 +245,10 @@ TextEditorComponent = React.createClass
|
||||
@updateRequested = true
|
||||
requestAnimationFrame =>
|
||||
@updateRequested = false
|
||||
@forceUpdate() if @isMounted()
|
||||
@forceUpdate() if @canUpdate()
|
||||
|
||||
canUpdate: ->
|
||||
@isMounted() and @props.editor.isAlive()
|
||||
|
||||
requestAnimationFrame: (fn) ->
|
||||
@updatesPaused = true
|
||||
@@ -250,7 +256,7 @@ TextEditorComponent = React.createClass
|
||||
requestAnimationFrame =>
|
||||
fn()
|
||||
@updatesPaused = false
|
||||
if @updateRequestedWhilePaused and @isMounted()
|
||||
if @updateRequestedWhilePaused and @canUpdate()
|
||||
@updateRequestedWhilePaused = false
|
||||
@forceUpdate()
|
||||
|
||||
@@ -773,7 +779,7 @@ TextEditorComponent = React.createClass
|
||||
if position is 'absolute' or height
|
||||
if @autoHeight
|
||||
@autoHeight = false
|
||||
@forceUpdate() unless @updatesPaused
|
||||
@forceUpdate() if not @updatesPaused and @canUpdate()
|
||||
|
||||
clientHeight = scrollViewNode.clientHeight
|
||||
editor.setHeight(clientHeight) if clientHeight > 0
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{View, $} = require 'space-pen'
|
||||
{callRemoveHooks} = require 'space-pen'
|
||||
{Emitter} = require 'event-kit'
|
||||
React = require 'react-atom-fork'
|
||||
{defaults} = require 'underscore-plus'
|
||||
TextBuffer = require 'text-buffer'
|
||||
@@ -13,8 +14,15 @@ class TextEditorElement extends HTMLElement
|
||||
lineOverdrawMargin: null
|
||||
focusOnAttach: false
|
||||
|
||||
onDidAttach: (callback) ->
|
||||
@emitter.on 'did-attach', callback
|
||||
|
||||
onDidDetach: (callback) ->
|
||||
@emitter.on 'did-detach', callback
|
||||
|
||||
createdCallback: ->
|
||||
@subscriptions =
|
||||
@emitter = new Emitter
|
||||
|
||||
@initializeContent()
|
||||
@createSpacePenShim()
|
||||
@addEventListener 'focus', @focused.bind(this)
|
||||
@@ -26,7 +34,7 @@ class TextEditorElement extends HTMLElement
|
||||
@setAttribute('tabindex', -1)
|
||||
|
||||
createSpacePenShim: ->
|
||||
TextEditorView ?= require './text-editor-view'
|
||||
TextEditorView ?= require('atom').TextEditorView
|
||||
@__spacePenView = new TextEditorView(this)
|
||||
|
||||
attachedCallback: ->
|
||||
@@ -34,13 +42,22 @@ class TextEditorElement extends HTMLElement
|
||||
@mountComponent() unless @component?.isMounted()
|
||||
@component.checkForVisibilityChange()
|
||||
@focus() if @focusOnAttach
|
||||
@emitter.emit 'did-attach'
|
||||
|
||||
detachedCallback: ->
|
||||
@emitter.emit 'did-detach'
|
||||
|
||||
setModel: (model) ->
|
||||
throw new Error("Model already assigned on TextEditorElement") if @model?
|
||||
return if model.isDestroyed()
|
||||
|
||||
@model = model
|
||||
@mountComponent()
|
||||
@addGrammarScopeAttribute()
|
||||
@model.onDidChangeGrammar => @addGrammarScopeAttribute()
|
||||
@addEncodingAttribute()
|
||||
@model.onDidChangeEncoding => @addEncodingAttribute()
|
||||
@model.onDidDestroy => @unmountComponent()
|
||||
@__spacePenView.setModel(@model)
|
||||
@model
|
||||
|
||||
@@ -68,6 +85,7 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
unmountComponent: ->
|
||||
return unless @component?.isMounted()
|
||||
callRemoveHooks(this)
|
||||
React.unmountComponentAtNode(this)
|
||||
@component = null
|
||||
|
||||
@@ -85,7 +103,10 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
addGrammarScopeAttribute: ->
|
||||
grammarScope = @model.getGrammar()?.scopeName?.replace(/\./g, ' ')
|
||||
@setAttribute('data-grammar', grammarScope)
|
||||
@dataset.grammar = grammarScope
|
||||
|
||||
addEncodingAttribute: ->
|
||||
@dataset.encoding = @model.getEncoding()
|
||||
|
||||
hasFocus: ->
|
||||
this is document.activeElement or @contains(document.activeElement)
|
||||
|
||||
@@ -1,308 +0,0 @@
|
||||
{View, $} = require 'space-pen'
|
||||
React = require 'react-atom-fork'
|
||||
{defaults} = require 'underscore-plus'
|
||||
TextBuffer = require 'text-buffer'
|
||||
TextEditor = require './text-editor'
|
||||
TextEditorElement = require './text-editor-element'
|
||||
TextEditorComponent = require './text-editor-component'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
# Public: Represents the entire visual pane in Atom.
|
||||
#
|
||||
# The TextEditorView manages the {TextEditor}, which manages the file buffers.
|
||||
# `TextEditorView` is intentionally sparse. Most of the things you'll want
|
||||
# to do are on {TextEditor}.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# Requiring in packages
|
||||
#
|
||||
# ```coffee
|
||||
# {TextEditorView} = require 'atom'
|
||||
#
|
||||
# miniEditorView = new TextEditorView(mini: true)
|
||||
# ```
|
||||
#
|
||||
# Iterating over the open editor views
|
||||
#
|
||||
# ```coffee
|
||||
# for editorView in atom.workspaceView.getEditorViews()
|
||||
# console.log(editorView.getModel().getPath())
|
||||
# ```
|
||||
#
|
||||
# Subscribing to every current and future editor
|
||||
#
|
||||
# ```coffee
|
||||
# atom.workspace.eachEditorView (editorView) ->
|
||||
# console.log(editorView.getModel().getPath())
|
||||
# ```
|
||||
module.exports =
|
||||
class TextEditorView extends View
|
||||
# The constructor for setting up an `TextEditorView` instance.
|
||||
#
|
||||
# * `modelOrParams` Either an {TextEditor}, or an object with one property, `mini`.
|
||||
# If `mini` is `true`, a "miniature" `TextEditor` is constructed.
|
||||
# Typically, this is ideal for scenarios where you need an Atom editor,
|
||||
# but without all the chrome, like scrollbars, gutter, _e.t.c._.
|
||||
#
|
||||
constructor: (modelOrParams, props) ->
|
||||
# Handle direct construction with an editor or params
|
||||
unless modelOrParams instanceof HTMLElement
|
||||
if modelOrParams instanceof TextEditor
|
||||
model = modelOrParams
|
||||
else
|
||||
{editor, mini, placeholderText, attributes} = modelOrParams
|
||||
model = editor ? new TextEditor
|
||||
buffer: new TextBuffer
|
||||
softWrapped: false
|
||||
tabLength: 2
|
||||
softTabs: true
|
||||
mini: mini
|
||||
placeholderText: placeholderText
|
||||
|
||||
element = new TextEditorElement
|
||||
element.lineOverdrawMargin = props?.lineOverdrawMargin
|
||||
element.setAttribute(name, value) for name, value of attributes if attributes?
|
||||
element.setModel(model)
|
||||
return element.__spacePenView
|
||||
|
||||
# Handle construction with an element
|
||||
@element = modelOrParams
|
||||
super
|
||||
|
||||
setModel: (@model) ->
|
||||
@editor = @model
|
||||
|
||||
@scrollView = @find('.scroll-view')
|
||||
@underlayer = @find('.highlights').addClass('underlayer')
|
||||
@overlayer = @find('.lines').addClass('overlayer')
|
||||
@hiddenInput = @.find('.hidden-input')
|
||||
|
||||
@subscribe atom.config.observe 'editor.showLineNumbers', =>
|
||||
@gutter = @find('.gutter')
|
||||
|
||||
@gutter.removeClassFromAllLines = (klass) =>
|
||||
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
||||
@gutter.find('.line-number').removeClass(klass)
|
||||
|
||||
@gutter.getLineNumberElement = (bufferRow) =>
|
||||
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
||||
@gutter.find("[data-buffer-row='#{bufferRow}']")
|
||||
|
||||
@gutter.addClassToLine = (bufferRow, klass) =>
|
||||
deprecate('Use decorations instead: http://blog.atom.io/2014/07/24/decorations.html')
|
||||
lines = @gutter.find("[data-buffer-row='#{bufferRow}']")
|
||||
lines.addClass(klass)
|
||||
lines.length > 0
|
||||
|
||||
# Public: Get the underlying editor model for this view.
|
||||
#
|
||||
# Returns an {TextEditor}
|
||||
getModel: -> @model
|
||||
|
||||
getEditor: -> @model
|
||||
|
||||
Object.defineProperty @::, 'lineHeight', get: -> @model.getLineHeightInPixels()
|
||||
Object.defineProperty @::, 'charWidth', get: -> @model.getDefaultCharWidth()
|
||||
Object.defineProperty @::, 'firstRenderedScreenRow', get: -> @component.getRenderedRowRange()[0]
|
||||
Object.defineProperty @::, 'lastRenderedScreenRow', get: -> @component.getRenderedRowRange()[1]
|
||||
Object.defineProperty @::, 'active', get: -> @is(@getPaneView()?.activeView)
|
||||
Object.defineProperty @::, 'isFocused', get: -> @component?.state.focused
|
||||
Object.defineProperty @::, 'mini', get: -> @component?.props.mini
|
||||
Object.defineProperty @::, 'component', get: -> @element?.component
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
return unless onDom
|
||||
return if @attached
|
||||
@attached = true
|
||||
@trigger 'editor:attached', [this]
|
||||
|
||||
beforeRemove: ->
|
||||
@trigger 'editor:detached', [this]
|
||||
@attached = false
|
||||
|
||||
remove: (selector, keepData) ->
|
||||
@model.destroy() unless keepData
|
||||
super
|
||||
|
||||
scrollTop: (scrollTop) ->
|
||||
if scrollTop?
|
||||
@model.setScrollTop(scrollTop)
|
||||
else
|
||||
@model.getScrollTop()
|
||||
|
||||
scrollLeft: (scrollLeft) ->
|
||||
if scrollLeft?
|
||||
@model.setScrollLeft(scrollLeft)
|
||||
else
|
||||
@model.getScrollLeft()
|
||||
|
||||
scrollToBottom: ->
|
||||
deprecate 'Use TextEditor::scrollToBottom instead. You can get the editor via editorView.getModel()'
|
||||
@model.setScrollBottom(Infinity)
|
||||
|
||||
scrollToScreenPosition: (screenPosition, options) ->
|
||||
deprecate 'Use TextEditor::scrollToScreenPosition instead. You can get the editor via editorView.getModel()'
|
||||
@model.scrollToScreenPosition(screenPosition, options)
|
||||
|
||||
scrollToBufferPosition: (bufferPosition, options) ->
|
||||
deprecate 'Use TextEditor::scrollToBufferPosition instead. You can get the editor via editorView.getModel()'
|
||||
@model.scrollToBufferPosition(bufferPosition, options)
|
||||
|
||||
scrollToCursorPosition: ->
|
||||
deprecate 'Use TextEditor::scrollToCursorPosition instead. You can get the editor via editorView.getModel()'
|
||||
@model.scrollToCursorPosition()
|
||||
|
||||
pixelPositionForBufferPosition: (bufferPosition) ->
|
||||
deprecate 'Use TextEditor::pixelPositionForBufferPosition instead. You can get the editor via editorView.getModel()'
|
||||
@model.pixelPositionForBufferPosition(bufferPosition)
|
||||
|
||||
pixelPositionForScreenPosition: (screenPosition) ->
|
||||
deprecate 'Use TextEditor::pixelPositionForScreenPosition instead. You can get the editor via editorView.getModel()'
|
||||
@model.pixelPositionForScreenPosition(screenPosition)
|
||||
|
||||
appendToLinesView: (view) ->
|
||||
view.css('position', 'absolute')
|
||||
view.css('z-index', 1)
|
||||
@find('.lines').prepend(view)
|
||||
|
||||
unmountComponent: ->
|
||||
React.unmountComponentAtNode(@element) if @component.isMounted()
|
||||
|
||||
splitLeft: ->
|
||||
deprecate """
|
||||
Use Pane::splitLeft instead.
|
||||
To duplicate this editor into the split use:
|
||||
editorView.getPaneView().getModel().splitLeft(copyActiveItem: true)
|
||||
"""
|
||||
pane = @getPaneView()
|
||||
pane?.splitLeft(pane?.copyActiveItem()).activeView
|
||||
|
||||
splitRight: ->
|
||||
deprecate """
|
||||
Use Pane::splitRight instead.
|
||||
To duplicate this editor into the split use:
|
||||
editorView.getPaneView().getModel().splitRight(copyActiveItem: true)
|
||||
"""
|
||||
pane = @getPaneView()
|
||||
pane?.splitRight(pane?.copyActiveItem()).activeView
|
||||
|
||||
splitUp: ->
|
||||
deprecate """
|
||||
Use Pane::splitUp instead.
|
||||
To duplicate this editor into the split use:
|
||||
editorView.getPaneView().getModel().splitUp(copyActiveItem: true)
|
||||
"""
|
||||
pane = @getPaneView()
|
||||
pane?.splitUp(pane?.copyActiveItem()).activeView
|
||||
|
||||
splitDown: ->
|
||||
deprecate """
|
||||
Use Pane::splitDown instead.
|
||||
To duplicate this editor into the split use:
|
||||
editorView.getPaneView().getModel().splitDown(copyActiveItem: true)
|
||||
"""
|
||||
pane = @getPaneView()
|
||||
pane?.splitDown(pane?.copyActiveItem()).activeView
|
||||
|
||||
# Public: Get this {TextEditorView}'s {PaneView}.
|
||||
#
|
||||
# Returns a {PaneView}
|
||||
getPaneView: ->
|
||||
@parent('.item-views').parents('atom-pane').view()
|
||||
getPane: ->
|
||||
deprecate 'Use TextEditorView::getPaneView() instead'
|
||||
@getPaneView()
|
||||
|
||||
show: ->
|
||||
super
|
||||
@component?.checkForVisibilityChange()
|
||||
|
||||
hide: ->
|
||||
super
|
||||
@component?.checkForVisibilityChange()
|
||||
|
||||
pageDown: ->
|
||||
deprecate('Use editorView.getModel().pageDown()')
|
||||
@model.pageDown()
|
||||
|
||||
pageUp: ->
|
||||
deprecate('Use editorView.getModel().pageUp()')
|
||||
@model.pageUp()
|
||||
|
||||
getFirstVisibleScreenRow: ->
|
||||
deprecate 'Use TextEditor::getFirstVisibleScreenRow instead. You can get the editor via editorView.getModel()'
|
||||
@model.getFirstVisibleScreenRow()
|
||||
|
||||
getLastVisibleScreenRow: ->
|
||||
deprecate 'Use TextEditor::getLastVisibleScreenRow instead. You can get the editor via editorView.getModel()'
|
||||
@model.getLastVisibleScreenRow()
|
||||
|
||||
getFontFamily: ->
|
||||
deprecate 'This is going away. Use atom.config.get("editor.fontFamily") instead'
|
||||
@component?.getFontFamily()
|
||||
|
||||
setFontFamily: (fontFamily) ->
|
||||
deprecate 'This is going away. Use atom.config.set("editor.fontFamily", "my-font") instead'
|
||||
@component?.setFontFamily(fontFamily)
|
||||
|
||||
getFontSize: ->
|
||||
deprecate 'This is going away. Use atom.config.get("editor.fontSize") instead'
|
||||
@component?.getFontSize()
|
||||
|
||||
setFontSize: (fontSize) ->
|
||||
deprecate 'This is going away. Use atom.config.set("editor.fontSize", 12) instead'
|
||||
@component?.setFontSize(fontSize)
|
||||
|
||||
setLineHeight: (lineHeight) ->
|
||||
deprecate 'This is going away. Use atom.config.set("editor.lineHeight", 1.5) instead'
|
||||
@component.setLineHeight(lineHeight)
|
||||
|
||||
setWidthInChars: (widthInChars) ->
|
||||
@component.getDOMNode().style.width = (@model.getDefaultCharWidth() * widthInChars) + 'px'
|
||||
|
||||
setShowIndentGuide: (showIndentGuide) ->
|
||||
deprecate 'This is going away. Use atom.config.set("editor.showIndentGuide", true|false) instead'
|
||||
@component.setShowIndentGuide(showIndentGuide)
|
||||
|
||||
setSoftWrap: (softWrapped) ->
|
||||
deprecate 'Use TextEditor::setSoftWrapped instead. You can get the editor via editorView.getModel()'
|
||||
@model.setSoftWrapped(softWrapped)
|
||||
|
||||
setShowInvisibles: (showInvisibles) ->
|
||||
deprecate 'This is going away. Use atom.config.set("editor.showInvisibles", true|false) instead'
|
||||
@component.setShowInvisibles(showInvisibles)
|
||||
|
||||
getText: ->
|
||||
@model.getText()
|
||||
|
||||
setText: (text) ->
|
||||
@model.setText(text)
|
||||
|
||||
insertText: (text) ->
|
||||
@model.insertText(text)
|
||||
|
||||
isInputEnabled: ->
|
||||
@component.isInputEnabled()
|
||||
|
||||
setInputEnabled: (inputEnabled) ->
|
||||
@component.setInputEnabled(inputEnabled)
|
||||
|
||||
requestDisplayUpdate: ->
|
||||
deprecate('Please remove from your code. ::requestDisplayUpdate no longer does anything')
|
||||
|
||||
updateDisplay: ->
|
||||
deprecate('Please remove from your code. ::updateDisplay no longer does anything')
|
||||
|
||||
resetDisplay: ->
|
||||
deprecate('Please remove from your code. ::resetDisplay no longer does anything')
|
||||
|
||||
redraw: ->
|
||||
deprecate('Please remove from your code. ::redraw no longer does anything')
|
||||
|
||||
setPlaceholderText: (placeholderText) ->
|
||||
deprecate('Use TextEditor::setPlaceholderText instead. eg. editorView.getModel().setPlaceholderText(text)')
|
||||
@model.setPlaceholderText(placeholderText)
|
||||
|
||||
lineElementForScreenRow: (screenRow) ->
|
||||
$(@component.lineNodeForScreenRow(screenRow))
|
||||
@@ -6,7 +6,7 @@ Delegator = require 'delegato'
|
||||
{Model} = require 'theorist'
|
||||
EmitterMixin = require('emissary').Emitter
|
||||
{CompositeDisposable, Emitter} = require 'event-kit'
|
||||
{Point, Range} = require 'text-buffer'
|
||||
{Point, Range} = TextBuffer = require 'text-buffer'
|
||||
LanguageMode = require './language-mode'
|
||||
DisplayBuffer = require './display-buffer'
|
||||
Cursor = require './cursor'
|
||||
@@ -84,6 +84,7 @@ class TextEditor extends Model
|
||||
@cursors = []
|
||||
@selections = []
|
||||
|
||||
buffer ?= new TextBuffer
|
||||
@displayBuffer ?= new DisplayBuffer({buffer, tabLength, softWrapped})
|
||||
@buffer = @displayBuffer.buffer
|
||||
@softTabs = @usesSoftTabs() ? @softTabs ? atom.config.get('editor.softTabs') ? true
|
||||
@@ -134,9 +135,11 @@ class TextEditor extends Model
|
||||
@emitter.emit 'did-change-title', @getTitle()
|
||||
@emit "path-changed"
|
||||
@emitter.emit 'did-change-path', @getPath()
|
||||
@subscribe @buffer.onDidChangeEncoding =>
|
||||
@emitter.emit 'did-change-encoding', @getEncoding()
|
||||
@subscribe @buffer.onDidDestroy => @destroy()
|
||||
|
||||
# TODO: remove these thwne we remove the deprecations. They are old events.
|
||||
# TODO: remove these when we remove the deprecations. They are old events.
|
||||
@subscribe @buffer.onDidStopChanging => @emit "contents-modified"
|
||||
@subscribe @buffer.onDidConflict => @emit "contents-conflicted"
|
||||
@subscribe @buffer.onDidChangeModified => @emit "modified-status-changed"
|
||||
@@ -260,6 +263,14 @@ class TextEditor extends Model
|
||||
onDidChangeSoftWrapped: (callback) ->
|
||||
@displayBuffer.onDidChangeSoftWrapped(callback)
|
||||
|
||||
# Extended: Calls your `callback` when the buffer's encoding has changed.
|
||||
#
|
||||
# * `callback` {Function}
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChangeEncoding: (callback) ->
|
||||
@emitter.on 'did-change-encoding', callback
|
||||
|
||||
# Extended: Calls your `callback` when the grammar that interprets and
|
||||
# colorizes the text has been changed. Immediately calls your callback with
|
||||
# the current grammar.
|
||||
@@ -568,6 +579,16 @@ class TextEditor extends Model
|
||||
# Essential: Returns the {String} path of this editor's text buffer.
|
||||
getPath: -> @buffer.getPath()
|
||||
|
||||
# Extended: Returns the {String} character set encoding of this editor's text
|
||||
# buffer.
|
||||
getEncoding: -> @buffer.getEncoding()
|
||||
|
||||
# Extended: Set the character set encoding to use in this editor's text
|
||||
# buffer.
|
||||
#
|
||||
# * `encoding` The {String} character set encoding name such as 'utf8'
|
||||
setEncoding: (encoding) -> @buffer.setEncoding(encoding)
|
||||
|
||||
# Essential: Returns {Boolean} `true` if this editor has been modified.
|
||||
isModified: -> @buffer.isModified()
|
||||
|
||||
@@ -752,7 +773,7 @@ class TextEditor extends Model
|
||||
@insertText('\n')
|
||||
|
||||
# Essential: For each selection, if the selection is empty, delete the character
|
||||
# preceding the cursor. Otherwise delete the selected text.
|
||||
# following the cursor. Otherwise delete the selected text.
|
||||
delete: ->
|
||||
@mutateSelectedText (selection) -> selection.delete()
|
||||
|
||||
|
||||
+44
-21
@@ -1,41 +1,64 @@
|
||||
isHighSurrogate = (string, index) ->
|
||||
0xD800 <= string.charCodeAt(index) <= 0xDBFF
|
||||
isHighSurrogate = (charCode) ->
|
||||
0xD800 <= charCode <= 0xDBFF
|
||||
|
||||
isLowSurrogate = (string, index) ->
|
||||
0xDC00 <= string.charCodeAt(index) <= 0xDFFF
|
||||
isLowSurrogate = (charCode) ->
|
||||
0xDC00 <= charCode <= 0xDFFF
|
||||
|
||||
isVariationSelector = (string, index) ->
|
||||
0xFE00 <= string.charCodeAt(index) <= 0xFE0F
|
||||
isVariationSelector = (charCode) ->
|
||||
0xFE00 <= charCode <= 0xFE0F
|
||||
|
||||
# Is the character at the given index the start of a high/low surrogate pair?
|
||||
isCombiningCharacter = (charCode) ->
|
||||
0x0300 <= charCode <= 0x036F or
|
||||
0x1AB0 <= charCode <= 0x1AFF or
|
||||
0x1DC0 <= charCode <= 0x1DFF or
|
||||
0x20D0 <= charCode <= 0x20FF or
|
||||
0xFE20 <= charCode <= 0xFE2F
|
||||
|
||||
# Are the given character codes a high/low surrogate pair?
|
||||
#
|
||||
# * `string` The {String} to check for a surrogate pair.
|
||||
# * `index` The {Number} index to look for a surrogate pair at.
|
||||
# * `charCodeA` The first character code {Number}.
|
||||
# * `charCode2` The second character code {Number}.
|
||||
#
|
||||
# Return a {Boolean}.
|
||||
isSurrogatePair = (string, index=0) ->
|
||||
isHighSurrogate(string, index) and isLowSurrogate(string, index + 1)
|
||||
isSurrogatePair = (charCodeA, charCodeB) ->
|
||||
isHighSurrogate(charCodeA) and isLowSurrogate(charCodeB)
|
||||
|
||||
# Is the character at the given index the start of a variation sequence?
|
||||
# Are the given character codes a variation sequence?
|
||||
#
|
||||
# * `string` The {String} to check for a variation sequence.
|
||||
# * `index` The {Number} index to look for a variation sequence at.
|
||||
# * `charCodeA` The first character code {Number}.
|
||||
# * `charCode2` The second character code {Number}.
|
||||
#
|
||||
# Return a {Boolean}.
|
||||
isVariationSequence = (string, index=0) ->
|
||||
not isVariationSelector(string, index) and isVariationSelector(string, index + 1)
|
||||
isVariationSequence = (charCodeA, charCodeB) ->
|
||||
not isVariationSelector(charCodeA) and isVariationSelector(charCodeB)
|
||||
|
||||
# Are the given character codes a combined character pair?
|
||||
#
|
||||
# * `charCodeA` The first character code {Number}.
|
||||
# * `charCode2` The second character code {Number}.
|
||||
#
|
||||
# Return a {Boolean}.
|
||||
isCombinedCharacter = (charCodeA, charCodeB) ->
|
||||
not isCombiningCharacter(charCodeA) and isCombiningCharacter(charCodeB)
|
||||
|
||||
# Is the character at the given index the start of high/low surrogate pair
|
||||
# or a variation sequence?
|
||||
# a variation sequence, or a combined character?
|
||||
#
|
||||
# * `string` The {String} to check for a surrogate pair or variation sequence.
|
||||
# * `index` The {Number} index to look for a surrogate pair at.
|
||||
# * `string` The {String} to check for a surrogate pair, variation sequence,
|
||||
# or combined character.
|
||||
# * `index` The {Number} index to look for a surrogate pair, variation
|
||||
# sequence, or combined character.
|
||||
#
|
||||
# Return a {Boolean}.
|
||||
isPairedCharacter = (string, index=0) ->
|
||||
isSurrogatePair(string, index) or isVariationSequence(string, index)
|
||||
charCodeA = string.charCodeAt(index)
|
||||
charCodeB = string.charCodeAt(index + 1)
|
||||
isSurrogatePair(charCodeA, charCodeB) or
|
||||
isVariationSequence(charCodeA, charCodeB) or
|
||||
isCombinedCharacter(charCodeA, charCodeB)
|
||||
|
||||
# Does the given string contain at least surrogate pair or variation sequence?
|
||||
# Does the given string contain at least surrogate pair, variation sequence,
|
||||
# or combined character?
|
||||
#
|
||||
# * `string` The {String} to check for the presence of paired characters.
|
||||
#
|
||||
|
||||
@@ -159,11 +159,14 @@ class ThemeManager
|
||||
themeNames = atom.config.get('core.themes') ? []
|
||||
themeNames = [themeNames] unless _.isArray(themeNames)
|
||||
themeNames = themeNames.filter (themeName) ->
|
||||
themeName and typeof themeName is 'string'
|
||||
if themeName and typeof themeName is 'string'
|
||||
return true if atom.packages.resolvePackagePath(themeName)
|
||||
console.warn("Enabled theme '#{themeName}' is not installed.")
|
||||
false
|
||||
|
||||
# Use a built-in syntax and UI theme when in safe mode since themes
|
||||
# installed to ~/.atom/packages will not be loaded.
|
||||
if @safeMode
|
||||
# Use a built-in syntax and UI theme any time the configured themes are not
|
||||
# available.
|
||||
if themeNames.length < 2
|
||||
builtInThemeNames = [
|
||||
'atom-dark-syntax'
|
||||
'atom-dark-ui'
|
||||
|
||||
+3
-2
@@ -21,10 +21,10 @@ class Token
|
||||
firstTrailingWhitespaceIndex: null
|
||||
hasInvisibleCharacters: false
|
||||
|
||||
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab}) ->
|
||||
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab, @hasPairedCharacter}) ->
|
||||
@screenDelta = @value.length
|
||||
@bufferDelta ?= @screenDelta
|
||||
@hasPairedCharacter = textUtils.hasPairedCharacter(@value)
|
||||
@hasPairedCharacter ?= textUtils.hasPairedCharacter(@value)
|
||||
|
||||
isEqual: (other) ->
|
||||
# TODO: scopes is deprecated. This is here for the sake of lang package tests
|
||||
@@ -125,6 +125,7 @@ class Token
|
||||
value: value[index..index + 1]
|
||||
scopes: @scopes
|
||||
isAtomic: true
|
||||
hasPairedCharacter: true
|
||||
)
|
||||
|
||||
buildHardTabToken: (tabLength, column) ->
|
||||
|
||||
@@ -29,7 +29,7 @@ class TokenizedBuffer extends Model
|
||||
@subscribe atom.syntax.onDidAddGrammar(@grammarAddedOrUpdated)
|
||||
@subscribe atom.syntax.onDidUpdateGrammar(@grammarAddedOrUpdated)
|
||||
|
||||
@subscribe @buffer.onDidChange (e) => @handleBufferChange(e)
|
||||
@subscribe @buffer.preemptDidChange (e) => @handleBufferChange(e)
|
||||
@subscribe @buffer.onDidChangePath (@bufferPath) => @reloadGrammar()
|
||||
|
||||
@reloadGrammar()
|
||||
|
||||
@@ -1,17 +1,117 @@
|
||||
{Disposable} = require 'event-kit'
|
||||
{jQuery} = require './space-pen-extensions'
|
||||
|
||||
# Essential: `ViewRegistry` handles the association between model and view
|
||||
# types in Atom. We call this association a View Provider. As in, for a given
|
||||
# model, this class can provide a view via {::getView}, as long as the
|
||||
# model/view association was registered via {::addViewProvider}
|
||||
#
|
||||
# If you're adding your own kind of pane item, a good strategy for all but the
|
||||
# simplest items is to separate the model and the view. The model handles
|
||||
# application logic and is the primary point of API interaction. The view
|
||||
# just handles presentation.
|
||||
#
|
||||
# View providers to inform the workspace how your model objects should be
|
||||
# presented in the DOM. A view provider must always return a DOM node, which
|
||||
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
|
||||
# an ideal tool for implementing views in Atom.
|
||||
#
|
||||
# You can access the `ViewRegistry` object via `atom.views`.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting the workspace element
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceElement = atom.views.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# ### Getting An Editor Element
|
||||
#
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorElement = atom.views.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane Element
|
||||
#
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneElement = atom.views.getView(pane)
|
||||
# ```
|
||||
module.exports =
|
||||
class ViewRegistry
|
||||
constructor: ->
|
||||
@views = new WeakMap
|
||||
@providers = []
|
||||
|
||||
# Essential: Add a provider that will be used to construct views in the
|
||||
# workspace's view layer based on model objects in its model layer.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# Text editors are divided into a model and a view layer, so when you interact
|
||||
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
|
||||
# to get the model object. We display text editors on screen by teaching the
|
||||
# workspace what view constructor it should use to represent them:
|
||||
#
|
||||
# ```coffee
|
||||
# atom.views.addViewProvider
|
||||
# modelConstructor: TextEditor
|
||||
# viewConstructor: TextEditorElement
|
||||
# ```
|
||||
#
|
||||
# * `providerSpec` {Object} containing the following keys:
|
||||
# * `modelConstructor` Constructor {Function} for your model.
|
||||
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
|
||||
# should be a subclass of `HTMLElement` (that is, your view should be a
|
||||
# DOM node) and have a `::setModel()` method which will be called
|
||||
# immediately after construction. If you don't supply this property, you
|
||||
# must supply the `createView` property with a function that never returns
|
||||
# `undefined`.
|
||||
# * `createView` (Optional) Factory {Function} that must return a subclass
|
||||
# of `HTMLElement` or `undefined`. If this property is not present or the
|
||||
# function returns `undefined`, the view provider will fall back to the
|
||||
# `viewConstructor` property. If you don't provide this property, you must
|
||||
# provider a `viewConstructor` property.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# added provider.
|
||||
addViewProvider: (providerSpec) ->
|
||||
@providers.push(providerSpec)
|
||||
new Disposable =>
|
||||
@providers = @providers.filter (provider) -> provider isnt providerSpec
|
||||
|
||||
# Essential: Get the view associated with an object in the workspace.
|
||||
#
|
||||
# If you're just *using* the workspace, you shouldn't need to access the view
|
||||
# layer, but view layer access may be necessary if you want to perform DOM
|
||||
# manipulation that isn't supported via the model API.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting An Editor View
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorView = atom.views.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane View
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneView = atom.views.getView(pane)
|
||||
# ```
|
||||
#
|
||||
# ### Getting The Workspace View
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceView = atom.views.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# * `object` The object for which you want to retrieve a view. This can be a
|
||||
# pane item, a pane, or the workspace itself.
|
||||
#
|
||||
# Returns a DOM element.
|
||||
getView: (object) ->
|
||||
return unless object?
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class WorkspaceElement extends HTMLElement
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
@paneContainer = @model.getView(@model.paneContainer)
|
||||
@paneContainer = atom.views.getView(@model.paneContainer)
|
||||
@verticalAxis.appendChild(@paneContainer)
|
||||
|
||||
@addEventListener 'focus', @handleFocus.bind(this)
|
||||
|
||||
@@ -59,7 +59,7 @@ class WorkspaceView extends View
|
||||
|
||||
constructor: (@element) ->
|
||||
unless @element?
|
||||
return atom.workspace.getView(atom.workspace).__spacePenView
|
||||
return atom.views.getView(atom.workspace).__spacePenView
|
||||
super
|
||||
@deprecateViewEvents()
|
||||
|
||||
@@ -262,22 +262,6 @@ class WorkspaceView extends View
|
||||
deprecate('Use Workspace::onDidOpen instead')
|
||||
originalWorkspaceViewOn.apply(this, arguments)
|
||||
|
||||
TextEditorView = require './text-editor-view'
|
||||
originalEditorViewOn = TextEditorView::on
|
||||
TextEditorView::on = (eventName) ->
|
||||
switch eventName
|
||||
when 'cursor:moved'
|
||||
deprecate('Use TextEditor::onDidChangeCursorPosition instead')
|
||||
when 'editor:attached'
|
||||
deprecate('Use TextEditor::onDidAddTextEditor instead')
|
||||
when 'editor:detached'
|
||||
deprecate('Use TextEditor::onDidDestroy instead')
|
||||
when 'editor:will-be-removed'
|
||||
deprecate('Use TextEditor::onDidDestroy instead')
|
||||
when 'selection:changed'
|
||||
deprecate('Use TextEditor::onDidChangeSelectionRange instead')
|
||||
originalEditorViewOn.apply(this, arguments)
|
||||
|
||||
originalPaneViewOn = PaneView::on
|
||||
PaneView::on = (eventName) ->
|
||||
switch eventName
|
||||
|
||||
+19
-102
@@ -45,15 +45,15 @@ class Workspace extends Model
|
||||
@emitter = new Emitter
|
||||
@openers = []
|
||||
|
||||
@viewRegistry ?= new ViewRegistry
|
||||
@paneContainer ?= new PaneContainer({@viewRegistry})
|
||||
viewRegistry = atom.views
|
||||
@paneContainer ?= new PaneContainer({viewRegistry})
|
||||
@paneContainer.onDidDestroyPaneItem(@onPaneItemDestroyed)
|
||||
|
||||
@panelContainers =
|
||||
top: new PanelContainer({@viewRegistry, location: 'top'})
|
||||
left: new PanelContainer({@viewRegistry, location: 'left'})
|
||||
right: new PanelContainer({@viewRegistry, location: 'right'})
|
||||
bottom: new PanelContainer({@viewRegistry, location: 'bottom'})
|
||||
top: new PanelContainer({viewRegistry, location: 'top'})
|
||||
left: new PanelContainer({viewRegistry, location: 'left'})
|
||||
right: new PanelContainer({viewRegistry, location: 'right'})
|
||||
bottom: new PanelContainer({viewRegistry, location: 'bottom'})
|
||||
|
||||
@subscribeToActiveItem()
|
||||
|
||||
@@ -68,15 +68,15 @@ class Workspace extends Model
|
||||
when 'atom://.atom/init-script'
|
||||
@open(atom.getUserInitScriptPath())
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: Workspace
|
||||
viewConstructor: WorkspaceElement
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: PanelContainer
|
||||
viewConstructor: PanelContainerElement
|
||||
|
||||
@addViewProvider
|
||||
atom.views.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
|
||||
@@ -85,8 +85,7 @@ class Workspace extends Model
|
||||
for packageName in params.packagesWithActiveGrammars ? []
|
||||
atom.packages.getLoadedPackage(packageName)?.loadGrammarsSync()
|
||||
|
||||
params.viewRegistry = new ViewRegistry
|
||||
params.paneContainer.viewRegistry = params.viewRegistry
|
||||
params.paneContainer.viewRegistry = atom.views
|
||||
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
|
||||
params
|
||||
|
||||
@@ -605,8 +604,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -620,8 +619,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -635,8 +634,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -650,8 +649,8 @@ class Workspace extends Model
|
||||
#
|
||||
# * `options` {Object}
|
||||
# * `item` Your panel content. It can be DOM element, a jQuery element, or
|
||||
# a model with a view registered via {::addViewProvider}. We recommend the
|
||||
# latter. See {::addViewProvider} for more information.
|
||||
# a model with a view registered via {ViewRegistry::addViewProvider}. We recommend the
|
||||
# latter. See {ViewRegistry::addViewProvider} for more information.
|
||||
# * `visible` (optional) {Boolean} false if you want the panel to initially be hidden
|
||||
# (default: true)
|
||||
# * `priority` (optional) {Number} Determines stacking order. Lower priority items are
|
||||
@@ -663,87 +662,5 @@ class Workspace extends Model
|
||||
|
||||
addPanel: (location, options) ->
|
||||
options ?= {}
|
||||
options.viewRegistry = @viewRegistry
|
||||
options.viewRegistry = atom.views
|
||||
@panelContainers[location].addPanel(new Panel(options))
|
||||
|
||||
###
|
||||
Section: View Management
|
||||
###
|
||||
|
||||
# Essential: Get the view associated with an object in the workspace.
|
||||
#
|
||||
# If you're just *using* the workspace, you shouldn't need to access the view
|
||||
# layer, but view layer access may be necessary if you want to perform DOM
|
||||
# manipulation that isn't supported via the model API.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# ### Getting An Editor View
|
||||
# ```coffee
|
||||
# textEditor = atom.workspace.getActiveTextEditor()
|
||||
# textEditorView = atom.workspace.getView(textEditor)
|
||||
# ```
|
||||
#
|
||||
# ### Getting A Pane View
|
||||
# ```coffee
|
||||
# pane = atom.workspace.getActivePane()
|
||||
# paneView = atom.workspace.getView(pane)
|
||||
# ```
|
||||
#
|
||||
# ### Getting The Workspace View
|
||||
#
|
||||
# ```coffee
|
||||
# workspaceView = atom.workspace.getView(atom.workspace)
|
||||
# ```
|
||||
#
|
||||
# * `object` The object for which you want to retrieve a view. This can be a
|
||||
# pane item, a pane, or the workspace itself.
|
||||
#
|
||||
# Returns a DOM element.
|
||||
getView: (object) ->
|
||||
@viewRegistry.getView(object)
|
||||
|
||||
# Essential: Add a provider that will be used to construct views in the
|
||||
# workspace's view layer based on model objects in its model layer.
|
||||
#
|
||||
# If you're adding your own kind of pane item, a good strategy for all but the
|
||||
# simplest items is to separate the model and the view. The model handles
|
||||
# application logic and is the primary point of API interaction. The view
|
||||
# just handles presentation.
|
||||
#
|
||||
# Use view providers to inform the workspace how your model objects should be
|
||||
# presented in the DOM. A view provider must always return a DOM node, which
|
||||
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
|
||||
# an ideal tool for implementing views in Atom.
|
||||
#
|
||||
# ## Examples
|
||||
#
|
||||
# Text editors are divided into a model and a view layer, so when you interact
|
||||
# with methods like `atom.workspace.getActiveTextEditor()` you're only going
|
||||
# to get the model object. We display text editors on screen by teaching the
|
||||
# workspace what view constructor it should use to represent them:
|
||||
#
|
||||
# ```coffee
|
||||
# atom.workspace.addViewProvider
|
||||
# modelConstructor: TextEditor
|
||||
# viewConstructor: TextEditorElement
|
||||
# ```
|
||||
#
|
||||
# * `providerSpec` {Object} containing the following keys:
|
||||
# * `modelConstructor` Constructor {Function} for your model.
|
||||
# * `viewConstructor` (Optional) Constructor {Function} for your view. It
|
||||
# should be a subclass of `HTMLElement` (that is, your view should be a
|
||||
# DOM node) and have a `::setModel()` method which will be called
|
||||
# immediately after construction. If you don't supply this property, you
|
||||
# must supply the `createView` property with a function that never returns
|
||||
# `undefined`.
|
||||
# * `createView` (Optional) Factory {Function} that must return a subclass
|
||||
# of `HTMLElement` or `undefined`. If this property is not present or the
|
||||
# function returns `undefined`, the view provider will fall back to the
|
||||
# `viewConstructor` property. If you don't provide this property, you must
|
||||
# provider a `viewConstructor` property.
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to remove the
|
||||
# added provider.
|
||||
addViewProvider: (providerSpec) ->
|
||||
@viewRegistry.addViewProvider(providerSpec)
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
@import "messages";
|
||||
@import "markdown";
|
||||
@import "editor";
|
||||
@import "select-list";
|
||||
@import "syntax";
|
||||
@import "utilities";
|
||||
@import "octicons";
|
||||
|
||||
+9
-2
@@ -2,11 +2,18 @@ window.onload = function() {
|
||||
try {
|
||||
var startTime = Date.now();
|
||||
|
||||
var path = require('path');
|
||||
|
||||
// Skip "?loadSettings=".
|
||||
var loadSettings = JSON.parse(decodeURIComponent(location.search.substr(14)));
|
||||
|
||||
// Normalize to make sure drive letter case is consistent on Windows
|
||||
process.resourcesPath = path.normalize(process.resourcesPath);
|
||||
|
||||
var devMode = loadSettings.devMode || !loadSettings.resourcePath.startsWith(process.resourcesPath + path.sep);
|
||||
|
||||
// Require before the module cache in dev mode
|
||||
if (loadSettings.devMode) {
|
||||
if (devMode) {
|
||||
require('coffee-script').register();
|
||||
}
|
||||
|
||||
@@ -25,7 +32,7 @@ window.onload = function() {
|
||||
|
||||
require('vm-compatibility-layer');
|
||||
|
||||
if (!loadSettings.devMode) {
|
||||
if (!devMode) {
|
||||
require('coffee-script').register();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
@import "ui-variables";
|
||||
@import "octicon-mixins";
|
||||
|
||||
.select-list {
|
||||
.loading {
|
||||
.loading-message {
|
||||
.octicon(hourglass);
|
||||
|
||||
&:before {
|
||||
font-size: 1.1em;
|
||||
width: 1.1em;
|
||||
height: 1.1em;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.badge {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
ol.list-group {
|
||||
position: relative;
|
||||
overflow-y: auto;
|
||||
max-height: 312px;
|
||||
margin: @component-padding 0 0 0;
|
||||
padding: 0;
|
||||
|
||||
li {
|
||||
display: block;
|
||||
|
||||
.primary-line,
|
||||
.secondary-line {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
externo
+1
-1
@@ -141,7 +141,7 @@ jasmine.JQuery.matchersClass = {};
|
||||
if (this.actual instanceof HTMLElement) {
|
||||
this.actual = jQuery(this.actual);
|
||||
}
|
||||
if (this.actual instanceof jQuery) {
|
||||
if (this.actual instanceof jQuery || this.actual && this.actual.jquery) {
|
||||
var result = jQueryMatchers[methodName].apply(this, arguments);
|
||||
this.actual = jasmine.JQuery.elementToString(this.actual);
|
||||
return result;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário