Comparar commits
441 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 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 | |||
| dfc0df42b2 | |||
| 452c78b735 | |||
| 42f67033cc | |||
| 5c417cf9cc | |||
| 81143af4b4 | |||
| 5c048a4f13 | |||
| 2ac9cc9ed1 | |||
| e8f8ead53f | |||
| f3d8c5d7ec | |||
| 7d179ef40f | |||
| 375b8efc22 | |||
| 086a011a63 | |||
| 46ff52b13a | |||
| 0ed4d07c33 | |||
| efe3d65291 | |||
| 8576486d06 | |||
| e5abca138d | |||
| fa24154e24 | |||
| 45c05d3b7d | |||
| bf4ac1d3eb | |||
| 892cdae622 | |||
| f33d7ba27f | |||
| 06436ef530 | |||
| 815244bba0 | |||
| 0303ebb5e5 | |||
| eab791d47e | |||
| 6ad96d98b8 | |||
| ed4ebefdc1 | |||
| a1828fa3a6 | |||
| 345c0f670c | |||
| d78e6fa711 | |||
| c3a6475308 | |||
| 2cc9f6bee8 | |||
| 0c6fba2ce2 | |||
| fa72db87a2 | |||
| a0d7bbdb92 | |||
| 4c3e1ef82b | |||
| 1056418f97 | |||
| 37040ad485 | |||
| dee9cccae7 | |||
| 50e27854cc | |||
| c931071c91 | |||
| 498c8d21b2 | |||
| 263b792eee | |||
| ffd3990a6b | |||
| 31490ca31e | |||
| 37159bb478 | |||
| 16ad957609 | |||
| 137eeab4cf | |||
| ce2076f30a | |||
| 8479d564f5 | |||
| ec6004615a | |||
| 7e7441dc23 | |||
| 2a09d25eb1 | |||
| d5508b338b | |||
| 86bd43bf73 | |||
| 3075b74b64 | |||
| 11d7437ecc | |||
| df439f5ada | |||
| dc28ddbdc8 | |||
| 49e98d368a | |||
| 02e91aa4cd | |||
| 14c8e9cedc | |||
| 4867e3ef14 | |||
| 3a70b98ae1 | |||
| 08f35531ba | |||
| ce2959c0b9 | |||
| 4c4b82fe6c | |||
| f4c3050050 | |||
| 2b148b7720 | |||
| c40dd16466 | |||
| 7ffe5d1385 | |||
| c2ef68a435 | |||
| aa117774b3 | |||
| 6b44369458 | |||
| 177b3a6d14 | |||
| 4d1e488ef4 | |||
| 0a39c28a79 | |||
| e019347ca4 | |||
| b425df1d58 | |||
| 055c632ee9 | |||
| 2ac1862e5f | |||
| 5a82afd333 | |||
| 13f81a452d | |||
| c8144b7e1b | |||
| b3b78fa926 | |||
| 824c00dab3 | |||
| 8d331e94d2 | |||
| bc2dd9f52c | |||
| 5dd9f9c5ad | |||
| 3f1afec15b | |||
| e4705d45c4 | |||
| c0846ab8a6 | |||
| bfbb262844 | |||
| 5669aa39ce | |||
| d1f9133ef4 | |||
| 362c9c8588 | |||
| c63cde1cd3 | |||
| 6d937831b9 | |||
| 0eacbed162 | |||
| 6e034c6319 | |||
| a4f6c674ef | |||
| 405af7fb16 | |||
| 995e89b5f6 | |||
| 6b90b83867 | |||
| 66d469ee10 | |||
| 657cbc9c17 | |||
| 29ea506f93 | |||
| 155d144788 | |||
| 892f341feb | |||
| d5808b5c85 | |||
| d6feb686c1 | |||
| 5069a5b48b | |||
| 8c136b18c2 | |||
| f81bc4b870 | |||
| 111b956f93 | |||
| 88a95ad06b | |||
| 04bd602c23 | |||
| de78e53b35 | |||
| fb1a866447 | |||
| 8925d309b0 | |||
| b94485eafd | |||
| a83acd0e8a | |||
| 4e2c500b64 | |||
| 03f863d558 | |||
| b8ad484db0 | |||
| f0fd7c2682 | |||
| 3f170a8b5e | |||
| 37a7cfaf9a | |||
| 5683491029 | |||
| 4ca630a7da | |||
| 99aedbab89 | |||
| 52c05eade7 | |||
| 1ddb956a94 | |||
| 2570c20da0 | |||
| 299710f08a | |||
| 83e5873f3b | |||
| 4889e03cf2 | |||
| 7f6cc8a100 | |||
| e8e0ee1e34 | |||
| 8e3d8eda31 | |||
| afd1fa995f | |||
| a03c9b6d68 | |||
| cdd31d69a8 | |||
| f94983d4d9 | |||
| ffa528001c | |||
| 305b9bc030 | |||
| 6ed3ef3f60 | |||
| 5c2e55861c | |||
| c0843d467d | |||
| 734a79b7ec | |||
| 55a5e66701 | |||
| da86c86577 | |||
| 072c537b6b | |||
| 1577a28ad4 | |||
| ee23131688 | |||
| 7d8b5bc1fc | |||
| 0243597ee8 | |||
| 50a5609c6b | |||
| e76ea838e1 | |||
| ed5c011963 | |||
| 0bc1407e7d | |||
| 7aa00f3417 | |||
| 06e9dbf48a | |||
| ff5acb6a34 | |||
| 231295cb2c | |||
| c8a18dfaf8 | |||
| b339baa923 | |||
| 92d08b47ad | |||
| 5c3a7a99fc | |||
| ea932a01f9 | |||
| d261df0906 | |||
| fac167379f | |||
| f6d9af8d1a | |||
| a128cf5eb3 | |||
| e9c2ee9675 | |||
| e85d33b2a6 | |||
| a42b3ff171 | |||
| 86fdbfbb15 | |||
| 757abfe3db | |||
| cde7940e40 | |||
| d7d6e506da | |||
| 593fc1e77a | |||
| ae857203fd | |||
| a1c418e995 | |||
| f07f096f56 | |||
| 62c1972c95 | |||
| 314c525d2d | |||
| 04b3eef768 | |||
| 506753a535 | |||
| a8b9e1b790 | |||
| be51ccf786 | |||
| 65e077abd1 | |||
| 79598aaae9 | |||
| 62a43c6fb9 | |||
| 1fe1147901 | |||
| 1c97dcd195 | |||
| d3371dbcd2 | |||
| b2b4860983 | |||
| 57fc3deaed | |||
| 677949d61c | |||
| e09d7159bc | |||
| e02af51a04 | |||
| d2c7a2caca | |||
| 739a629552 | |||
| 88f0183352 | |||
| 7f01a163e5 | |||
| fc44662ba3 | |||
| 5052aaca95 | |||
| 826681b6c2 | |||
| 8334bba484 | |||
| a0ae526017 | |||
| 6a6c7b1852 | |||
| 42040f8a9d | |||
| 9d1db0f3de | |||
| f0b922f643 | |||
| bb92b8697d | |||
| 4c17c9eae6 | |||
| 289f17b119 | |||
| dfd7bcae7f | |||
| 0cfd37acd0 | |||
| 105fc302ea | |||
| f4ddc05b9c | |||
| 948f96dd6f | |||
| db627f5cde | |||
| a6866656b7 | |||
| 40c5289e2b | |||
| 7dffc58c5b | |||
| 67d430d100 | |||
| d745b9ef5f | |||
| b9d89cbf5d | |||
| 934c0720d8 | |||
| 06ac206707 | |||
| 6e1bdbbed7 | |||
| 3e3de50eb3 | |||
| d7a8dfb209 | |||
| b0aea54544 | |||
| 41598af2b2 | |||
| f495db41e7 | |||
| 76187f176c | |||
| d7cb1550bf | |||
| 086be13ac4 | |||
| f0cffcbd84 | |||
| d1f3d7d51e | |||
| bdc0341eb3 | |||
| 171411823f | |||
| 7926531330 | |||
| 440866d79e | |||
| d9c758b940 | |||
| 827a8ba107 | |||
| 65a1fafaf7 | |||
| 9bd6891ac2 | |||
| 8a0755340f | |||
| bdebe575b7 | |||
| 472a48092d | |||
| d877872c71 | |||
| 0a297d7642 | |||
| 87d2026e63 | |||
| 20f6489232 | |||
| 2c737b8927 | |||
| 0df5045edb | |||
| b91c25186f | |||
| 7b8a293f30 | |||
| 26df31aa1f | |||
| 36ff22e30a | |||
| 93c5b4be7b | |||
| 495fa43753 | |||
| 2954aacb1c | |||
| 1bf8f516c3 | |||
| e0a84232c3 | |||
| 8c204bb60e | |||
| 245c77869f | |||
| 508a30efb1 | |||
| 5ad54bbe92 | |||
| 4da6513fb5 | |||
| 1154490a97 | |||
| 0e7e24ca6b | |||
| 944ac14be7 | |||
| 7aa28920cf | |||
| 6ce6553456 | |||
| b4470a14cb | |||
| 5b629e6b29 | |||
| 7304b97547 | |||
| f523c5eb73 | |||
| 5981cfb8c9 | |||
| d1e966349f | |||
| dc19fa4baa | |||
| 84e90d140f | |||
| ea557ab109 | |||
| 503393122f | |||
| b5c6d76999 | |||
| 6c56f2f985 | |||
| a4b959f2b8 | |||
| c59b7f6ead | |||
| 38a6f52ef7 | |||
| 33e2829697 |
+10
-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
|
||||
|
||||
@@ -62,6 +64,8 @@ For more information on how to work with Atom's official packages, see
|
||||
* Use `path.join()` to concatenate filenames.
|
||||
* Use `os.tmpdir()` rather than `/tmp` when you need to reference the
|
||||
temporary directory.
|
||||
* Using a plain `return` when returning explicitly at the end of a function.
|
||||
* Not `return null`, `return undefined`, `null`, or `undefined`
|
||||
|
||||
## Git Commit Messages
|
||||
|
||||
@@ -97,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.102.0"
|
||||
"atom-package-manager": "0.109.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -7,7 +7,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"async": "~0.2.9",
|
||||
"donna": "1.0.1",
|
||||
"donna": "1.0.6",
|
||||
"formidable": "~1.0.14",
|
||||
"fs-plus": "2.x",
|
||||
"github-releases": "~0.2.0",
|
||||
@@ -18,7 +18,7 @@
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"grunt-cson": "0.10.0",
|
||||
"grunt-download-atom-shell": "~0.8.0",
|
||||
"grunt-download-atom-shell": "~0.10.0",
|
||||
"grunt-lesslint": "0.13.0",
|
||||
"grunt-markdown": "~0.4.0",
|
||||
"grunt-peg": "~1.1.0",
|
||||
|
||||
@@ -153,7 +153,7 @@ module.exports = (grunt) ->
|
||||
fs.writeFileSync path.join(appDir, 'node_modules', 'symbols-view', 'vendor', 'ctags-win32.exe.ignore'), ''
|
||||
fs.writeFileSync path.join(shellAppDir, 'atom.exe.gui'), ''
|
||||
|
||||
dependencies = ['compile', "generate-license:save"]
|
||||
dependencies = ['compile', 'generate-license:save', 'generate-module-cache', 'compile-packages-slug']
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
dependencies.push('set-exe-icon') if process.platform is 'win32'
|
||||
grunt.task.run(dependencies...)
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
path = require 'path'
|
||||
CSON = require 'season'
|
||||
fs = require 'fs-plus'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{spawn, rm} = require('./task-helpers')(grunt)
|
||||
|
||||
grunt.registerTask 'compile-packages-slug', 'Add bundled package metadata information to the main package.json file', ->
|
||||
appDir = fs.realpathSync(grunt.config.get('atom.appDir'))
|
||||
|
||||
modulesDirectory = path.join(appDir, 'node_modules')
|
||||
packages = {}
|
||||
|
||||
for moduleDirectory in fs.listSync(modulesDirectory)
|
||||
continue if path.basename(moduleDirectory) is '.bin'
|
||||
|
||||
metadataPath = path.join(moduleDirectory, 'package.json')
|
||||
metadata = grunt.file.readJSON(metadataPath)
|
||||
continue unless metadata?.engines?.atom?
|
||||
|
||||
moduleCache = metadata._atomModuleCache ? {}
|
||||
|
||||
rm metadataPath
|
||||
_.remove(moduleCache.extensions?['.json'] ? [], 'package.json')
|
||||
|
||||
for property in ['_from', '_id', 'dist', 'readme', 'readmeFilename']
|
||||
delete metadata[property]
|
||||
|
||||
pack = {metadata, keymaps: {}, menus: {}}
|
||||
|
||||
if metadata.main
|
||||
mainPath = require.resolve(path.resolve(moduleDirectory, metadata.main))
|
||||
pack.main = path.relative(appDir, mainPath)
|
||||
|
||||
for keymapPath in fs.listSync(path.join(moduleDirectory, 'keymaps'), ['.cson', '.json'])
|
||||
relativePath = path.relative(appDir, keymapPath)
|
||||
pack.keymaps[relativePath] = CSON.readFileSync(keymapPath)
|
||||
rm keymapPath
|
||||
|
||||
for menuPath in fs.listSync(path.join(moduleDirectory, 'menus'), ['.cson', '.json'])
|
||||
relativePath = path.relative(appDir, menuPath)
|
||||
pack.menus[relativePath] = CSON.readFileSync(menuPath)
|
||||
rm menuPath
|
||||
|
||||
packages[metadata.name] = pack
|
||||
|
||||
for extension, paths of moduleCache.extensions
|
||||
delete moduleCache.extensions[extension] if paths.length is 0
|
||||
|
||||
metadata = grunt.file.readJSON(path.join(appDir, 'package.json'))
|
||||
metadata._atomPackages = packages
|
||||
|
||||
grunt.file.write(path.join(appDir, 'package.json'), JSON.stringify(metadata))
|
||||
@@ -0,0 +1,39 @@
|
||||
path = require 'path'
|
||||
fs = require 'fs-plus'
|
||||
ModuleCache = require '../../src/module-cache'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
grunt.registerTask 'generate-module-cache', 'Generate a module cache for all core modules and packages', ->
|
||||
appDir = grunt.config.get('atom.appDir')
|
||||
|
||||
{packageDependencies} = grunt.file.readJSON('package.json')
|
||||
|
||||
for packageName, version of packageDependencies
|
||||
ModuleCache.create(path.join(appDir, 'node_modules', packageName))
|
||||
|
||||
ModuleCache.create(appDir)
|
||||
|
||||
metadata = grunt.file.readJSON(path.join(appDir, 'package.json'))
|
||||
|
||||
metadata._atomModuleCache.folders.forEach (folder) ->
|
||||
if '' in folder.paths
|
||||
folder.paths = [
|
||||
''
|
||||
'exports'
|
||||
'spec'
|
||||
'src'
|
||||
'src/browser'
|
||||
'static'
|
||||
'vendor'
|
||||
]
|
||||
|
||||
# Reactionary does not have an explicit react dependency
|
||||
metadata._atomModuleCache.folders.push
|
||||
paths: [
|
||||
'node_modules/reactionary-atom-fork/lib'
|
||||
]
|
||||
dependencies: {
|
||||
'react-atom-fork': metadata.dependencies['react-atom-fork']
|
||||
}
|
||||
|
||||
grunt.file.write(path.join(appDir, 'package.json'), JSON.stringify(metadata))
|
||||
@@ -32,7 +32,7 @@ module.exports = (grunt) ->
|
||||
binDir = path.join(installDir, 'bin')
|
||||
shareDir = path.join(installDir, 'share', 'atom')
|
||||
|
||||
iconName = path.join(shareDir,'resources','app','resources','atom.png')
|
||||
iconName = path.join(shareDir,'resources', 'app', 'resources', 'atom.png')
|
||||
|
||||
mkdir binDir
|
||||
cp 'atom.sh', path.join(binDir, 'atom')
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{spawn, rm, mkdir} = require('./task-helpers')(grunt)
|
||||
|
||||
fillTemplate = (filePath, data) ->
|
||||
template = _.template(String(fs.readFileSync("#{filePath}.in")))
|
||||
filled = template(data)
|
||||
|
||||
outputPath = path.join(grunt.config.get('atom.buildDir'), path.basename(filePath))
|
||||
grunt.file.write(outputPath, filled)
|
||||
outputPath
|
||||
|
||||
grunt.registerTask 'mkrpm', 'Create rpm package', ->
|
||||
done = @async()
|
||||
|
||||
if process.arch is 'ia32'
|
||||
arch = 'i386'
|
||||
else if process.arch is 'x64'
|
||||
arch = 'amd64'
|
||||
else
|
||||
return done("Unsupported arch #{process.arch}")
|
||||
|
||||
{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')
|
||||
|
||||
data = {name, version, description, installDir, iconName}
|
||||
specFilePath = fillTemplate(path.join('resources', 'linux', 'redhat', 'atom.spec'), data)
|
||||
desktopFilePath = fillTemplate(path.join('resources', 'linux', 'atom.desktop'), data)
|
||||
|
||||
cmd = path.join('script', 'mkrpm')
|
||||
args = [specFilePath, desktopFilePath, buildDir]
|
||||
spawn {cmd, args}, (error) ->
|
||||
if error?
|
||||
done(error)
|
||||
else
|
||||
grunt.log.ok "Created rpm package in #{rpmDir}"
|
||||
done()
|
||||
@@ -20,9 +20,9 @@ module.exports = (gruntObject) ->
|
||||
{cp} = require('./task-helpers')(grunt)
|
||||
|
||||
grunt.registerTask 'publish-build', 'Publish the built app', ->
|
||||
return if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH isnt 'master'
|
||||
tasks = ['upload-assets']
|
||||
tasks.unshift('build-docs', 'prepare-docs') if process.platform is 'darwin'
|
||||
tasks = []
|
||||
tasks.push('build-docs', 'prepare-docs') if process.platform is 'darwin'
|
||||
tasks.push('upload-assets') if process.env.JANKY_SHA1 and process.env.JANKY_BRANCH is 'master'
|
||||
grunt.task.run(tasks)
|
||||
|
||||
grunt.registerTask 'prepare-docs', 'Move api.json to atom-api.json', ->
|
||||
@@ -31,7 +31,16 @@ module.exports = (gruntObject) ->
|
||||
cp path.join(docsOutputDir, 'api.json'), path.join(buildDir, 'atom-api.json')
|
||||
|
||||
grunt.registerTask 'upload-assets', 'Upload the assets to a GitHub release', ->
|
||||
done = @async()
|
||||
doneCallback = @async()
|
||||
startTime = Date.now()
|
||||
done = (args...) ->
|
||||
elapsedTime = Math.round((Date.now() - startTime) / 100) / 10
|
||||
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()
|
||||
|
||||
@@ -63,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)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ module.exports = (grunt) ->
|
||||
packageJsonPath = path.join(appDir, 'package.json')
|
||||
packageJson = require(packageJsonPath)
|
||||
packageJson.version = version
|
||||
packageJsonString = JSON.stringify(packageJson, null, 2)
|
||||
packageJsonString = JSON.stringify(packageJson)
|
||||
fs.writeFileSync(packageJsonPath, packageJsonString)
|
||||
|
||||
if process.platform is 'darwin'
|
||||
|
||||
@@ -4,6 +4,8 @@ path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
async = require 'async'
|
||||
|
||||
concurrency = 2
|
||||
|
||||
module.exports = (grunt) ->
|
||||
{isAtomPackage, spawn} = require('./task-helpers')(grunt)
|
||||
|
||||
@@ -61,7 +63,7 @@ module.exports = (grunt) ->
|
||||
continue unless isAtomPackage(packagePath)
|
||||
packageSpecQueue.push(packagePath)
|
||||
|
||||
packageSpecQueue.concurrency = 1
|
||||
packageSpecQueue.concurrency = concurrency - 1
|
||||
packageSpecQueue.drain = -> callback(null, failedPackages)
|
||||
|
||||
runCoreSpecs = (callback) ->
|
||||
@@ -84,7 +86,7 @@ module.exports = (grunt) ->
|
||||
fs.unlinkSync('ci.log')
|
||||
else
|
||||
# TODO: Restore concurrency on Windows
|
||||
packageSpecQueue.concurrency = 2
|
||||
packageSpecQueue.concurrency = concurrency
|
||||
|
||||
callback(null, error)
|
||||
|
||||
@@ -102,7 +104,7 @@ module.exports = (grunt) ->
|
||||
method [runCoreSpecs, runPackageSpecs], (error, results) ->
|
||||
[coreSpecFailed, failedPackages] = results
|
||||
elapsedTime = Math.round((Date.now() - startTime) / 100) / 10
|
||||
grunt.verbose.writeln("Total spec time: #{elapsedTime}s")
|
||||
grunt.log.ok("Total spec time: #{elapsedTime}s using #{concurrency} cores")
|
||||
failures = failedPackages
|
||||
failures.push "atom core" if coreSpecFailed
|
||||
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
# Scoped Settings, Scopes and Scope Descriptors
|
||||
|
||||
Atom supports language-specific settings. You can soft wrap only Markdown files, or set the tab length to 4 in Python files.
|
||||
|
||||
Language-specific settings are a subset of something more general we call "scoped settings". Scoped settings allow targeting down to a specific syntax token type. For example, you could conceivably set a setting to target only Ruby comments, only code inside Markdown files, or even only JavaScript function names.
|
||||
|
||||
## Scope names in syntax tokens
|
||||
|
||||
Each token in the editor has a collection of scope names. For example, the aformentioned JavaScript function name might have the scope names `function` and `name`. An open paren might have the scope names `punctuation`, `parameters`, `begin`.
|
||||
|
||||
Scope names work just like CSS classes. In fact, in the editor, scope names are attached to a token's DOM node as CSS classes.
|
||||
|
||||
Take this piece of JavaScript:
|
||||
|
||||
```js
|
||||
function functionName() {
|
||||
console.log('Log it out');
|
||||
}
|
||||
```
|
||||
|
||||
In the dev tools, the first line's markup looks like this.
|
||||
|
||||

|
||||
|
||||
All the class names on the spans are scope names. Any scope name can be used to target a setting's value.
|
||||
|
||||
## Scope Selectors
|
||||
|
||||
Scope selectors allow you to target specific tokens just like a CSS selector targets specific nodes in the DOM. Some examples:
|
||||
|
||||
```coffee
|
||||
'.source.js' # selects all javascript tokens
|
||||
'.source.js .function.name' # selects all javascript function names
|
||||
'.function.name' # selects all function names in any language
|
||||
```
|
||||
|
||||
[Config::set][config-set] accepts a `scopeSelector`. If you'd like to set a setting for JavaScript function names, you can give it the js function name `scopeSelector`:
|
||||
|
||||
```coffee
|
||||
atom.config.set('.source.js .function.name', 'my-package.my-setting', 'special value')
|
||||
```
|
||||
|
||||
## Scope Descriptors
|
||||
|
||||
A scope descriptor is an [Object][scope-descriptor] that wraps an `Array` of
|
||||
`String`s. The Array describes a path from the root of the syntax tree to a
|
||||
token including _all_ scope names for the entire path.
|
||||
|
||||
In our JavaScript example above, a scope descriptor for the function name token would be:
|
||||
|
||||
```coffee
|
||||
['source.js', 'meta.function.js', 'entity.name.function.js']
|
||||
```
|
||||
|
||||
[Config::get][config-get] accepts a `scopeDescriptor`. You can get the value for your setting scoped to JavaScript function names via:
|
||||
|
||||
```coffee
|
||||
scopeDescriptor = ['source.js', 'meta.function.js', 'entity.name.function.js']
|
||||
value = atom.config.get(scopeDescriptor, 'my-package.my-setting')
|
||||
```
|
||||
|
||||
But, you do not need to generate scope descriptors by hand. There are a couple methods available to get the scope descriptor from the editor:
|
||||
|
||||
* [Editor::getRootScopeDescriptor][editor-getRootScopeDescriptor] to get the language's descriptor. eg. `[".source.js"]`
|
||||
* [Editor::scopeDescriptorForBufferPosition][editor-scopeDescriptorForBufferPosition] to get the descriptor at a specific position in the buffer.
|
||||
* [Cursor::getScopeDescriptor][cursor-getScopeDescriptor] to get a cursor's descriptor based on position. eg. if the cursor were in the name of the method in our example it would return `["source.js", "meta.function.js", "entity.name.function.js"]`
|
||||
|
||||
Let's revisit our example using these methods:
|
||||
|
||||
```coffee
|
||||
editor = atom.workspace.getActiveTextEditor()
|
||||
cursor = editor.getLastCursor()
|
||||
valueAtCursor = atom.config.get(cursor.getScopeDescriptor(), 'my-package.my-setting')
|
||||
valueForLanguage = atom.config.get(editor.getRootScopeDescriptor(), 'my-package.my-setting')
|
||||
```
|
||||
|
||||
|
||||
[config]:https://atom.io/docs/api/latest/Config
|
||||
[config-get]:https://atom.io/docs/api/latest/Config#instance-get
|
||||
[config-set]:https://atom.io/docs/api/latest/Config#instance-set
|
||||
[config-observe]:https://atom.io/docs/api/latest/Config#instance-observe
|
||||
|
||||
[editor-getRootScopeDescriptor]:https://atom.io/docs/api/latest/TextEditor#instance-getRootScopeDescriptor
|
||||
[editor-scopeDescriptorForBufferPosition]:https://atom.io/docs/api/latest/TextEditor#instance-scopeDescriptorForBufferPosition
|
||||
|
||||
[cursor-getScopeDescriptor]:https://atom.io/docs/api/latest/Cursor#instance-getScopeDescriptor
|
||||
[scope-descriptor]:https://atom.io/docs/api/latest/ScopeDescriptor
|
||||
@@ -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`:
|
||||
|
||||
|
||||
@@ -9,22 +9,27 @@ in the proper package's repository.
|
||||
|
||||
### Cloning
|
||||
|
||||
The first step is creating your own clone. You can of course do this manually
|
||||
with git, or you can use the `apm develop` command to create a clone based on
|
||||
the package's `repository` field in the `package.json`.
|
||||
The first step is creating your own clone.
|
||||
|
||||
For example, if you want to make changes to the `tree-view` package, run the
|
||||
following command:
|
||||
For example, if you want to make changes to the `tree-view` package, fork the repo on your github account, then clone it:
|
||||
|
||||
```
|
||||
> apm develop tree-view
|
||||
Cloning https://github.com/atom/tree-view ✓
|
||||
> git clone git@github.com:your-username/tree-view.git
|
||||
```
|
||||
|
||||
Next install all the dependencies:
|
||||
|
||||
```
|
||||
> cd tree-view
|
||||
> apm install
|
||||
Installing modules ✓
|
||||
~/.atom/dev/packages/tree-view -> ~/github/tree-view
|
||||
```
|
||||
|
||||
This clones the `tree-view` repository to `~/github`. If you prefer a different
|
||||
path, specify it via the `ATOM_REPOS_HOME` environment variable.
|
||||
Now you can link it to development mode so when you run an Atom window with `atom --dev`, you will use your fork instead of the built in package:
|
||||
|
||||
```
|
||||
> apm link -d
|
||||
```
|
||||
|
||||
### Running in Development Mode
|
||||
|
||||
@@ -46,7 +51,4 @@ from the package directory to create and remove dev-mode symlinks.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
Finally, you need to install the cloned package's dependencies by running
|
||||
`apm install` within the package directory. This step is also performed
|
||||
automatically the first time you run `apm develop`, but you'll want to keep
|
||||
dependencies up to date by running `apm update` after pulling upstream changes.
|
||||
You'll want to keep dependencies up to date by running `apm update` after pulling any upstream changes.
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
* [Converting a TextMate Bundle](converting-a-text-mate-bundle.md)
|
||||
* [Converting a TextMate Theme](converting-a-text-mate-theme.md)
|
||||
* [Contributing](contributing.md)
|
||||
* [Contributing to Core Packages](contributing-to-packages.md)
|
||||
* [Debugging](debugging.md)
|
||||
|
||||
### Advanced Topics
|
||||
@@ -18,3 +19,4 @@
|
||||
* [Keymaps](advanced/keymaps.md)
|
||||
* [Serialization](advanced/serialization.md)
|
||||
* [View System](advanced/view-system.md)
|
||||
* [Scopes and Scope Descriptors](advanced/scopes-and-scope-descriptors.md)
|
||||
|
||||
@@ -19,3 +19,7 @@
|
||||
# You can find more information about keymaps in these guides:
|
||||
# * https://atom.io/docs/latest/customizing-atom#customizing-key-bindings
|
||||
# * https://atom.io/docs/latest/advanced/keymaps
|
||||
#
|
||||
# This file uses CoffeeScript Object Notation (CSON).
|
||||
# If you are unfamiliar with CSON, you can read more about it here:
|
||||
# https://github.com/bevry/cson#what-is-cson
|
||||
|
||||
@@ -13,3 +13,6 @@
|
||||
# 'prefix': 'log'
|
||||
# 'body': 'console.log $1'
|
||||
#
|
||||
# This file uses CoffeeScript Object Notation (CSON).
|
||||
# If you are unfamiliar with CSON, you can read more about it here:
|
||||
# https://github.com/bevry/cson#what-is-cson
|
||||
|
||||
@@ -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' }
|
||||
]
|
||||
}
|
||||
|
||||
+42
-42
@@ -1,7 +1,7 @@
|
||||
{
|
||||
{
|
||||
"name": "atom",
|
||||
"productName": "Atom",
|
||||
"version": "0.137.0",
|
||||
"version": "0.141.0",
|
||||
"description": "A hackable text editor for the 21st Century.",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
@@ -17,7 +17,7 @@
|
||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||
}
|
||||
],
|
||||
"atomShellVersion": "0.18.0",
|
||||
"atomShellVersion": "0.18.2",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^2.2.1",
|
||||
@@ -37,36 +37,36 @@
|
||||
"guid": "0.0.10",
|
||||
"jasmine-json": "~0.0",
|
||||
"jasmine-tagged": "^1.1.2",
|
||||
"less-cache": "0.15.0",
|
||||
"less-cache": "0.17.0",
|
||||
"mixto": "^1",
|
||||
"mkdirp": "0.3.5",
|
||||
"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.13.2",
|
||||
"scandal": "1.0.3",
|
||||
"scoped-property-store": "^0.15.0",
|
||||
"scrollbar-style": "^1.0.2",
|
||||
"season": "^1.0.2",
|
||||
"semver": "1.1.4",
|
||||
"semver": "2.2.1",
|
||||
"serializable": "^1",
|
||||
"space-pen": "3.8.0",
|
||||
"temp": "0.7.0",
|
||||
"text-buffer": "^3.2.8",
|
||||
"text-buffer": "^3.4",
|
||||
"theorist": "^1.0.2",
|
||||
"underscore-plus": "^1.5.1",
|
||||
"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,69 +78,69 @@
|
||||
"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.10.0",
|
||||
"dev-live-reload": "0.34.0",
|
||||
"deprecation-cop": "0.11.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.39.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.25.0",
|
||||
"markdown-preview": "0.104.0",
|
||||
"link": "0.26.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.152.0",
|
||||
"snippets": "0.55.0",
|
||||
"spell-check": "0.42.0",
|
||||
"settings-view": "0.154.0",
|
||||
"snippets": "0.56.0",
|
||||
"spell-check": "0.43.0",
|
||||
"status-bar": "0.46.0",
|
||||
"styleguide": "0.30.0",
|
||||
"symbols-view": "0.66.0",
|
||||
"tabs": "0.54.0",
|
||||
"timecop": "0.22.0",
|
||||
"tabs": "0.55.0",
|
||||
"timecop": "0.23.0",
|
||||
"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.28.0",
|
||||
"language-coffee-script": "0.35.0",
|
||||
"language-c": "0.29.0",
|
||||
"language-coffee-script": "0.37.0",
|
||||
"language-css": "0.21.0",
|
||||
"language-gfm": "0.51.0",
|
||||
"language-gfm": "0.53.0",
|
||||
"language-git": "0.9.0",
|
||||
"language-go": "0.18.0",
|
||||
"language-go": "0.19.0",
|
||||
"language-html": "0.26.0",
|
||||
"language-hyperlink": "0.12.0",
|
||||
"language-java": "0.11.0",
|
||||
"language-javascript": "0.40.0",
|
||||
"language-javascript": "0.42.0",
|
||||
"language-json": "0.8.0",
|
||||
"language-less": "0.15.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.20.0",
|
||||
"language-ruby": "0.39.0",
|
||||
"language-python": "0.21.0",
|
||||
"language-ruby": "0.41.0",
|
||||
"language-ruby-on-rails": "0.18.0",
|
||||
"language-sass": "0.22.0",
|
||||
"language-sass": "0.24.0",
|
||||
"language-shellscript": "0.8.0",
|
||||
"language-source": "0.8.0",
|
||||
"language-sql": "0.11.0",
|
||||
"language-text": "0.6.0",
|
||||
"language-todo": "0.13.0",
|
||||
"language-toml": "0.12.0",
|
||||
"language-toml": "0.14.0",
|
||||
"language-xml": "0.24.0",
|
||||
"language-yaml": "0.18.0"
|
||||
"language-yaml": "0.19.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[Desktop Entry]
|
||||
Name=Atom
|
||||
Comment=<%= description %>
|
||||
GenericName=Text Editor
|
||||
Exec=<%= installDir %>/share/atom/atom %U
|
||||
Icon=<%= iconName %>
|
||||
Type=Application
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
Name: <%= name %>
|
||||
Version: <%= version %>
|
||||
Release: 0.1%{?dist}
|
||||
Summary: Atom is a hackable text editor for the 21st century
|
||||
License: MIT
|
||||
URL: https://atom.io/
|
||||
BuildConflicts: gyp
|
||||
BuildRequires: make, gcc, gcc-c++, glibc-devel, git-core, libgnome-keyring-devel
|
||||
Requires: libgnome-keyring
|
||||
AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
|
||||
|
||||
%description
|
||||
<%= description %>
|
||||
|
||||
%install
|
||||
mkdir -p %{buildroot}/usr/local/share/atom
|
||||
cp -r /tmp/atom-build/Atom/* %{buildroot}/usr/local/share/atom
|
||||
mkdir -p %{buildroot}/usr/local/bin/
|
||||
ln -sf /usr/local/share/atom/resources/app/apm/node_modules/.bin/apm %{buildroot}/usr/local/bin/apm
|
||||
cp atom.sh %{buildroot}/usr/local/bin/atom
|
||||
chmod 755 atom.sh
|
||||
mkdir -p %{buildroot}/usr/local/share/applications/
|
||||
mv atom.desktop %{buildroot}/usr/local/share/applications/
|
||||
|
||||
%files
|
||||
/usr/local/bin/atom
|
||||
/usr/local/bin/apm
|
||||
/usr/local/share/atom/
|
||||
/usr/local/share/applications/atom.desktop
|
||||
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
|
||||
Arquivo executável
+22
@@ -0,0 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
SPEC_FILE="$1"
|
||||
DESKTOP_FILE="$2"
|
||||
BUILD_DIRECTORY="$3"
|
||||
|
||||
RPM_BUILD_ROOT=~/rpmbuild
|
||||
ARCH=`uname -m`
|
||||
|
||||
rpmdev-setuptree
|
||||
|
||||
cp -r $BUILD_DIRECTORY/Atom/* $RPM_BUILD_ROOT/BUILD
|
||||
cp $SPEC_FILE $RPM_BUILD_ROOT/SPECS
|
||||
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/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
|
||||
@@ -88,6 +88,19 @@ describe "Config", ->
|
||||
expect(atom.config.getDefault('foo.bar')).toEqual initialDefaultValue
|
||||
expect(atom.config.getDefault('foo.bar')).not.toBe initialDefaultValue
|
||||
|
||||
describe "when scoped settings are used", ->
|
||||
it "returns the global default when no scoped default set", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 10
|
||||
|
||||
it "returns the scoped default when a scoped default is set", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: baz: 42)
|
||||
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 42
|
||||
|
||||
atom.config.set('.source.coffee', 'foo.bar.baz', 55)
|
||||
expect(atom.config.getDefault('.source.coffee', 'foo.bar.baz')).toBe 42
|
||||
|
||||
describe ".isDefault(keyPath)", ->
|
||||
it "returns true when the value of the key path is its default value", ->
|
||||
atom.config.setDefaults("foo", same: 1, changes: 1)
|
||||
@@ -99,6 +112,21 @@ describe "Config", ->
|
||||
expect(atom.config.isDefault('foo.same')).toBe false
|
||||
expect(atom.config.isDefault('foo.changes')).toBe false
|
||||
|
||||
describe "when scoped settings are used", ->
|
||||
it "returns false when a scoped setting was set by the user", ->
|
||||
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe true
|
||||
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: baz: 42)
|
||||
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe true
|
||||
|
||||
atom.config.set('.source.coffee', 'foo.bar.baz', 55)
|
||||
expect(atom.config.isDefault('.source.coffee', 'foo.bar.baz')).toBe false
|
||||
|
||||
describe ".setDefaults(keyPath)", ->
|
||||
it "sets a default when the setting's key contains an escaped dot", ->
|
||||
atom.config.setDefaults("foo", 'a\\.b': 1, b: 2)
|
||||
expect(atom.config.get("foo")).toEqual 'a\\.b': 1, b: 2
|
||||
|
||||
describe ".toggle(keyPath)", ->
|
||||
it "negates the boolean value of the current key path value", ->
|
||||
atom.config.set('foo.a', 1)
|
||||
@@ -130,6 +158,66 @@ describe "Config", ->
|
||||
atom.config.restoreDefault('a.c')
|
||||
expect(atom.config.get('a.c')).toBeUndefined()
|
||||
|
||||
it "calls ::save()", ->
|
||||
atom.config.setDefaults('a', b: 3)
|
||||
atom.config.set('a.b', 4)
|
||||
atom.config.save.reset()
|
||||
|
||||
atom.config.restoreDefault('a.c')
|
||||
expect(atom.config.save.callCount).toBe 1
|
||||
|
||||
describe "when scoped settings are used", ->
|
||||
it "restores the global default when no scoped default set", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.set('.source.coffee', 'foo.bar.baz', 55)
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.baz')).toBe 55
|
||||
|
||||
atom.config.restoreDefault('.source.coffee', 'foo.bar.baz')
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.baz')).toBe 10
|
||||
|
||||
it "restores the scoped default when a scoped default is set", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: baz: 42)
|
||||
atom.config.set('.source.coffee', 'foo.bar.baz', 55)
|
||||
atom.config.set('.source.coffee', 'foo.bar.ok', 100)
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.baz')).toBe 55
|
||||
|
||||
atom.config.restoreDefault('.source.coffee', 'foo.bar.baz')
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.baz')).toBe 42
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.ok')).toBe 100
|
||||
|
||||
it "calls ::save()", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: baz: 42)
|
||||
atom.config.set('.source.coffee', 'foo.bar.baz', 55)
|
||||
atom.config.save.reset()
|
||||
|
||||
atom.config.restoreDefault('.source.coffee', 'foo.bar.baz')
|
||||
expect(atom.config.save.callCount).toBe 1
|
||||
|
||||
describe ".getSettings()", ->
|
||||
it "returns all settings including defaults", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.set("foo.ok", 12)
|
||||
|
||||
expect(atom.config.getSettings().foo).toEqual
|
||||
ok: 12
|
||||
bar:
|
||||
baz: 10
|
||||
|
||||
describe "when scoped settings are used", ->
|
||||
it "returns all the scoped settings including all the defaults", ->
|
||||
atom.config.setDefaults("foo", bar: baz: 10)
|
||||
atom.config.set("foo.ok", 12)
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: baz: 42)
|
||||
atom.config.addScopedSettings("default", ".source.coffee", foo: bar: omg: 'omg')
|
||||
|
||||
expect(atom.config.getSettings(".source.coffee").foo).toEqual
|
||||
ok: 12
|
||||
bar:
|
||||
baz: 42
|
||||
omg: 'omg'
|
||||
|
||||
describe ".pushAtKeyPath(keyPath, value)", ->
|
||||
it "pushes the given value to the array at the key path and updates observers", ->
|
||||
atom.config.set("foo.bar.baz", ["a"])
|
||||
@@ -948,6 +1036,21 @@ describe "Config", ->
|
||||
expect(atom.config.set('foo.bar.arr', ['two', 'three'])).toBe true
|
||||
expect(atom.config.get('foo.bar.arr')).toEqual ['two', 'three']
|
||||
|
||||
describe "when scoped settings are used", ->
|
||||
beforeEach ->
|
||||
schema =
|
||||
type: 'string'
|
||||
default: 'ok'
|
||||
scopes:
|
||||
'.source.js':
|
||||
default: 'omg'
|
||||
atom.config.setSchema('foo.bar.str', schema)
|
||||
|
||||
it 'it respects the scoped defaults', ->
|
||||
expect(atom.config.get('foo.bar.str')).toBe 'ok'
|
||||
expect(atom.config.get(['.source.js'], 'foo.bar.str')).toBe 'omg'
|
||||
expect(atom.config.get(['.source.coffee'], 'foo.bar.str')).toBe 'ok'
|
||||
|
||||
describe "scoped settings", ->
|
||||
describe ".get(scopeDescriptor, keyPath)", ->
|
||||
it "returns the property with the most specific scope selector", ->
|
||||
@@ -972,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)
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"foo": "bar"
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"theme": "syntax",
|
||||
"stylesheets": ["editor.less"]
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
path = require 'path'
|
||||
Module = require 'module'
|
||||
fs = require 'fs-plus'
|
||||
temp = require 'temp'
|
||||
ModuleCache = require '../src/module-cache'
|
||||
|
||||
describe 'ModuleCache', ->
|
||||
beforeEach ->
|
||||
spyOn(Module, '_findPath').andCallThrough()
|
||||
|
||||
it 'resolves atom shell module paths without hitting the filesystem', ->
|
||||
builtins = ModuleCache.cache.builtins
|
||||
expect(Object.keys(builtins).length).toBeGreaterThan 0
|
||||
|
||||
for builtinName, builtinPath of builtins
|
||||
expect(require.resolve(builtinName)).toBe builtinPath
|
||||
expect(fs.isFileSync(require.resolve(builtinName)))
|
||||
|
||||
expect(Module._findPath.callCount).toBe 0
|
||||
|
||||
it 'resolves relative core paths without hitting the filesystem', ->
|
||||
ModuleCache.add atom.getLoadSettings().resourcePath, {
|
||||
_atomModuleCache:
|
||||
extensions:
|
||||
'.json': [
|
||||
path.join('spec', 'fixtures', 'module-cache', 'file.json')
|
||||
]
|
||||
}
|
||||
expect(require('./fixtures/module-cache/file.json').foo).toBe 'bar'
|
||||
expect(Module._findPath.callCount).toBe 0
|
||||
|
||||
it 'resolves module paths when a compatible version is provided by core', ->
|
||||
packagePath = fs.realpathSync(temp.mkdirSync('atom-package'))
|
||||
ModuleCache.add packagePath, {
|
||||
_atomModuleCache:
|
||||
folders: [{
|
||||
paths: [
|
||||
''
|
||||
]
|
||||
dependencies:
|
||||
'underscore-plus': '*'
|
||||
}]
|
||||
}
|
||||
ModuleCache.add atom.getLoadSettings().resourcePath, {
|
||||
_atomModuleCache:
|
||||
dependencies: [{
|
||||
name: 'underscore-plus'
|
||||
version: require('underscore-plus/package.json').version
|
||||
path: path.join('node_modules', 'underscore-plus', 'lib', 'underscore-plus.js')
|
||||
}]
|
||||
}
|
||||
|
||||
indexPath = path.join(packagePath, 'index.js')
|
||||
fs.writeFileSync indexPath, """
|
||||
exports.load = function() { require('underscore-plus'); };
|
||||
"""
|
||||
|
||||
packageMain = require(indexPath)
|
||||
Module._findPath.reset()
|
||||
packageMain.load()
|
||||
expect(Module._findPath.callCount).toBe 0
|
||||
|
||||
it 'does not resolve module paths when no compatible version is provided by core', ->
|
||||
packagePath = fs.realpathSync(temp.mkdirSync('atom-package'))
|
||||
ModuleCache.add packagePath, {
|
||||
_atomModuleCache:
|
||||
folders: [{
|
||||
paths: [
|
||||
''
|
||||
]
|
||||
dependencies:
|
||||
'underscore-plus': '0.0.1'
|
||||
}]
|
||||
}
|
||||
ModuleCache.add atom.getLoadSettings().resourcePath, {
|
||||
_atomModuleCache:
|
||||
dependencies: [{
|
||||
name: 'underscore-plus'
|
||||
version: require('underscore-plus/package.json').version
|
||||
path: path.join('node_modules', 'underscore-plus', 'lib', 'underscore-plus.js')
|
||||
}]
|
||||
}
|
||||
|
||||
indexPath = path.join(packagePath, 'index.js')
|
||||
fs.writeFileSync indexPath, """
|
||||
exports.load = function() { require('underscore-plus'); };
|
||||
"""
|
||||
|
||||
packageMain = require(indexPath)
|
||||
Module._findPath.reset()
|
||||
expect(-> packageMain.load()).toThrow()
|
||||
expect(Module._findPath.callCount).toBe 1
|
||||
@@ -0,0 +1,63 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelElement = require '../src/panel-element'
|
||||
PanelContainer = require '../src/panel-container'
|
||||
PanelContainerElement = require '../src/panel-container-element'
|
||||
|
||||
describe "PanelContainerElement", ->
|
||||
[jasmineContent, element, container, viewRegistry] = []
|
||||
|
||||
class TestPanelContainerItem
|
||||
constructior: ->
|
||||
|
||||
class TestPanelContainerItemElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@classList.add('test-root')
|
||||
setModel: (@model) ->
|
||||
TestPanelContainerItemElement = document.registerElement 'atom-test-container-item-element', prototype: TestPanelContainerItemElement.prototype
|
||||
|
||||
beforeEach ->
|
||||
jasmineContent = document.body.querySelector('#jasmine-content')
|
||||
|
||||
viewRegistry = new ViewRegistry
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: PanelContainer
|
||||
viewConstructor: PanelContainerElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: TestPanelContainerItem
|
||||
viewConstructor: TestPanelContainerItemElement
|
||||
|
||||
container = new PanelContainer({viewRegistry, location: 'left'})
|
||||
element = container.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
it 'has a location attribute with value from the model', ->
|
||||
expect(element.getAttribute('location')).toBe 'left'
|
||||
|
||||
it 'removes the element when the container is destroyed', ->
|
||||
expect(element.parentNode).toBe jasmineContent
|
||||
container.destroy()
|
||||
expect(element.parentNode).not.toBe jasmineContent
|
||||
|
||||
describe "adding and removing panels", ->
|
||||
it "adds atom-panel elements when a new panel is added to the container; removes them when the panels are destroyed", ->
|
||||
expect(element.childNodes.length).toBe 0
|
||||
|
||||
panel1 = new Panel({viewRegistry, item: new TestPanelContainerItem(), location: 'left'})
|
||||
container.addPanel(panel1)
|
||||
expect(element.childNodes.length).toBe 1
|
||||
|
||||
expect(element.childNodes[0].tagName).toBe 'ATOM-PANEL'
|
||||
|
||||
panel2 = new Panel({viewRegistry, item: new TestPanelContainerItem(), location: 'left'})
|
||||
container.addPanel(panel2)
|
||||
expect(element.childNodes.length).toBe 2
|
||||
|
||||
panel1.destroy()
|
||||
expect(element.childNodes.length).toBe 1
|
||||
|
||||
panel2.destroy()
|
||||
expect(element.childNodes.length).toBe 0
|
||||
@@ -0,0 +1,98 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelContainer = require '../src/panel-container'
|
||||
|
||||
describe "PanelContainer", ->
|
||||
[container, viewRegistry] = []
|
||||
|
||||
class TestPanelItem
|
||||
constructior: ->
|
||||
|
||||
beforeEach ->
|
||||
viewRegistry = new ViewRegistry
|
||||
container = new PanelContainer({viewRegistry})
|
||||
|
||||
describe "::addPanel(panel)", ->
|
||||
it 'emits an onDidAddPanel event with the index the panel was inserted at', ->
|
||||
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
|
||||
panel1 = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(panel1)
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
|
||||
|
||||
panel2 = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(panel2)
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
|
||||
|
||||
describe "when a panel is destroyed", ->
|
||||
it 'emits an onDidRemovePanel event with the index of the removed item', ->
|
||||
container.onDidRemovePanel removePanelSpy = jasmine.createSpy()
|
||||
|
||||
panel1 = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(panel1)
|
||||
panel2 = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(panel2)
|
||||
|
||||
expect(removePanelSpy).not.toHaveBeenCalled()
|
||||
|
||||
panel2.destroy()
|
||||
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel2, index: 1})
|
||||
|
||||
panel1.destroy()
|
||||
expect(removePanelSpy).toHaveBeenCalledWith({panel: panel1, index: 0})
|
||||
|
||||
describe "panel priority", ->
|
||||
describe 'left / top panel container', ->
|
||||
[initialPanel] = []
|
||||
beforeEach ->
|
||||
# 'left' logic is the same as 'top'
|
||||
container = new PanelContainer({viewRegistry, location: 'left'})
|
||||
initialPanel = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(initialPanel)
|
||||
|
||||
describe 'when a panel with low priority is added', ->
|
||||
it 'is inserted at the beginning of the list', ->
|
||||
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = new Panel(item: new TestPanelItem(), priority: 0)
|
||||
container.addPanel(panel)
|
||||
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
expect(container.getPanels()[0]).toBe panel
|
||||
|
||||
describe 'when a panel with priority between two other panels is added', ->
|
||||
it 'is inserted at the between the two panels', ->
|
||||
panel = new Panel(item: new TestPanelItem(), priority: 1000)
|
||||
container.addPanel(panel)
|
||||
|
||||
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = new Panel(item: new TestPanelItem(), priority: 101)
|
||||
container.addPanel(panel)
|
||||
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
|
||||
expect(container.getPanels()[1]).toBe panel
|
||||
|
||||
describe 'right / bottom panel container', ->
|
||||
[initialPanel] = []
|
||||
beforeEach ->
|
||||
# 'bottom' logic is the same as 'right'
|
||||
container = new PanelContainer({viewRegistry, location: 'right'})
|
||||
initialPanel = new Panel(item: new TestPanelItem())
|
||||
container.addPanel(initialPanel)
|
||||
|
||||
describe 'when a panel with high priority is added', ->
|
||||
it 'is inserted at the beginning of the list', ->
|
||||
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = new Panel(item: new TestPanelItem(), priority: 1000)
|
||||
container.addPanel(panel)
|
||||
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
expect(container.getPanels()[0]).toBe panel
|
||||
|
||||
describe 'when a panel with low priority is added', ->
|
||||
it 'is inserted at the end of the list', ->
|
||||
container.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = new Panel(item: new TestPanelItem(), priority: 0)
|
||||
container.addPanel(panel)
|
||||
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 1})
|
||||
expect(container.getPanels()[1]).toBe panel
|
||||
@@ -0,0 +1,56 @@
|
||||
ViewRegistry = require '../src/view-registry'
|
||||
Panel = require '../src/panel'
|
||||
PanelElement = require '../src/panel-element'
|
||||
|
||||
describe "PanelElement", ->
|
||||
[jasmineContent, element, panel, viewRegistry] = []
|
||||
|
||||
class TestPanelItem
|
||||
constructior: ->
|
||||
|
||||
class TestPanelItemElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@classList.add('test-root')
|
||||
setModel: (@model) ->
|
||||
TestPanelItemElement = document.registerElement 'atom-test-item-element', prototype: TestPanelItemElement.prototype
|
||||
|
||||
beforeEach ->
|
||||
jasmineContent = document.body.querySelector('#jasmine-content')
|
||||
|
||||
viewRegistry = new ViewRegistry
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
viewRegistry.addViewProvider
|
||||
modelConstructor: TestPanelItem
|
||||
viewConstructor: TestPanelItemElement
|
||||
|
||||
it 'removes the element when the panel is destroyed', ->
|
||||
panel = new Panel({viewRegistry, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.parentNode).toBe jasmineContent
|
||||
panel.destroy()
|
||||
expect(element.parentNode).not.toBe jasmineContent
|
||||
|
||||
describe "changing panel visibility", ->
|
||||
it 'initially renders panel created with visibile: false', ->
|
||||
panel = new Panel({viewRegistry, visible: false, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.style.display).toBe 'none'
|
||||
|
||||
it 'hides and shows the panel element when Panel::hide() and Panel::show() are called', ->
|
||||
panel = new Panel({viewRegistry, item: new TestPanelItem})
|
||||
element = panel.getView()
|
||||
jasmineContent.appendChild(element)
|
||||
|
||||
expect(element.style.display).not.toBe 'none'
|
||||
|
||||
panel.hide()
|
||||
expect(element.style.display).toBe 'none'
|
||||
|
||||
panel.show()
|
||||
expect(element.style.display).not.toBe 'none'
|
||||
@@ -0,0 +1,23 @@
|
||||
Panel = require '../src/panel'
|
||||
|
||||
describe "Panel", ->
|
||||
[panel] = []
|
||||
|
||||
class TestPanelItem
|
||||
constructior: ->
|
||||
|
||||
beforeEach ->
|
||||
panel = new Panel(item: new TestPanelItem())
|
||||
|
||||
describe "changing panel visibility", ->
|
||||
it 'emits an event when visibility changes', ->
|
||||
panel.onDidChangeVisible spy = jasmine.createSpy()
|
||||
|
||||
panel.hide()
|
||||
expect(panel.isVisible()).toBe false
|
||||
expect(spy).toHaveBeenCalledWith(false)
|
||||
spy.reset()
|
||||
|
||||
panel.show()
|
||||
expect(panel.isVisible()).toBe true
|
||||
expect(spy).toHaveBeenCalledWith(true)
|
||||
@@ -29,6 +29,7 @@ atom.packages.packageDirPaths.unshift(fixturePackagesPath)
|
||||
atom.keymaps.loadBundledKeymaps()
|
||||
keyBindingsToRestore = atom.keymaps.getKeyBindings()
|
||||
commandsToRestore = atom.commands.getSnapshot()
|
||||
styleElementsToRestore = atom.styles.getSnapshot()
|
||||
|
||||
window.addEventListener 'core:close', -> window.close()
|
||||
window.addEventListener 'beforeunload', ->
|
||||
@@ -44,8 +45,7 @@ Object.defineProperty document, 'title',
|
||||
|
||||
jasmine.getEnv().addEqualityTester(_.isEqual) # Use underscore's definition of equality for toEqual assertions
|
||||
|
||||
if process.platform is 'win32' and process.env.JANKY_SHA1
|
||||
# Use longer timeout on Windows CI
|
||||
if process.env.JANKY_SHA1 and process.platform is 'win32'
|
||||
jasmine.getEnv().defaultTimeoutInterval = 60000
|
||||
else
|
||||
jasmine.getEnv().defaultTimeoutInterval = 5000
|
||||
@@ -74,6 +74,7 @@ beforeEach ->
|
||||
atom.workspace = new Workspace()
|
||||
atom.keymaps.keyBindings = _.clone(keyBindingsToRestore)
|
||||
atom.commands.restoreSnapshot(commandsToRestore)
|
||||
atom.styles.restoreSnapshot(styleElementsToRestore)
|
||||
|
||||
window.resetTimeouts()
|
||||
atom.packages.packageStates = {}
|
||||
@@ -224,7 +225,7 @@ addCustomMatchers = (spec) ->
|
||||
notText = if @isNot then " not" else ""
|
||||
element = @actual
|
||||
element = element.get(0) if element.jquery
|
||||
@message = -> return "Expected element '#{element}' or its descendants #{notText} to show."
|
||||
@message = -> return "Expected element '#{element}' or its descendants#{notText} to show."
|
||||
element.style.display in ['block', 'inline-block', 'static', 'fixed']
|
||||
|
||||
window.keyIdentifierForKey = (key) ->
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
StyleManager = require '../src/style-manager'
|
||||
|
||||
describe "StyleManager", ->
|
||||
[manager, addEvents, removeEvents, updateEvents] = []
|
||||
|
||||
beforeEach ->
|
||||
manager = new StyleManager
|
||||
addEvents = []
|
||||
removeEvents = []
|
||||
updateEvents = []
|
||||
|
||||
manager.onDidAddStyleElement (event) -> addEvents.push(event)
|
||||
manager.onDidRemoveStyleElement (event) -> removeEvents.push(event)
|
||||
manager.onDidUpdateStyleElement (event) -> updateEvents.push(event)
|
||||
|
||||
describe "::addStyleSheet(source, params)", ->
|
||||
it "adds a stylesheet based on the given source and returns a disposable allowing it to be removed", ->
|
||||
disposable = manager.addStyleSheet("a {color: red;}")
|
||||
|
||||
expect(addEvents.length).toBe 1
|
||||
expect(addEvents[0].textContent).toBe "a {color: red;}"
|
||||
|
||||
styleElements = manager.getStyleElements()
|
||||
expect(styleElements.length).toBe 1
|
||||
expect(styleElements[0].textContent).toBe "a {color: red;}"
|
||||
|
||||
disposable.dispose()
|
||||
|
||||
expect(removeEvents.length).toBe 1
|
||||
expect(removeEvents[0].textContent).toBe "a {color: red;}"
|
||||
expect(manager.getStyleElements().length).toBe 0
|
||||
|
||||
describe "when a sourcePath parameter is specified", ->
|
||||
it "ensures a maximum of one style element for the given source path, updating a previous if it exists", ->
|
||||
disposable1 = manager.addStyleSheet("a {color: red;}", sourcePath: '/foo/bar')
|
||||
|
||||
expect(addEvents.length).toBe 1
|
||||
expect(addEvents[0].getAttribute('source-path')).toBe '/foo/bar'
|
||||
|
||||
disposable2 = manager.addStyleSheet("a {color: blue;}", sourcePath: '/foo/bar')
|
||||
|
||||
expect(addEvents.length).toBe 1
|
||||
expect(updateEvents.length).toBe 1
|
||||
expect(updateEvents[0].getAttribute('source-path')).toBe '/foo/bar'
|
||||
expect(updateEvents[0].textContent).toBe "a {color: blue;}"
|
||||
|
||||
disposable2.dispose()
|
||||
addEvents = []
|
||||
|
||||
manager.addStyleSheet("a {color: yellow;}", sourcePath: '/foo/bar')
|
||||
|
||||
expect(addEvents.length).toBe 1
|
||||
expect(addEvents[0].getAttribute('source-path')).toBe '/foo/bar'
|
||||
expect(addEvents[0].textContent).toBe "a {color: yellow;}"
|
||||
|
||||
describe "when a group parameter is specified", ->
|
||||
it "inserts the stylesheet at the end of any existing stylesheets for the same group", ->
|
||||
manager.addStyleSheet("a {color: red}", group: 'a')
|
||||
manager.addStyleSheet("a {color: blue}", group: 'b')
|
||||
manager.addStyleSheet("a {color: green}", group: 'a')
|
||||
|
||||
expect(manager.getStyleElements().map (elt) -> elt.textContent).toEqual [
|
||||
"a {color: red}"
|
||||
"a {color: green}"
|
||||
"a {color: blue}"
|
||||
]
|
||||
@@ -0,0 +1,54 @@
|
||||
StylesElement = require '../src/styles-element'
|
||||
StyleManager = require '../src/style-manager'
|
||||
|
||||
describe "StylesElement", ->
|
||||
[element, addedStyleElements, removedStyleElements, updatedStyleElements] = []
|
||||
|
||||
beforeEach ->
|
||||
element = new StylesElement
|
||||
document.querySelector('#jasmine-content').appendChild(element)
|
||||
addedStyleElements = []
|
||||
removedStyleElements = []
|
||||
updatedStyleElements = []
|
||||
element.onDidAddStyleElement (element) -> addedStyleElements.push(element)
|
||||
element.onDidRemoveStyleElement (element) -> removedStyleElements.push(element)
|
||||
element.onDidUpdateStyleElement (element) -> updatedStyleElements.push(element)
|
||||
|
||||
it "renders a style tag for all currently active stylesheets in the style manager", ->
|
||||
initialChildCount = element.children.length
|
||||
|
||||
disposable1 = atom.styles.addStyleSheet("a {color: red;}")
|
||||
expect(element.children.length).toBe initialChildCount + 1
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: red;}"
|
||||
expect(addedStyleElements).toEqual [element.children[initialChildCount]]
|
||||
|
||||
disposable2 = atom.styles.addStyleSheet("a {color: blue;}")
|
||||
expect(element.children.length).toBe initialChildCount + 2
|
||||
expect(element.children[initialChildCount + 1].textContent).toBe "a {color: blue;}"
|
||||
expect(addedStyleElements).toEqual [element.children[initialChildCount], element.children[initialChildCount + 1]]
|
||||
|
||||
disposable1.dispose()
|
||||
expect(element.children.length).toBe initialChildCount + 1
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: blue;}"
|
||||
expect(removedStyleElements).toEqual [addedStyleElements[0]]
|
||||
|
||||
it "orders style elements by group", ->
|
||||
initialChildCount = element.children.length
|
||||
|
||||
atom.styles.addStyleSheet("a {color: red}", group: 'a')
|
||||
atom.styles.addStyleSheet("a {color: blue}", group: 'b')
|
||||
atom.styles.addStyleSheet("a {color: green}", group: 'a')
|
||||
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: red}"
|
||||
expect(element.children[initialChildCount + 1].textContent).toBe "a {color: green}"
|
||||
expect(element.children[initialChildCount + 2].textContent).toBe "a {color: blue}"
|
||||
|
||||
it "updates existing style nodes when style elements are updated", ->
|
||||
initialChildCount = element.children.length
|
||||
|
||||
atom.styles.addStyleSheet("a {color: red;}", sourcePath: '/foo/bar')
|
||||
atom.styles.addStyleSheet("a {color: blue;}", sourcePath: '/foo/bar')
|
||||
|
||||
expect(element.children.length).toBe initialChildCount + 1
|
||||
expect(element.children[initialChildCount].textContent).toBe "a {color: blue;}"
|
||||
expect(updatedStyleElements).toEqual [element.children[initialChildCount]]
|
||||
@@ -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])
|
||||
@@ -1230,6 +1248,22 @@ describe "TextEditorComponent", ->
|
||||
beforeEach ->
|
||||
linesNode = componentNode.querySelector('.lines')
|
||||
|
||||
describe "when the mouse is single-clicked below the last line", ->
|
||||
it "moves the cursor to the end of file buffer position", ->
|
||||
editor.setText('foo')
|
||||
editor.setCursorBufferPosition([0, 0])
|
||||
height = 4.5 * lineHeightInPixels
|
||||
wrapperNode.style.height = height + 'px'
|
||||
wrapperNode.style.width = 10 * charWidth + 'px'
|
||||
component.measureHeightAndWidth()
|
||||
nextAnimationFrame()
|
||||
|
||||
coordinates = clientCoordinatesForScreenPosition([0, 2])
|
||||
coordinates.clientY = height * 2
|
||||
linesNode.dispatchEvent(buildMouseEvent('mousedown', coordinates))
|
||||
nextAnimationFrame()
|
||||
expect(editor.getCursorScreenPosition()).toEqual [0, 3]
|
||||
|
||||
describe "when a non-folded line is single-clicked", ->
|
||||
describe "when no modifier keys are held down", ->
|
||||
it "moves the cursor to the nearest screen position", ->
|
||||
@@ -2252,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", ->
|
||||
@@ -3412,9 +3425,12 @@ describe "TextEditor", ->
|
||||
describe "when no text is selected", ->
|
||||
describe "when the line below isn't empty", ->
|
||||
it "joins the line below with the current line separated by a space and moves the cursor to the start of line that was moved up", ->
|
||||
editor.setCursorBufferPosition([0, Infinity])
|
||||
editor.insertText(' ')
|
||||
editor.setCursorBufferPosition([0])
|
||||
editor.joinLines()
|
||||
expect(editor.lineTextForBufferRow(0)).toBe 'var quicksort = function () { var sort = function(items) {'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 30]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [0, 29]
|
||||
|
||||
describe "when the line below is empty", ->
|
||||
it "deletes the line below and moves the cursor to the end of the line", ->
|
||||
@@ -3430,6 +3446,13 @@ describe "TextEditor", ->
|
||||
editor.joinLines()
|
||||
expect(editor.lineTextForBufferRow(12)).toBe '};'
|
||||
|
||||
describe "when the line is empty", ->
|
||||
it "joins the line below with the current line with no added space", ->
|
||||
editor.setCursorBufferPosition([10])
|
||||
editor.joinLines()
|
||||
expect(editor.lineTextForBufferRow(10)).toBe 'return sort(Array.apply(this, arguments));'
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10, 0]
|
||||
|
||||
describe "when text is selected", ->
|
||||
describe "when the selection does not span multiple lines", ->
|
||||
it "joins the line below with the current line separated by a space and retains the selected text", ->
|
||||
@@ -3650,10 +3673,10 @@ describe "TextEditor", ->
|
||||
{tokens} = grammar.tokenizeLine("var i; // http://github.com")
|
||||
|
||||
expect(tokens[0].value).toBe "var"
|
||||
expect(tokens[0].scopeDescriptor).toEqual ["source.js", "storage.modifier.js"]
|
||||
expect(tokens[0].scopes).toEqual ["source.js", "storage.modifier.js"]
|
||||
|
||||
expect(tokens[6].value).toBe "http://github.com"
|
||||
expect(tokens[6].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
|
||||
expect(tokens[6].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
|
||||
|
||||
describe "when the grammar is added", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
@@ -3665,7 +3688,7 @@ describe "TextEditor", ->
|
||||
|
||||
{tokens} = editor.tokenizedLineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " http://github.com"
|
||||
expect(tokens[1].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-hyperlink')
|
||||
@@ -3673,7 +3696,7 @@ describe "TextEditor", ->
|
||||
runs ->
|
||||
{tokens} = editor.tokenizedLineForScreenRow(0)
|
||||
expect(tokens[2].value).toBe "http://github.com"
|
||||
expect(tokens[2].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "markup.underline.link.http.hyperlink"]
|
||||
|
||||
describe "when the grammar is updated", ->
|
||||
it "retokenizes existing buffers that contain tokens that match the injection selector", ->
|
||||
@@ -3685,7 +3708,7 @@ describe "TextEditor", ->
|
||||
|
||||
{tokens} = editor.tokenizedLineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('package-with-injection-selector')
|
||||
@@ -3693,7 +3716,7 @@ describe "TextEditor", ->
|
||||
runs ->
|
||||
{tokens} = editor.tokenizedLineForScreenRow(0)
|
||||
expect(tokens[1].value).toBe " SELECT * FROM OCTOCATS"
|
||||
expect(tokens[1].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
expect(tokens[1].scopes).toEqual ["source.js", "comment.line.double-slash.js"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-sql')
|
||||
@@ -3701,7 +3724,7 @@ describe "TextEditor", ->
|
||||
runs ->
|
||||
{tokens} = editor.tokenizedLineForScreenRow(0)
|
||||
expect(tokens[2].value).toBe "SELECT"
|
||||
expect(tokens[2].scopeDescriptor).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
|
||||
expect(tokens[2].scopes).toEqual ["source.js", "comment.line.double-slash.js", "keyword.other.DML.sql"]
|
||||
|
||||
describe ".normalizeTabsInBufferRange()", ->
|
||||
it "normalizes tabs depending on the editor's soft tab/tab length settings", ->
|
||||
|
||||
@@ -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.theme')).toHaveLength 1
|
||||
expect($('style.theme:eq(0)').attr('id')).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 ->
|
||||
@@ -101,9 +101,9 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style.theme')).toHaveLength 2
|
||||
expect($('style.theme:eq(0)').attr('id')).toMatch /atom-dark-syntax/
|
||||
expect($('style.theme:eq(1)').attr('id')).toMatch /atom-light-syntax/
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
expect($('style[group=theme]:eq(0)').attr('source-path')).toMatch /atom-dark-syntax/
|
||||
expect($('style[group=theme]:eq(1)').attr('source-path')).toMatch /atom-light-syntax/
|
||||
atom.config.set('core.themes', [])
|
||||
|
||||
waitsFor ->
|
||||
@@ -111,7 +111,7 @@ describe "ThemeManager", ->
|
||||
|
||||
runs ->
|
||||
reloadHandler.reset()
|
||||
expect($('style.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'])
|
||||
|
||||
@@ -119,7 +119,7 @@ describe "ThemeManager", ->
|
||||
reloadHandler.callCount == 1
|
||||
|
||||
runs ->
|
||||
expect($('style.theme')).toHaveLength 2
|
||||
expect($('style[group=theme]')).toHaveLength 2
|
||||
importPaths = themeManager.getImportPaths()
|
||||
expect(importPaths.length).toBe 1
|
||||
expect(importPaths[0]).toContain 'atom-dark-ui'
|
||||
@@ -142,8 +142,8 @@ describe "ThemeManager", ->
|
||||
expect(stylesheetAddedHandler).toHaveBeenCalled()
|
||||
expect(stylesheetsChangedHandler).toHaveBeenCalled()
|
||||
|
||||
element = $('head style[id*="css.css"]')
|
||||
expect(element.attr('id')).toBe themeManager.stringToId(cssPath)
|
||||
element = $('head style[source-path*="css.css"]')
|
||||
expect(element.attr('source-path')).toBe themeManager.stringToId(cssPath)
|
||||
expect(element.text()).toBe fs.readFileSync(cssPath, 'utf8')
|
||||
expect(element[0].sheet).toBe stylesheetAddedHandler.argsForCall[0][0]
|
||||
|
||||
@@ -159,8 +159,8 @@ describe "ThemeManager", ->
|
||||
themeManager.requireStylesheet(lessPath)
|
||||
expect($('head style').length).toBe lengthBefore + 1
|
||||
|
||||
element = $('head style[id*="sample.less"]')
|
||||
expect(element.attr('id')).toBe themeManager.stringToId(lessPath)
|
||||
element = $('head style[source-path*="sample.less"]')
|
||||
expect(element.attr('source-path')).toBe themeManager.stringToId(lessPath)
|
||||
expect(element.text()).toBe """
|
||||
#header {
|
||||
color: #4d926f;
|
||||
@@ -178,9 +178,9 @@ describe "ThemeManager", ->
|
||||
|
||||
it "supports requiring css and less stylesheets without an explicit extension", ->
|
||||
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'css')
|
||||
expect($('head style[id*="css.css"]').attr('id')).toBe themeManager.stringToId(atom.project.resolve('css.css'))
|
||||
expect($('head style[source-path*="css.css"]').attr('source-path')).toBe themeManager.stringToId(atom.project.resolve('css.css'))
|
||||
themeManager.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
|
||||
expect($('head style[id*="sample.less"]').attr('id')).toBe themeManager.stringToId(atom.project.resolve('sample.less'))
|
||||
expect($('head style[source-path*="sample.less"]').attr('source-path')).toBe themeManager.stringToId(atom.project.resolve('sample.less'))
|
||||
|
||||
$('head style[id*="css.css"]').remove()
|
||||
$('head style[id*="sample.less"]').remove()
|
||||
@@ -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 ->
|
||||
|
||||
@@ -51,12 +51,12 @@ describe "TokenizedBuffer", ->
|
||||
it "initially creates un-tokenized screen lines, then tokenizes lines chunk at a time in the background", ->
|
||||
line0 = tokenizedBuffer.tokenizedLineForRow(0)
|
||||
expect(line0.tokens.length).toBe 1
|
||||
expect(line0.tokens[0]).toEqual(value: line0.text, scopeDescriptor: ['source.js'])
|
||||
expect(line0.tokens[0]).toEqual(value: line0.text, scopes: ['source.js'])
|
||||
|
||||
line11 = tokenizedBuffer.tokenizedLineForRow(11)
|
||||
expect(line11.tokens.length).toBe 2
|
||||
expect(line11.tokens[0]).toEqual(value: " ", scopeDescriptor: ['source.js'], isAtomic: true)
|
||||
expect(line11.tokens[1]).toEqual(value: "return sort(Array.apply(this, arguments));", scopeDescriptor: ['source.js'])
|
||||
expect(line11.tokens[0]).toEqual(value: " ", scopes: ['source.js'], isAtomic: true)
|
||||
expect(line11.tokens[1]).toEqual(value: "return sort(Array.apply(this, arguments));", scopes: ['source.js'])
|
||||
|
||||
# background tokenization has not begun
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack).toBeUndefined()
|
||||
@@ -149,10 +149,10 @@ describe "TokenizedBuffer", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
buffer.setTextInRange([[0, 0], [2, 0]], "foo()\n7\n")
|
||||
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1]).toEqual(value: '(', scopeDescriptor: ['source.js', 'meta.brace.round.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: '7', scopeDescriptor: ['source.js', 'constant.numeric.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.brace.round.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.js'])
|
||||
# line 2 is unchanged
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'if', scopeDescriptor: ['source.js', 'keyword.control.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
@@ -164,7 +164,7 @@ describe "TokenizedBuffer", ->
|
||||
buffer.insert([5, 30], '/* */')
|
||||
changeHandler.reset()
|
||||
buffer.insert([2, 0], '/*')
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopeDescriptor).toEqual ['source.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js']
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
@@ -172,9 +172,9 @@ describe "TokenizedBuffer", ->
|
||||
changeHandler.reset()
|
||||
|
||||
advanceClock()
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
@@ -185,23 +185,23 @@ describe "TokenizedBuffer", ->
|
||||
buffer.insert([5, 0], '*/')
|
||||
|
||||
buffer.insert([1, 0], 'var ')
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
|
||||
describe "when lines are both updated and removed", ->
|
||||
it "updates tokens to reflect the change", ->
|
||||
buffer.setTextInRange([[1, 0], [3, 0]], "foo()")
|
||||
|
||||
# previous line 0 remains
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopeDescriptor: ['source.js', 'storage.modifier.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
# previous line 3 should be combined with input to form line 1
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopeDescriptor: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[6]).toEqual(value: '=', scopeDescriptor: ['source.js', 'keyword.operator.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[6]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js'])
|
||||
|
||||
# lines below deleted regions should be shifted upward
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'while', scopeDescriptor: ['source.js', 'keyword.control.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[4]).toEqual(value: '=', scopeDescriptor: ['source.js', 'keyword.operator.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: '<', scopeDescriptor: ['source.js', 'keyword.operator.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'while', scopes: ['source.js', 'keyword.control.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: '<', scopes: ['source.js', 'keyword.operator.js'])
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
@@ -214,8 +214,8 @@ describe "TokenizedBuffer", ->
|
||||
changeHandler.reset()
|
||||
|
||||
buffer.setTextInRange([[2, 0], [3, 0]], '/*')
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopeDescriptor).toEqual ['source.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js']
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
@@ -223,8 +223,8 @@ describe "TokenizedBuffer", ->
|
||||
changeHandler.reset()
|
||||
|
||||
advanceClock()
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
@@ -235,19 +235,19 @@ describe "TokenizedBuffer", ->
|
||||
buffer.setTextInRange([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()")
|
||||
|
||||
# previous line 0 remains
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopeDescriptor: ['source.js', 'storage.modifier.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
# 3 new lines inserted
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopeDescriptor: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0]).toEqual(value: 'bar', scopeDescriptor: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0]).toEqual(value: 'baz', scopeDescriptor: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0]).toEqual(value: 'bar', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0]).toEqual(value: 'baz', scopes: ['source.js'])
|
||||
|
||||
# previous line 2 is joined with quux() on line 4
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0]).toEqual(value: 'quux', scopeDescriptor: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: 'if', scopeDescriptor: ['source.js', 'keyword.control.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0]).toEqual(value: 'quux', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
|
||||
|
||||
# previous line 3 is pushed down to become line 5
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[4]).toEqual(value: '=', scopeDescriptor: ['source.js', 'keyword.operator.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[4]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.js'])
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
@@ -264,17 +264,17 @@ describe "TokenizedBuffer", ->
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
delete event.bufferChange
|
||||
expect(event).toEqual(start: 2, end: 2, delta: 2)
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopeDescriptor).toEqual ['source.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js']
|
||||
changeHandler.reset()
|
||||
|
||||
advanceClock() # tokenize invalidated lines in background
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).tokens[0].scopeDescriptor).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).tokens[0].scopeDescriptor).not.toBe ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(6).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(7).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(8).tokens[0].scopes).not.toBe ['source.js', 'comment.block.js']
|
||||
|
||||
expect(changeHandler).toHaveBeenCalled()
|
||||
[event] = changeHandler.argsForCall[0]
|
||||
@@ -343,7 +343,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokens[0].value).toBe "#"
|
||||
expect(tokens[1].value).toBe " Econ 101"
|
||||
expect(tokens[2].value).toBe tabAsSpaces
|
||||
expect(tokens[2].scopeDescriptor).toEqual tokens[1].scopeDescriptor
|
||||
expect(tokens[2].scopes).toEqual tokens[1].scopes
|
||||
expect(tokens[2].isAtomic).toBeTruthy()
|
||||
expect(tokens[3].value).toBe ""
|
||||
|
||||
@@ -526,7 +526,7 @@ describe "TokenizedBuffer", ->
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
{tokens} = tokenizedBuffer.tokenizedLineForRow(0)
|
||||
expect(tokens[0]).toEqual value: "<div class='name'>", scopeDescriptor: ["text.html.ruby"]
|
||||
expect(tokens[0]).toEqual value: "<div class='name'>", scopes: ["text.html.ruby"]
|
||||
|
||||
waitsForPromise ->
|
||||
atom.packages.activatePackage('language-html')
|
||||
@@ -534,7 +534,7 @@ describe "TokenizedBuffer", ->
|
||||
runs ->
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
{tokens} = tokenizedBuffer.tokenizedLineForRow(0)
|
||||
expect(tokens[0]).toEqual value: '<', scopeDescriptor: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
|
||||
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby","meta.tag.block.any.html","punctuation.definition.tag.begin.html"]
|
||||
|
||||
describe ".tokenForPosition(position)", ->
|
||||
afterEach ->
|
||||
@@ -545,9 +545,9 @@ describe "TokenizedBuffer", ->
|
||||
buffer = atom.project.bufferForPathSync('sample.js')
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
expect(tokenizedBuffer.tokenForPosition([1,0]).scopeDescriptor).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,1]).scopeDescriptor).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,2]).scopeDescriptor).toEqual ["source.js", "storage.modifier.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,0]).scopes).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,1]).scopes).toEqual ["source.js"]
|
||||
expect(tokenizedBuffer.tokenForPosition([1,2]).scopes).toEqual ["source.js", "storage.modifier.js"]
|
||||
|
||||
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
|
||||
beforeEach ->
|
||||
|
||||
@@ -28,7 +28,7 @@ describe "TokenizedLine", ->
|
||||
ensureValidScopeTree(child, scopeDescriptor.concat([scopeTree.scope]))
|
||||
else
|
||||
expect(scopeTree).toBe tokens[tokenIndex++]
|
||||
expect(scopeDescriptor).toEqual scopeTree.scopeDescriptor
|
||||
expect(scopeDescriptor).toEqual scopeTree.scopes
|
||||
|
||||
waitsForPromise ->
|
||||
atom.project.open('coffee.coffee').then (o) -> editor = o
|
||||
|
||||
@@ -456,3 +456,39 @@ describe "Workspace", ->
|
||||
|
||||
expect(item2.isModified()).toBe false
|
||||
expect(atom.setDocumentEdited).toHaveBeenCalledWith(false)
|
||||
|
||||
describe "adding panels", ->
|
||||
class TestPanel
|
||||
constructior: ->
|
||||
|
||||
describe '::addLeftPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
atom.workspace.panelContainers.left.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = atom.workspace.addLeftPanel(item: new TestPanel())
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
describe '::addRightPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
atom.workspace.panelContainers.right.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = atom.workspace.addRightPanel(item: new TestPanel())
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
describe '::addTopPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
atom.workspace.panelContainers.top.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = atom.workspace.addTopPanel(item: new TestPanel())
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
describe '::addBottomPanel(model)', ->
|
||||
it 'adds a panel to the correct panel container', ->
|
||||
atom.workspace.panelContainers.bottom.onDidAddPanel addPanelSpy = jasmine.createSpy()
|
||||
panel = atom.workspace.addBottomPanel(item: new TestPanel())
|
||||
|
||||
expect(panel).toBeDefined()
|
||||
expect(addPanelSpy).toHaveBeenCalledWith({panel, index: 0})
|
||||
|
||||
@@ -270,3 +270,19 @@ describe "WorkspaceView", ->
|
||||
atom.config.set('editor.lineHeight', '30px')
|
||||
expect(getComputedStyle(editorNode).lineHeight).toBe atom.config.get('editor.lineHeight')
|
||||
expect(editor.getLineHeightInPixels()).not.toBe initialLineHeight
|
||||
|
||||
describe 'panel containers', ->
|
||||
workspaceElement = null
|
||||
beforeEach ->
|
||||
workspaceElement = atom.workspace.getView(atom.workspace)
|
||||
|
||||
it 'inserts panel container elements in the correct places in the DOM', ->
|
||||
leftContainer = workspaceElement.querySelector('atom-panel-container[location="left"]')
|
||||
rightContainer = workspaceElement.querySelector('atom-panel-container[location="right"]')
|
||||
expect(leftContainer.nextSibling).toBe workspaceElement.verticalAxis
|
||||
expect(rightContainer.previousSibling).toBe workspaceElement.verticalAxis
|
||||
|
||||
topContainer = workspaceElement.querySelector('atom-panel-container[location="top"]')
|
||||
bottomContainer = workspaceElement.querySelector('atom-panel-container[location="bottom"]')
|
||||
expect(topContainer.nextSibling).toBe workspaceElement.paneContainer
|
||||
expect(bottomContainer.previousSibling).toBe workspaceElement.paneContainer
|
||||
|
||||
+13
-3
@@ -14,6 +14,7 @@ fs = require 'fs-plus'
|
||||
|
||||
{$} = require './space-pen-extensions'
|
||||
WindowEventHandler = require './window-event-handler'
|
||||
StylesElement = require './styles-element'
|
||||
|
||||
# Essential: Atom global for dealing with packages, themes, menus, and the window.
|
||||
#
|
||||
@@ -29,7 +30,10 @@ class Atom extends Model
|
||||
#
|
||||
# Returns an Atom instance, fully initialized
|
||||
@loadOrCreate: (mode) ->
|
||||
@deserialize(@loadState(mode)) ? new this({mode, @version})
|
||||
startTime = Date.now()
|
||||
atom = @deserialize(@loadState(mode)) ? new this({mode, @version})
|
||||
atom.deserializeTimings.atom = Date.now() - startTime
|
||||
atom
|
||||
|
||||
# Deserializes the Atom environment from a state object
|
||||
@deserialize: (state) ->
|
||||
@@ -103,7 +107,7 @@ class Atom extends Model
|
||||
Section: Properties
|
||||
###
|
||||
|
||||
# Experimental: A {CommandRegistry} instance
|
||||
# Public: A {CommandRegistry} instance
|
||||
commands: null
|
||||
|
||||
# Public: A {Config} instance
|
||||
@@ -152,6 +156,7 @@ class Atom extends Model
|
||||
{@mode} = @state
|
||||
DeserializerManager = require './deserializer-manager'
|
||||
@deserializers = new DeserializerManager()
|
||||
@deserializeTimings = {}
|
||||
|
||||
# Sets up the basic services that should be available in all modes
|
||||
# (both spec and application).
|
||||
@@ -182,6 +187,7 @@ class Atom extends Model
|
||||
Clipboard = require './clipboard'
|
||||
Syntax = require './syntax'
|
||||
ThemeManager = require './theme-manager'
|
||||
StyleManager = require './style-manager'
|
||||
ContextMenuManager = require './context-menu-manager'
|
||||
MenuManager = require './menu-manager'
|
||||
{devMode, safeMode, resourcePath} = @getLoadSettings()
|
||||
@@ -196,11 +202,16 @@ class Atom extends Model
|
||||
# Make react.js faster
|
||||
process.env.NODE_ENV ?= 'production' unless devMode
|
||||
|
||||
# Set Atom's home so packages don't have to guess it
|
||||
process.env.ATOM_HOME = configDirPath
|
||||
|
||||
@config = new Config({configDirPath, resourcePath})
|
||||
@keymaps = new KeymapManager({configDirPath, resourcePath})
|
||||
@keymap = @keymaps # Deprecated
|
||||
@commands = new CommandRegistry
|
||||
@packages = new PackageManager({devMode, configDirPath, resourcePath, safeMode})
|
||||
@styles = new StyleManager
|
||||
document.head.appendChild(new StylesElement)
|
||||
@themes = new ThemeManager({packageManager: @packages, configDirPath, resourcePath, safeMode})
|
||||
@contextMenu = new ContextMenuManager({resourcePath, devMode})
|
||||
@menu = new MenuManager({resourcePath})
|
||||
@@ -597,7 +608,6 @@ class Atom extends Model
|
||||
delete @state.packageStates
|
||||
|
||||
deserializeEditorWindow: ->
|
||||
@deserializeTimings = {}
|
||||
@deserializePackageStates()
|
||||
@deserializeProject()
|
||||
@deserializeWorkspaceView()
|
||||
|
||||
@@ -10,24 +10,48 @@ _ = require 'underscore-plus'
|
||||
module.exports =
|
||||
class ApplicationMenu
|
||||
constructor: (@version) ->
|
||||
@menu = Menu.buildFromTemplate @getDefaultTemplate()
|
||||
Menu.setApplicationMenu @menu
|
||||
@windowTemplates = new WeakMap()
|
||||
@setActiveTemplate(@getDefaultTemplate())
|
||||
global.atomApplication.autoUpdateManager.on 'state-changed', (state) =>
|
||||
@showUpdateMenuItem(state)
|
||||
|
||||
# Public: Updates the entire menu with the given keybindings.
|
||||
#
|
||||
# window - The BrowserWindow this menu template is associated with.
|
||||
# template - The Object which describes the menu to display.
|
||||
# keystrokesByCommand - An Object where the keys are commands and the values
|
||||
# are Arrays containing the keystroke.
|
||||
update: (template, keystrokesByCommand) ->
|
||||
update: (window, template, keystrokesByCommand) ->
|
||||
@translateTemplate(template, keystrokesByCommand)
|
||||
@substituteVersion(template)
|
||||
@menu = Menu.buildFromTemplate(template)
|
||||
Menu.setApplicationMenu(@menu)
|
||||
@windowTemplates.set(window, template)
|
||||
@setActiveTemplate(template) if window is @lastFocusedWindow
|
||||
|
||||
setActiveTemplate: (template) ->
|
||||
unless _.isEqual(template, @activeTemplate)
|
||||
@activeTemplate = template
|
||||
@menu = Menu.buildFromTemplate(_.deepClone(template))
|
||||
Menu.setApplicationMenu(@menu)
|
||||
|
||||
@showUpdateMenuItem(global.atomApplication.autoUpdateManager.getState())
|
||||
|
||||
# Register a BrowserWindow with this application menu.
|
||||
addWindow: (window) ->
|
||||
@lastFocusedWindow ?= window
|
||||
|
||||
focusHandler = =>
|
||||
@lastFocusedWindow = window
|
||||
if template = @windowTemplates.get(window)
|
||||
@setActiveTemplate(template)
|
||||
|
||||
window.on 'focus', focusHandler
|
||||
window.once 'closed', =>
|
||||
@lastFocusedWindow = null if window is @lastFocusedWindow
|
||||
@windowTemplates.delete(window)
|
||||
window.removeListener 'focus', focusHandler
|
||||
|
||||
@enableWindowSpecificItems(true)
|
||||
|
||||
# Flattens the given menu and submenu items into an single Array.
|
||||
#
|
||||
# menu - A complete menu configuration object for atom-shell's menu API.
|
||||
|
||||
@@ -97,7 +97,7 @@ class AtomApplication
|
||||
# Public: Adds the {AtomWindow} to the global window list.
|
||||
addWindow: (window) ->
|
||||
@windows.push window
|
||||
@applicationMenu?.enableWindowSpecificItems(true)
|
||||
@applicationMenu?.addWindow(window.browserWindow)
|
||||
window.once 'window:loaded', =>
|
||||
@autoUpdateManager.emitUpdateAvailableEvent(window)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -215,7 +221,8 @@ class AtomApplication
|
||||
@promptForPath({window})
|
||||
|
||||
ipc.on 'update-application-menu', (event, template, keystrokesByCommand) =>
|
||||
@applicationMenu.update(template, keystrokesByCommand)
|
||||
win = BrowserWindow.fromWebContents(event.sender)
|
||||
@applicationMenu.update(win, template, keystrokesByCommand)
|
||||
|
||||
ipc.on 'run-package-specs', (event, specDirectory) =>
|
||||
@runSpecs({resourcePath: global.devResourcePath, specDirectory: specDirectory, exitWhenDone: false})
|
||||
|
||||
@@ -78,13 +78,18 @@ parseCommandLine = ->
|
||||
|
||||
Folder paths will open in an existing window if that folder has already been
|
||||
opened or a new window if it hasn't.
|
||||
|
||||
Environment Variables:
|
||||
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
|
||||
Defaults to `~/github/atom`.
|
||||
"""
|
||||
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
|
||||
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.')
|
||||
options.alias('h', 'help').boolean('h').describe('h', 'Print this usage message.')
|
||||
options.alias('l', 'log-file').string('l').describe('l', 'Log all output to file.')
|
||||
options.alias('n', 'new-window').boolean('n').describe('n', 'Open a new window.')
|
||||
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the spec directory (default: Atom\'s spec directory).')
|
||||
options.alias('r', 'resource-path').string('r').describe('r', 'Set the path to the Atom source directory and enable dev-mode.')
|
||||
options.alias('s', 'spec-directory').string('s').describe('s', 'Set the directory from which to run package specs (default: Atom\'s spec directory).')
|
||||
options.boolean('safe').describe('safe', 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.')
|
||||
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
|
||||
options.alias('v', 'version').boolean('v').describe('v', 'Print the version.')
|
||||
@@ -113,8 +118,18 @@ parseCommandLine = ->
|
||||
if args['resource-path']
|
||||
devMode = true
|
||||
resourcePath = args['resource-path']
|
||||
else if devMode
|
||||
resourcePath = global.devResourcePath
|
||||
else
|
||||
# Set resourcePath based on the specDirectory if running specs on atom core
|
||||
if specDirectory?
|
||||
packageDirectoryPath = path.join(specDirectory, '..')
|
||||
packageManifestPath = path.join(packageDirectoryPath, 'package.json')
|
||||
if fs.statSyncNoException(packageManifestPath)
|
||||
try
|
||||
packageManifest = JSON.parse(fs.readFileSync(packageManifestPath))
|
||||
resourcePath = packageDirectoryPath if packageManifest.name is 'atom'
|
||||
|
||||
if devMode
|
||||
resourcePath ?= global.devResourcePath
|
||||
|
||||
unless fs.statSyncNoException(resourcePath)
|
||||
resourcePath = path.dirname(path.dirname(__dirname))
|
||||
|
||||
@@ -45,3 +45,11 @@ module.exports =
|
||||
writable: false
|
||||
value: requireCoffeeScript
|
||||
})
|
||||
addPathToCache: (filePath) ->
|
||||
extension = path.extname(filePath)
|
||||
if extension is '.coffee'
|
||||
content = fs.readFileSync(filePath, 'utf8')
|
||||
cachePath = getCachePath(coffee)
|
||||
compileCoffeeScript(coffee, filePath, cachePath)
|
||||
else if extension is '.cson'
|
||||
CSON.readFileSync(filePath)
|
||||
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -128,3 +128,7 @@ module.exports =
|
||||
cr:
|
||||
type: ['boolean', 'string']
|
||||
default: '\u00a4'
|
||||
zoomFontWhenCtrlScrolling:
|
||||
type: 'boolean'
|
||||
default: process.platform isnt 'darwin'
|
||||
description: 'Increase/decrease the editor font size when pressing the Ctrl key and scrolling the mouse up/down.'
|
||||
|
||||
+121
-43
@@ -9,6 +9,7 @@ pathWatcher = require 'pathwatcher'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
ScopedPropertyStore = require 'scoped-property-store'
|
||||
ScopeDescriptor = require './scope-descriptor'
|
||||
|
||||
# Essential: Used to access all of Atom's configuration details.
|
||||
#
|
||||
@@ -313,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')
|
||||
@@ -335,9 +337,11 @@ class Config
|
||||
# # do stuff with value
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {Array} of {String}s describing a path from
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` {String} name of the key to observe
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
# * `value` the new value of the key
|
||||
@@ -349,7 +353,7 @@ class Config
|
||||
if args.length is 2
|
||||
# observe(keyPath, callback)
|
||||
[keyPath, callback, scopeDescriptor, options] = args
|
||||
else if args.length is 3 and Array.isArray(scopeDescriptor)
|
||||
else if args.length is 3 and (Array.isArray(scopeDescriptor) or scopeDescriptor instanceof ScopeDescriptor)
|
||||
# observe(scopeDescriptor, keyPath, callback)
|
||||
[scopeDescriptor, keyPath, callback, options] = args
|
||||
else if args.length is 3 and _.isString(scopeDescriptor) and _.isObject(keyPath)
|
||||
@@ -371,9 +375,11 @@ class Config
|
||||
# Essential: Add a listener for changes to a given key path. If `keyPath` is
|
||||
# not specified, your callback will be called on changes to any key.
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {Array} of {String}s describing a path from
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}. See {::get} for examples.
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` (optional) {String} name of the key to observe. Must be
|
||||
# specified if `scopeDescriptor` is specified.
|
||||
# * `callback` {Function} to call when the value of the key changes.
|
||||
@@ -440,9 +446,11 @@ class Config
|
||||
# atom.config.get(scopeDescriptor, 'editor.tabLength') # => 2
|
||||
# ```
|
||||
#
|
||||
# * `scopeDescriptor` (optional) {Array} of {String}s describing a path from
|
||||
# * `scopeDescriptor` (optional) {ScopeDescriptor} describing a path from
|
||||
# the root of the syntax tree to a token. Get one by calling
|
||||
# {editor.getLastCursor().getScopeDescriptor()}
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key to retrieve.
|
||||
#
|
||||
# Returns the value from Atom's default settings, the user's configuration
|
||||
@@ -486,7 +494,9 @@ class Config
|
||||
# atom.config.get(['source.js'], 'editor.tabLength') # => 4
|
||||
# ```
|
||||
#
|
||||
# * `scope` (optional) {String}. eg. '.source.ruby'
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# See [the scopes docs](https://atom.io/docs/latest/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
# * `keyPath` The {String} name of the key.
|
||||
# * `value` The value of the setting. Passing `undefined` will revert the
|
||||
# setting to the default value.
|
||||
@@ -494,11 +504,11 @@ class Config
|
||||
# Returns a {Boolean}
|
||||
# * `true` if the value was set.
|
||||
# * `false` if the value was not able to be coerced to the type specified in the setting's schema.
|
||||
set: (scope, keyPath, value) ->
|
||||
set: (scopeSelector, keyPath, value) ->
|
||||
if arguments.length < 3
|
||||
value = keyPath
|
||||
keyPath = scope
|
||||
scope = undefined
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = undefined
|
||||
|
||||
unless value == undefined
|
||||
try
|
||||
@@ -506,8 +516,8 @@ class Config
|
||||
catch e
|
||||
return false
|
||||
|
||||
if scope?
|
||||
@setRawScopedValue(scope, keyPath, value)
|
||||
if scopeSelector?
|
||||
@setRawScopedValue(scopeSelector, keyPath, value)
|
||||
else
|
||||
@setRawValue(keyPath, value)
|
||||
|
||||
@@ -519,29 +529,59 @@ class Config
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns the new value.
|
||||
restoreDefault: (keyPath) ->
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
@get(keyPath)
|
||||
restoreDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
@scopedSettingsStore.removePropertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
_.setValueForKeyPath(settings, keyPath, undefined)
|
||||
@addScopedSettings('user-config', scopeSelector, settings, @usersScopedSettingPriority)
|
||||
@save() unless @configFileHasErrors
|
||||
@getDefault(scopeSelector, keyPath)
|
||||
else
|
||||
@set(keyPath, _.valueForKeyPath(@defaultSettings, keyPath))
|
||||
@get(keyPath)
|
||||
|
||||
# Extended: Get the global default value of the key path. _Please note_ that in most
|
||||
# cases calling this is not necessary! {::get} returns the default value when
|
||||
# a custom value is not specified.
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns the default value.
|
||||
getDefault: (keyPath) ->
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
getDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
defaultValue = @scopedSettingsStore.getPropertyValue(scopeSelector, keyPath, excludeSources: ['user-config'])
|
||||
defaultValue ?= _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
else
|
||||
defaultValue = _.valueForKeyPath(@defaultSettings, keyPath)
|
||||
_.deepClone(defaultValue)
|
||||
|
||||
# Extended: Is the value at `keyPath` its default value?
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
# * `keyPath` The {String} name of the key.
|
||||
#
|
||||
# Returns a {Boolean}, `true` if the current value is the default, `false`
|
||||
# otherwise.
|
||||
isDefault: (keyPath) ->
|
||||
not _.valueForKeyPath(@settings, keyPath)?
|
||||
isDefault: (scopeSelector, keyPath) ->
|
||||
if arguments.length == 1
|
||||
keyPath = scopeSelector
|
||||
scopeSelector = null
|
||||
|
||||
if scopeSelector?
|
||||
settings = @scopedSettingsStore.propertiesForSourceAndSelector('user-config', scopeSelector)
|
||||
not _.valueForKeyPath(settings, keyPath)?
|
||||
else
|
||||
not _.valueForKeyPath(@settings, keyPath)?
|
||||
|
||||
# Extended: Retrieve the schema for a specific key path. The schema will tell
|
||||
# you what type the keyPath expects, and other metadata about the config
|
||||
@@ -552,7 +592,7 @@ class Config
|
||||
# Returns an {Object} eg. `{type: 'integer', default: 23, minimum: 1}`.
|
||||
# Returns `null` when the keyPath has no schema specified.
|
||||
getSchema: (keyPath) ->
|
||||
keys = keyPath.split('.')
|
||||
keys = splitKeyPath(keyPath)
|
||||
schema = @schema
|
||||
for key in keys
|
||||
break unless schema?
|
||||
@@ -560,9 +600,17 @@ class Config
|
||||
schema
|
||||
|
||||
# Extended: Returns a new {Object} containing all of the global settings and
|
||||
# defaults. This does not include scoped settings.
|
||||
getSettings: ->
|
||||
_.deepExtend(@settings, @defaultSettings)
|
||||
# defaults. Returns the scoped settings when a `scopeSelector` is specified.
|
||||
#
|
||||
# * `scopeSelector` (optional) {String}. eg. '.source.ruby'
|
||||
getSettings: (scopeSelector) ->
|
||||
settings = _.deepExtend(@settings, @defaultSettings)
|
||||
|
||||
if scopeSelector?
|
||||
scopedSettings = @scopedSettingsStore.propertiesForSelector(scopeSelector)
|
||||
settings = _.deepExtend(scopedSettings, settings)
|
||||
|
||||
settings
|
||||
|
||||
# Extended: Get the {String} path to the config file being used.
|
||||
getUserConfigPath: ->
|
||||
@@ -624,7 +672,7 @@ class Config
|
||||
|
||||
rootSchema = @schema
|
||||
if keyPath
|
||||
for key in keyPath.split('.')
|
||||
for key in splitKeyPath(keyPath)
|
||||
rootSchema.type = 'object'
|
||||
rootSchema.properties ?= {}
|
||||
properties = rootSchema.properties
|
||||
@@ -633,6 +681,7 @@ class Config
|
||||
|
||||
_.extend rootSchema, schema
|
||||
@setDefaults(keyPath, @extractDefaultsFromSchema(schema))
|
||||
@setScopedDefaultsFromSchema(keyPath, schema)
|
||||
|
||||
load: ->
|
||||
@initializeConfigDirectory()
|
||||
@@ -708,7 +757,7 @@ class Config
|
||||
|
||||
unsetUnspecifiedValues = (keyPath, value) =>
|
||||
if isPlainObject(value)
|
||||
keys = if keyPath? then keyPath.split('.') else []
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
unsetUnspecifiedValues(keys.concat([key]).join('.'), childValue)
|
||||
@@ -721,7 +770,7 @@ class Config
|
||||
|
||||
setRecursive: (keyPath, value) ->
|
||||
if isPlainObject(value)
|
||||
keys = if keyPath? then keyPath.split('.') else []
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of value
|
||||
continue unless value.hasOwnProperty(key)
|
||||
@setRecursive(keys.concat([key]).join('.'), childValue)
|
||||
@@ -764,8 +813,8 @@ class Config
|
||||
|
||||
isSubKeyPath: (keyPath, subKeyPath) ->
|
||||
return false unless keyPath? and subKeyPath?
|
||||
pathSubTokens = subKeyPath.split('.')
|
||||
pathTokens = keyPath.split('.').slice(0, pathSubTokens.length)
|
||||
pathSubTokens = splitKeyPath(subKeyPath)
|
||||
pathTokens = splitKeyPath(keyPath).slice(0, pathSubTokens.length)
|
||||
_.isEqual(pathTokens, pathSubTokens)
|
||||
|
||||
setRawDefault: (keyPath, value) ->
|
||||
@@ -776,7 +825,7 @@ class Config
|
||||
|
||||
setDefaults: (keyPath, defaults) ->
|
||||
if defaults? and isPlainObject(defaults)
|
||||
keys = if keyPath? then keyPath.split('.') else []
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of defaults
|
||||
continue unless defaults.hasOwnProperty(key)
|
||||
@setDefaults(keys.concat([key]).join('.'), childValue)
|
||||
@@ -787,6 +836,32 @@ class Config
|
||||
catch e
|
||||
console.warn("'#{keyPath}' could not set the default. Attempted default: #{JSON.stringify(defaults)}; Schema: #{JSON.stringify(@getSchema(keyPath))}")
|
||||
|
||||
# `schema` will look something like this
|
||||
#
|
||||
# ```coffee
|
||||
# type: 'string'
|
||||
# default: 'ok'
|
||||
# scopes:
|
||||
# '.source.js':
|
||||
# default: 'omg'
|
||||
# ```
|
||||
setScopedDefaultsFromSchema: (keyPath, schema) ->
|
||||
if schema.scopes? and isPlainObject(schema.scopes)
|
||||
scopedDefaults = {}
|
||||
for scope, scopeSchema of schema.scopes
|
||||
continue unless scopeSchema.hasOwnProperty('default')
|
||||
scopedDefaults[scope] = {}
|
||||
_.setValueForKeyPath(scopedDefaults[scope], keyPath, scopeSchema.default)
|
||||
@scopedSettingsStore.addProperties('schema-default', scopedDefaults)
|
||||
|
||||
if schema.type is 'object' and schema.properties? and isPlainObject(schema.properties)
|
||||
keys = splitKeyPath(keyPath)
|
||||
for key, childValue of schema.properties
|
||||
continue unless schema.properties.hasOwnProperty(key)
|
||||
@setScopedDefaultsFromSchema(keys.concat([key]).join('.'), childValue)
|
||||
|
||||
return
|
||||
|
||||
extractDefaultsFromSchema: (schema) ->
|
||||
if schema.default?
|
||||
schema.default
|
||||
@@ -807,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: (name, selector, value) ->
|
||||
addScopedSettings: (source, selector, value, options) ->
|
||||
settingsBySelector = {}
|
||||
settingsBySelector[selector] = value
|
||||
disposable = @scopedSettingsStore.addProperties(name, settingsBySelector)
|
||||
disposable = @scopedSettingsStore.addProperties(source, settingsBySelector, options)
|
||||
@emitter.emit 'did-change'
|
||||
new Disposable =>
|
||||
disposable.dispose()
|
||||
@@ -827,16 +902,12 @@ 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) ->
|
||||
scopeChain = scopeDescriptor
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope[0] is '.'
|
||||
scope
|
||||
.join(' ')
|
||||
@scopedSettingsStore.getPropertyValue(scopeChain, keyPath)
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getPropertyValue(scopeDescriptor.getScopeChain(), keyPath)
|
||||
|
||||
observeScopedKeyPath: (scopeDescriptor, keyPath, callback) ->
|
||||
oldValue = @get(scopeDescriptor, keyPath)
|
||||
@@ -863,12 +934,8 @@ class Config
|
||||
# * language mode uses it for one thing.
|
||||
# * autocomplete uses it for editor.completions
|
||||
settingsForScopeDescriptor: (scopeDescriptor, keyPath) ->
|
||||
scopeChain = scopeDescriptor
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope[0] is '.'
|
||||
scope
|
||||
.join(' ')
|
||||
@scopedSettingsStore.getProperties(scopeChain, keyPath)
|
||||
scopeDescriptor = ScopeDescriptor.fromObject(scopeDescriptor)
|
||||
@scopedSettingsStore.getProperties(scopeDescriptor.getScopeChain(), keyPath)
|
||||
|
||||
# Base schema enforcers. These will coerce raw input into the specified type,
|
||||
# and will throw an error when the value cannot be coerced. Throwing the error
|
||||
@@ -968,3 +1035,14 @@ Config.addSchemaEnforcers
|
||||
|
||||
isPlainObject = (value) ->
|
||||
_.isObject(value) and not _.isArray(value) and not _.isFunction(value) and not _.isString(value)
|
||||
|
||||
splitKeyPath = (keyPath) ->
|
||||
return [] unless keyPath?
|
||||
startIndex = 0
|
||||
keyPathArray = []
|
||||
for char, i in keyPath
|
||||
if char is '.' and (i is 0 or keyPath[i-1] != '\\')
|
||||
keyPathArray.push keyPath.substring(startIndex, i)
|
||||
startIndex = i + 1
|
||||
keyPathArray.push keyPath.substr(startIndex, keyPath.length)
|
||||
keyPathArray
|
||||
|
||||
+2
-2
@@ -216,12 +216,12 @@ class Cursor extends Model
|
||||
|
||||
# Public: Retrieves the scope descriptor for the cursor's current position.
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
# Returns a {ScopeDescriptor}
|
||||
getScopeDescriptor: ->
|
||||
@editor.scopeDescriptorForBufferPosition(@getBufferPosition())
|
||||
getScopes: ->
|
||||
Grim.deprecate 'Use Cursor::getScopeDescriptor() instead'
|
||||
@getScopeDescriptor()
|
||||
@getScopeDescriptor().getScopesArray()
|
||||
|
||||
# Public: Returns true if this cursor has no non-whitespace characters before
|
||||
# its current position.
|
||||
|
||||
@@ -650,11 +650,21 @@ class DisplayBuffer extends Model
|
||||
left = 0
|
||||
column = 0
|
||||
for token in @tokenizedLineForScreenRow(targetRow).tokens
|
||||
charWidths = @getScopedCharWidths(token.scopeDescriptor)
|
||||
for char in token.value
|
||||
charWidths = @getScopedCharWidths(token.scopes)
|
||||
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) ->
|
||||
@@ -662,18 +672,29 @@ class DisplayBuffer extends Model
|
||||
targetLeft = pixelPosition.left
|
||||
defaultCharWidth = @defaultCharWidth
|
||||
row = Math.floor(targetTop / @getLineHeightInPixels())
|
||||
targetLeft = Infinity if row > @getLastRow()
|
||||
row = Math.min(row, @getLastRow())
|
||||
row = Math.max(0, row)
|
||||
|
||||
left = 0
|
||||
column = 0
|
||||
for token in @tokenizedLineForScreenRow(row).tokens
|
||||
charWidths = @getScopedCharWidths(token.scopeDescriptor)
|
||||
for char in token.value
|
||||
charWidths = @getScopedCharWidths(token.scopes)
|
||||
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)
|
||||
|
||||
@@ -714,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]
|
||||
@@ -756,7 +781,7 @@ class DisplayBuffer extends Model
|
||||
#
|
||||
# bufferPosition - A {Point} in the {TextBuffer}
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
# Returns a {ScopeDescriptor}.
|
||||
scopeDescriptorForBufferPosition: (bufferPosition) ->
|
||||
@tokenizedBuffer.scopeDescriptorForPosition(bufferPosition)
|
||||
|
||||
@@ -1051,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()
|
||||
|
||||
|
||||
@@ -200,7 +200,7 @@ LinesComponent = React.createClass
|
||||
firstTrailingWhitespacePosition = text.search(/\s*$/)
|
||||
lineIsWhitespaceOnly = firstTrailingWhitespacePosition is 0
|
||||
for token in tokens
|
||||
innerHTML += @updateScopeStack(scopeStack, token.scopeDescriptor)
|
||||
innerHTML += @updateScopeStack(scopeStack, token.scopes)
|
||||
hasIndentGuide = not mini and showIndentGuide and (token.hasLeadingWhitespace() or (token.hasTrailingWhitespace() and lineIsWhitespaceOnly))
|
||||
innerHTML += token.getValueAsHtml({hasIndentGuide})
|
||||
|
||||
@@ -308,10 +308,20 @@ LinesComponent = React.createClass
|
||||
iterator = null
|
||||
charIndex = 0
|
||||
|
||||
for {value, scopeDescriptor}, tokenIndex in tokenizedLine.tokens
|
||||
charWidths = editor.getScopedCharWidths(scopeDescriptor)
|
||||
for {value, scopes, hasPairedCharacter} in tokenizedLine.tokens
|
||||
charWidths = editor.getScopedCharWidths(scopes)
|
||||
|
||||
valueIndex = 0
|
||||
while valueIndex < value.length
|
||||
if hasPairedCharacter
|
||||
char = value.substr(valueIndex, 2)
|
||||
charLength = 2
|
||||
valueIndex += 2
|
||||
else
|
||||
char = value[valueIndex]
|
||||
charLength = 1
|
||||
valueIndex++
|
||||
|
||||
for char in value
|
||||
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(scopeDescriptor, char, charWidth)
|
||||
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
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
Module = require 'module'
|
||||
path = require 'path'
|
||||
semver = require 'semver'
|
||||
|
||||
# Extend semver.Range to memoize matched versions for speed
|
||||
class Range extends semver.Range
|
||||
constructor: ->
|
||||
super
|
||||
@matchedVersions = new Set()
|
||||
@unmatchedVersions = new Set()
|
||||
|
||||
test: (version) ->
|
||||
return true if @matchedVersions.has(version)
|
||||
return false if @unmatchedVersions.has(version)
|
||||
|
||||
matches = super
|
||||
if matches
|
||||
@matchedVersions.add(version)
|
||||
else
|
||||
@unmatchedVersions.add(version)
|
||||
matches
|
||||
|
||||
nativeModules = process.binding('natives')
|
||||
|
||||
cache =
|
||||
builtins: {}
|
||||
debug: false
|
||||
dependencies: {}
|
||||
extensions: {}
|
||||
folders: {}
|
||||
ranges: {}
|
||||
registered: false
|
||||
resourcePath: null
|
||||
resourcePathWithTrailingSlash: null
|
||||
|
||||
# isAbsolute is inlined from fs-plus so that fs-plus itself can be required
|
||||
# from this cache.
|
||||
if process.platform is 'win32'
|
||||
isAbsolute = (pathToCheck) ->
|
||||
pathToCheck and (pathToCheck[1] is ':' or (pathToCheck[0] is '\\' and pathToCheck[1] is '\\'))
|
||||
else
|
||||
isAbsolute = (pathToCheck) ->
|
||||
pathToCheck and pathToCheck[0] is '/'
|
||||
|
||||
isCorePath = (pathToCheck) ->
|
||||
pathToCheck.startsWith(cache.resourcePathWithTrailingSlash)
|
||||
|
||||
loadDependencies = (modulePath, rootPath, rootMetadata, moduleCache) ->
|
||||
fs = require 'fs-plus'
|
||||
|
||||
for childPath in fs.listSync(path.join(modulePath, 'node_modules'))
|
||||
continue if path.basename(childPath) is '.bin'
|
||||
continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(path.basename(childPath))
|
||||
|
||||
childMetadataPath = path.join(childPath, 'package.json')
|
||||
continue unless fs.isFileSync(childMetadataPath)
|
||||
|
||||
childMetadata = JSON.parse(fs.readFileSync(childMetadataPath))
|
||||
if childMetadata?.version
|
||||
try
|
||||
mainPath = require.resolve(childPath)
|
||||
|
||||
if mainPath
|
||||
moduleCache.dependencies.push
|
||||
name: childMetadata.name
|
||||
version: childMetadata.version
|
||||
path: path.relative(rootPath, mainPath)
|
||||
|
||||
loadDependencies(childPath, rootPath, rootMetadata, moduleCache)
|
||||
|
||||
return
|
||||
|
||||
loadFolderCompatibility = (modulePath, rootPath, rootMetadata, moduleCache) ->
|
||||
fs = require 'fs-plus'
|
||||
|
||||
metadataPath = path.join(modulePath, 'package.json')
|
||||
return unless fs.isFileSync(metadataPath)
|
||||
|
||||
dependencies = JSON.parse(fs.readFileSync(metadataPath))?.dependencies ? {}
|
||||
|
||||
for name, version of dependencies
|
||||
try
|
||||
new Range(version)
|
||||
catch error
|
||||
delete dependencies[name]
|
||||
|
||||
onDirectory = (childPath) ->
|
||||
path.basename(childPath) isnt 'node_modules'
|
||||
|
||||
extensions = ['.js', '.coffee', '.json', '.node']
|
||||
paths = {}
|
||||
onFile = (childPath) ->
|
||||
if path.extname(childPath) in extensions
|
||||
relativePath = path.relative(rootPath, path.dirname(childPath))
|
||||
paths[relativePath] = true
|
||||
fs.traverseTreeSync(modulePath, onFile, onDirectory)
|
||||
|
||||
paths = Object.keys(paths)
|
||||
if paths.length > 0 and Object.keys(dependencies).length > 0
|
||||
moduleCache.folders.push({paths, dependencies})
|
||||
|
||||
for childPath in fs.listSync(path.join(modulePath, 'node_modules'))
|
||||
continue if path.basename(childPath) is '.bin'
|
||||
continue if rootPath is modulePath and rootMetadata.packageDependencies?.hasOwnProperty(path.basename(childPath))
|
||||
|
||||
loadFolderCompatibility(childPath, rootPath, rootMetadata, moduleCache)
|
||||
|
||||
return
|
||||
|
||||
loadExtensions = (modulePath, rootPath, rootMetadata, moduleCache) ->
|
||||
fs = require 'fs-plus'
|
||||
extensions = ['.js', '.coffee', '.json', '.node']
|
||||
nodeModulesPath = path.join(rootPath, 'node_modules')
|
||||
|
||||
onFile = (filePath) ->
|
||||
filePath = path.relative(rootPath, filePath)
|
||||
segments = filePath.split(path.sep)
|
||||
return if 'test' in segments
|
||||
return if 'tests' in segments
|
||||
return if 'spec' in segments
|
||||
return if 'specs' in segments
|
||||
return if segments.length > 1 and not (segments[0] in ['exports', 'lib', 'node_modules', 'src', 'static', 'vendor'])
|
||||
|
||||
extension = path.extname(filePath)
|
||||
if extension in extensions
|
||||
moduleCache.extensions[extension] ?= []
|
||||
moduleCache.extensions[extension].push(filePath)
|
||||
|
||||
onDirectory = (childPath) ->
|
||||
# Don't include extensions from bundled packages
|
||||
# These are generated and stored in the package's own metadata cache
|
||||
if rootMetadata.name is 'atom'
|
||||
parentPath = path.dirname(childPath)
|
||||
if parentPath is nodeModulesPath
|
||||
packageName = path.basename(childPath)
|
||||
return false if rootMetadata.packageDependencies?.hasOwnProperty(packageName)
|
||||
|
||||
true
|
||||
|
||||
fs.traverseTreeSync(rootPath, onFile, onDirectory)
|
||||
|
||||
return
|
||||
|
||||
satisfies = (version, rawRange) ->
|
||||
unless parsedRange = cache.ranges[rawRange]
|
||||
parsedRange = new Range(rawRange)
|
||||
cache.ranges[rawRange] = parsedRange
|
||||
parsedRange.test(version)
|
||||
|
||||
resolveFilePath = (relativePath, parentModule) ->
|
||||
return unless relativePath
|
||||
return unless parentModule?.filename
|
||||
return unless relativePath[0] is '.' or isAbsolute(relativePath)
|
||||
|
||||
resolvedPath = path.resolve(path.dirname(parentModule.filename), relativePath)
|
||||
return unless isCorePath(resolvedPath)
|
||||
|
||||
extension = path.extname(resolvedPath)
|
||||
if extension
|
||||
return resolvedPath if cache.extensions[extension]?.has(resolvedPath)
|
||||
else
|
||||
for extension, paths of cache.extensions
|
||||
resolvedPathWithExtension = "#{resolvedPath}#{extension}"
|
||||
return resolvedPathWithExtension if paths.has(resolvedPathWithExtension)
|
||||
|
||||
return
|
||||
|
||||
resolveModulePath = (relativePath, parentModule) ->
|
||||
return unless relativePath
|
||||
return unless parentModule?.filename
|
||||
|
||||
return if nativeModules.hasOwnProperty(relativePath)
|
||||
return if relativePath[0] is '.'
|
||||
return if isAbsolute(relativePath)
|
||||
|
||||
folderPath = path.dirname(parentModule.filename)
|
||||
|
||||
range = cache.folders[folderPath]?[relativePath]
|
||||
unless range?
|
||||
if builtinPath = cache.builtins[relativePath]
|
||||
return builtinPath
|
||||
else
|
||||
return
|
||||
|
||||
candidates = cache.dependencies[relativePath]
|
||||
return unless candidates?
|
||||
|
||||
for version, resolvedPath of candidates
|
||||
if Module._cache.hasOwnProperty(resolvedPath) or isCorePath(resolvedPath)
|
||||
return resolvedPath if satisfies(version, range)
|
||||
|
||||
return
|
||||
|
||||
registerBuiltins = (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)
|
||||
cache.builtins.atom ?= path.join(cache.resourcePath, 'exports', 'atom.js')
|
||||
|
||||
atomShellRoot = path.join(process.resourcesPath, 'atom')
|
||||
|
||||
commonRoot = path.join(atomShellRoot, 'common', 'api', 'lib')
|
||||
commonBuiltins = ['callbacks-registry', 'clipboard', 'crash-reporter', 'screen', 'shell']
|
||||
for builtin in commonBuiltins
|
||||
cache.builtins[builtin] = path.join(commonRoot, "#{builtin}.js")
|
||||
|
||||
rendererRoot = path.join(atomShellRoot, 'renderer', 'api', 'lib')
|
||||
rendererBuiltins = ['ipc', 'remote']
|
||||
for builtin in rendererBuiltins
|
||||
cache.builtins[builtin] = path.join(rendererRoot, "#{builtin}.js")
|
||||
|
||||
if cache.debug
|
||||
cache.findPathCount = 0
|
||||
cache.findPathTime = 0
|
||||
cache.loadCount = 0
|
||||
cache.requireTime = 0
|
||||
global.moduleCache = cache
|
||||
|
||||
originalLoad = Module::load
|
||||
Module::load = ->
|
||||
cache.loadCount++
|
||||
originalLoad.apply(this, arguments)
|
||||
|
||||
originalRequire = Module::require
|
||||
Module::require = ->
|
||||
startTime = Date.now()
|
||||
exports = originalRequire.apply(this, arguments)
|
||||
cache.requireTime += Date.now() - startTime
|
||||
exports
|
||||
|
||||
originalFindPath = Module._findPath
|
||||
Module._findPath = (request, paths) ->
|
||||
cacheKey = JSON.stringify({request, paths})
|
||||
cache.findPathCount++ unless Module._pathCache[cacheKey]
|
||||
|
||||
startTime = Date.now()
|
||||
foundPath = originalFindPath.apply(global, arguments)
|
||||
cache.findPathTime += Date.now() - startTime
|
||||
foundPath
|
||||
|
||||
exports.create = (modulePath) ->
|
||||
fs = require 'fs-plus'
|
||||
|
||||
modulePath = fs.realpathSync(modulePath)
|
||||
metadataPath = path.join(modulePath, 'package.json')
|
||||
metadata = JSON.parse(fs.readFileSync(metadataPath))
|
||||
|
||||
moduleCache =
|
||||
version: 1
|
||||
dependencies: []
|
||||
extensions: {}
|
||||
folders: []
|
||||
|
||||
loadDependencies(modulePath, modulePath, metadata, moduleCache)
|
||||
loadFolderCompatibility(modulePath, modulePath, metadata, moduleCache)
|
||||
loadExtensions(modulePath, modulePath, metadata, moduleCache)
|
||||
|
||||
metadata._atomModuleCache = moduleCache
|
||||
fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2))
|
||||
|
||||
return
|
||||
|
||||
exports.register = ({resourcePath, devMode}={}) ->
|
||||
return if cache.registered
|
||||
|
||||
originalResolveFilename = Module._resolveFilename
|
||||
Module._resolveFilename = (relativePath, parentModule) ->
|
||||
resolvedPath = resolveModulePath(relativePath, parentModule)
|
||||
resolvedPath ?= resolveFilePath(relativePath, parentModule)
|
||||
resolvedPath ? originalResolveFilename(relativePath, parentModule)
|
||||
|
||||
cache.registered = true
|
||||
cache.resourcePath = resourcePath
|
||||
cache.resourcePathWithTrailingSlash = "#{resourcePath}#{path.sep}"
|
||||
registerBuiltins(devMode)
|
||||
|
||||
return
|
||||
|
||||
exports.add = (directoryPath, metadata) ->
|
||||
# path.join isn't used in this function for speed since path.join calls
|
||||
# path.normalize and all the paths are already normalized here.
|
||||
|
||||
unless metadata?
|
||||
try
|
||||
metadata = require("#{directoryPath}#{path.sep}package.json")
|
||||
catch error
|
||||
return
|
||||
|
||||
cacheToAdd = metadata?._atomModuleCache
|
||||
return unless cacheToAdd?
|
||||
|
||||
for dependency in cacheToAdd.dependencies ? []
|
||||
cache.dependencies[dependency.name] ?= {}
|
||||
cache.dependencies[dependency.name][dependency.version] ?= "#{directoryPath}#{path.sep}#{dependency.path}"
|
||||
|
||||
for entry in cacheToAdd.folders ? []
|
||||
for folderPath in entry.paths
|
||||
if folderPath
|
||||
cache.folders["#{directoryPath}#{path.sep}#{folderPath}"] = entry.dependencies
|
||||
else
|
||||
cache.folders[directoryPath] = entry.dependencies
|
||||
|
||||
for extension, paths of cacheToAdd.extensions
|
||||
cache.extensions[extension] ?= new Set()
|
||||
for filePath in paths
|
||||
cache.extensions[extension].add("#{directoryPath}#{path.sep}#{filePath}")
|
||||
|
||||
return
|
||||
|
||||
exports.cache = cache
|
||||
@@ -29,11 +29,11 @@ module.exports =
|
||||
class PackageManager
|
||||
EmitterMixin.includeInto(this)
|
||||
|
||||
constructor: ({configDirPath, devMode, safeMode, @resourcePath}) ->
|
||||
constructor: ({configDirPath, @devMode, safeMode, @resourcePath}) ->
|
||||
@emitter = new Emitter
|
||||
@packageDirPaths = []
|
||||
unless safeMode
|
||||
if devMode
|
||||
if @devMode
|
||||
@packageDirPaths.push(path.join(configDirPath, "dev", "packages"))
|
||||
@packageDirPaths.push(path.join(configDirPath, "packages"))
|
||||
|
||||
|
||||
+55
-17
@@ -10,8 +10,14 @@ Q = require 'q'
|
||||
{deprecate} = require 'grim'
|
||||
|
||||
$ = null # Defer require in case this is in the window-less browser process
|
||||
ModuleCache = require './module-cache'
|
||||
ScopedProperties = require './scoped-properties'
|
||||
|
||||
try
|
||||
packagesCache = require('../package.json')?._atomPackages ? {}
|
||||
catch error
|
||||
packagesCache = {}
|
||||
|
||||
# Loads and activates a package's main module and resources such as
|
||||
# stylesheets, keymaps, grammar, editor properties, and menus.
|
||||
module.exports =
|
||||
@@ -20,14 +26,25 @@ class Package
|
||||
|
||||
@stylesheetsDir: 'stylesheets'
|
||||
|
||||
@isBundledPackagePath: (packagePath) ->
|
||||
if atom.packages.devMode
|
||||
return false unless atom.packages.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}")
|
||||
|
||||
@resourcePathWithTrailingSlash ?= "#{atom.packages.resourcePath}#{path.sep}"
|
||||
packagePath?.startsWith(@resourcePathWithTrailingSlash)
|
||||
|
||||
@loadMetadata: (packagePath, ignoreErrors=false) ->
|
||||
if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
|
||||
try
|
||||
metadata = CSON.readFileSync(metadataPath)
|
||||
catch error
|
||||
throw error unless ignoreErrors
|
||||
packageName = path.basename(packagePath)
|
||||
if @isBundledPackagePath(packagePath)
|
||||
metadata = packagesCache[packageName]?.metadata
|
||||
unless metadata?
|
||||
if metadataPath = CSON.resolve(path.join(packagePath, 'package'))
|
||||
try
|
||||
metadata = CSON.readFileSync(metadataPath)
|
||||
catch error
|
||||
throw error unless ignoreErrors
|
||||
metadata ?= {}
|
||||
metadata.name = path.basename(packagePath)
|
||||
metadata.name = packageName
|
||||
metadata
|
||||
|
||||
keymaps: null
|
||||
@@ -46,7 +63,9 @@ class Package
|
||||
constructor: (@path, @metadata) ->
|
||||
@emitter = new Emitter
|
||||
@metadata ?= Package.loadMetadata(@path)
|
||||
@bundledPackage = Package.isBundledPackagePath(@path)
|
||||
@name = @metadata?.name ? path.basename(@path)
|
||||
ModuleCache.add(@path, @metadata)
|
||||
@reset()
|
||||
|
||||
###
|
||||
@@ -175,10 +194,16 @@ class Package
|
||||
@scopedPropertiesActivated = true
|
||||
|
||||
loadKeymaps: ->
|
||||
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath)]
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@keymaps = (["#{atom.packages.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of packagesCache[@name].keymaps)
|
||||
else
|
||||
@keymaps = @getKeymapPaths().map (keymapPath) -> [keymapPath, CSON.readFileSync(keymapPath)]
|
||||
|
||||
loadMenus: ->
|
||||
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath)]
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
@menus = (["#{atom.packages.resourcePath}#{path.sep}#{menuPath}", menuObject] for menuPath, menuObject of packagesCache[@name].menus)
|
||||
else
|
||||
@menus = @getMenuPaths().map (menuPath) -> [menuPath, CSON.readFileSync(menuPath)]
|
||||
|
||||
getKeymapPaths: ->
|
||||
keymapsDirPath = path.join(@path, 'keymaps')
|
||||
@@ -312,19 +337,31 @@ class Package
|
||||
|
||||
requireMainModule: ->
|
||||
return @mainModule if @mainModule?
|
||||
return unless @isCompatible()
|
||||
unless @isCompatible()
|
||||
console.warn """
|
||||
Failed to require the main module of '#{@name}' because it requires an incompatible native module.
|
||||
Run `apm rebuild` in the package directory to resolve.
|
||||
"""
|
||||
return
|
||||
mainModulePath = @getMainModulePath()
|
||||
@mainModule = require(mainModulePath) if fs.isFileSync(mainModulePath)
|
||||
|
||||
getMainModulePath: ->
|
||||
return @mainModulePath if @resolvedMainModulePath
|
||||
@resolvedMainModulePath = true
|
||||
mainModulePath =
|
||||
if @metadata.main
|
||||
path.join(@path, @metadata.main)
|
||||
|
||||
if @bundledPackage and packagesCache[@name]?
|
||||
if packagesCache[@name].main
|
||||
@mainModulePath = "#{atom.packages.resourcePath}#{path.sep}#{packagesCache[@name].main}"
|
||||
else
|
||||
path.join(@path, 'index')
|
||||
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
|
||||
@mainModulePath = null
|
||||
else
|
||||
mainModulePath =
|
||||
if @metadata.main
|
||||
path.join(@path, @metadata.main)
|
||||
else
|
||||
path.join(@path, 'index')
|
||||
@mainModulePath = fs.resolveExtension(mainModulePath, ["", _.keys(require.extensions)...])
|
||||
|
||||
hasActivationCommands: ->
|
||||
for selector, commands of @getActivationCommands()
|
||||
@@ -336,8 +373,10 @@ class Package
|
||||
for selector, commands of @getActivationCommands()
|
||||
for command in commands
|
||||
do (selector, command) =>
|
||||
atom.commands.commandRegistered(command)
|
||||
@activationCommandSubscriptions.add(atom.commands.onWillDispatch (event) =>
|
||||
# Add dummy command so it appears in menu.
|
||||
# The real command will be registered on package activation
|
||||
@activationCommandSubscriptions.add atom.commands.add selector, command, ->
|
||||
@activationCommandSubscriptions.add atom.commands.onWillDispatch (event) =>
|
||||
return unless event.type is command
|
||||
currentTarget = event.target
|
||||
while currentTarget
|
||||
@@ -346,7 +385,6 @@ class Package
|
||||
@activateNow()
|
||||
break
|
||||
currentTarget = currentTarget.parentElement
|
||||
)
|
||||
|
||||
getActivationCommands: ->
|
||||
return @activationCommands if @activationCommands?
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
|
||||
class PanelContainerElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
@subscriptions.add @model.onDidAddPanel(@panelAdded.bind(this))
|
||||
@subscriptions.add @model.onDidRemovePanel(@panelRemoved.bind(this))
|
||||
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
|
||||
|
||||
@setAttribute('location', @model.getLocation())
|
||||
|
||||
panelAdded: ({panel, index}) ->
|
||||
if index >= @childNodes.length
|
||||
@appendChild(panel.getView())
|
||||
else
|
||||
referenceItem = @childNodes[index + 1]
|
||||
@insertBefore(panel.getView(), referenceItem)
|
||||
|
||||
panelRemoved: ({panel, index}) ->
|
||||
@removeChild(@childNodes[index])
|
||||
|
||||
destroyed: ->
|
||||
@subscriptions.dispose()
|
||||
@parentNode?.removeChild(this)
|
||||
|
||||
module.exports = PanelContainerElement = document.registerElement 'atom-panel-container', prototype: PanelContainerElement.prototype
|
||||
@@ -0,0 +1,66 @@
|
||||
{Emitter, CompositeDisposable} = require 'event-kit'
|
||||
|
||||
module.exports =
|
||||
class PanelContainer
|
||||
constructor: ({@viewRegistry, @location}) ->
|
||||
@emitter = new Emitter
|
||||
@subscriptions = new CompositeDisposable
|
||||
@panels = []
|
||||
|
||||
destroy: ->
|
||||
pane.destroy() for pane in @getPanels()
|
||||
@subscriptions.dispose()
|
||||
@emitter.emit 'did-destroy', this
|
||||
@emitter.dispose()
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
onDidAddPanel: (callback) ->
|
||||
@emitter.on 'did-add-panel', callback
|
||||
|
||||
onDidRemovePanel: (callback) ->
|
||||
@emitter.on 'did-remove-panel', callback
|
||||
|
||||
onDidDestroy: (callback) ->
|
||||
@emitter.on 'did-destroy', callback
|
||||
|
||||
###
|
||||
Section: Panels
|
||||
###
|
||||
|
||||
getView: -> @viewRegistry.getView(this)
|
||||
|
||||
getLocation: -> @location
|
||||
|
||||
getPanels: -> @panels
|
||||
|
||||
addPanel: (panel) ->
|
||||
@subscriptions.add panel.onDidDestroy(@panelDestoryed.bind(this))
|
||||
|
||||
index = @getPanelIndex(panel)
|
||||
if index is @panels.length
|
||||
@panels.push(panel)
|
||||
else
|
||||
@panels.splice(index, 0, panel)
|
||||
|
||||
@emitter.emit 'did-add-panel', {panel, index}
|
||||
panel
|
||||
|
||||
panelDestoryed: (panel) ->
|
||||
index = @panels.indexOf(panel)
|
||||
if index > -1
|
||||
@panels.splice(index, 1)
|
||||
@emitter.emit 'did-remove-panel', {panel, index}
|
||||
|
||||
getPanelIndex: (panel) ->
|
||||
priority = panel.getPriority()
|
||||
if @location in ['bottom', 'right']
|
||||
for p, i in @panels by -1
|
||||
return i + 1 if priority < p.getPriority()
|
||||
0
|
||||
else
|
||||
for p, i in @panels
|
||||
return i if priority < p.getPriority()
|
||||
@panels.length
|
||||
@@ -0,0 +1,31 @@
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
{callAttachHooks} = require './space-pen-extensions'
|
||||
|
||||
class PanelElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
|
||||
getModel: -> @model
|
||||
|
||||
setModel: (@model) ->
|
||||
view = @model.getItemView()
|
||||
@appendChild(view)
|
||||
callAttachHooks(view) # for backward compatibility with SpacePen views
|
||||
|
||||
@subscriptions.add @model.onDidChangeVisible(@visibleChanged.bind(this))
|
||||
@subscriptions.add @model.onDidDestroy(@destroyed.bind(this))
|
||||
|
||||
attachedCallback: ->
|
||||
@visibleChanged(@model.isVisible())
|
||||
|
||||
visibleChanged: (visible) ->
|
||||
if visible
|
||||
@style.display = null
|
||||
else
|
||||
@style.display = 'none'
|
||||
|
||||
destroyed: ->
|
||||
@subscriptions.dispose()
|
||||
@parentNode?.removeChild(this)
|
||||
|
||||
module.exports = PanelElement = document.registerElement 'atom-panel', prototype: PanelElement.prototype
|
||||
@@ -0,0 +1,78 @@
|
||||
{Emitter} = require 'event-kit'
|
||||
|
||||
# Extended: A container representing a panel on the edges of the editor window.
|
||||
# You should not create a `Panel` directly, instead use {Workspace::addTopPanel}
|
||||
# and friends to add panels.
|
||||
#
|
||||
# Examples: [tree-view](https://github.com/atom/tree-view),
|
||||
# [status-bar](https://github.com/atom/status-bar),
|
||||
# and [find-and-replace](https://github.com/atom/find-and-replace) all use
|
||||
# panels.
|
||||
module.exports =
|
||||
class Panel
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
###
|
||||
|
||||
constructor: ({@viewRegistry, @item, @visible, @priority}) ->
|
||||
@emitter = new Emitter
|
||||
@visible ?= true
|
||||
@priority ?= 100
|
||||
|
||||
# Public: Destroy and remove this panel from the UI.
|
||||
destroy: ->
|
||||
@emitter.emit 'did-destroy', this
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
###
|
||||
|
||||
# Public: Invoke the given callback when the pane hidden or shown.
|
||||
#
|
||||
# * `callback` {Function} to be called when the pane is destroyed.
|
||||
# * `visible` {Boolean} true when the panel has been shown
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidChangeVisible: (callback) ->
|
||||
@emitter.on 'did-change-visible', callback
|
||||
|
||||
# Public: Invoke the given callback when the pane is destroyed.
|
||||
#
|
||||
# * `callback` {Function} to be called when the pane is destroyed.
|
||||
# * `panel` {Panel} this panel
|
||||
#
|
||||
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
|
||||
onDidDestroy: (callback) ->
|
||||
@emitter.on 'did-destroy', callback
|
||||
|
||||
###
|
||||
Section: Panel Details
|
||||
###
|
||||
|
||||
# Public: Gets this panel model's view DOM node.
|
||||
#
|
||||
# Returns an `<atom-panel>` {Element}
|
||||
getView: -> @viewRegistry.getView(this)
|
||||
|
||||
# Public: Gets your panel contents view.
|
||||
#
|
||||
# Returns an {Element} or jQuery element, depeneding on how you created the panel.
|
||||
getItemView: -> @viewRegistry.getView(@item)
|
||||
|
||||
# Public: Returns a {Number} indicating this panel's priority.
|
||||
getPriority: -> @priority
|
||||
|
||||
# Public: Returns a {Boolean} true when the panel is visible.
|
||||
isVisible: -> @visible
|
||||
|
||||
# Public: Hide this panel
|
||||
hide: ->
|
||||
wasVisible = @visible
|
||||
@visible = false
|
||||
@emitter.emit 'did-change-visible', @visible if wasVisible
|
||||
|
||||
# Public: Show this panel
|
||||
show: ->
|
||||
wasVisible = @visible
|
||||
@visible = true
|
||||
@emitter.emit 'did-change-visible', @visible unless wasVisible
|
||||
@@ -0,0 +1,46 @@
|
||||
# Extended: Wraps an {Array} of `String`s. The Array describes a path from the
|
||||
# root of the syntax tree to a token including _all_ scope names for the entire
|
||||
# path.
|
||||
#
|
||||
# Methods that take a `ScopeDescriptor` will also accept an {Array} of {Strings}
|
||||
# scope names e.g. `['.source.js']`.
|
||||
#
|
||||
# You can use `ScopeDescriptor`s to get language-specific config settings via
|
||||
# {Config::get}.
|
||||
#
|
||||
# You should not need to create a `ScopeDescriptor` directly.
|
||||
#
|
||||
# * {Editor::getRootScopeDescriptor} to get the language's descriptor.
|
||||
# * {Editor::scopeDescriptorForBufferPosition} to get the descriptor at a
|
||||
# specific position in the buffer.
|
||||
# * {Cursor::getScopeDescriptor} to get a cursor's descriptor based on position.
|
||||
#
|
||||
# See the [scopes and scope descriptor guide](https://atom.io/docs/v0.138.0/advanced/scopes-and-scope-descriptors)
|
||||
# for more information.
|
||||
module.exports =
|
||||
class ScopeDescriptor
|
||||
@fromObject: (scopes) ->
|
||||
if scopes instanceof ScopeDescriptor
|
||||
scopes
|
||||
else
|
||||
new ScopeDescriptor({scopes})
|
||||
|
||||
###
|
||||
Section: Construction and Destruction
|
||||
###
|
||||
|
||||
# Public: Create a {ScopeDescriptor} object.
|
||||
#
|
||||
# * `object` {Object}
|
||||
# * `scopes` {Array} of {String}s
|
||||
constructor: ({@scopes}) ->
|
||||
|
||||
# Public: Returns an {Array} of {String}s
|
||||
getScopesArray: -> @scopes
|
||||
|
||||
getScopeChain: ->
|
||||
@scopes
|
||||
.map (scope) ->
|
||||
scope = ".#{scope}" unless scope[0] is '.'
|
||||
scope
|
||||
.join(' ')
|
||||
+24
-5
@@ -461,7 +461,8 @@ class Selection extends Model
|
||||
end--
|
||||
@editor.buffer.deleteRows(start, end)
|
||||
|
||||
# Public: Joins the current line with the one below it.
|
||||
# Public: Joins the current line with the one below it. Lines will
|
||||
# be separated by a single space.
|
||||
#
|
||||
# If there selection spans more than one line, all the lines are joined together.
|
||||
joinLines: ->
|
||||
@@ -475,15 +476,33 @@ class Selection extends Model
|
||||
for row in [0...rowCount]
|
||||
@cursor.setBufferPosition([selectedRange.start.row])
|
||||
@cursor.moveToEndOfLine()
|
||||
nextRow = selectedRange.start.row + 1
|
||||
if nextRow <= @editor.buffer.getLastRow() and @editor.buffer.lineLengthForRow(nextRow) > 0
|
||||
@insertText(' ')
|
||||
@cursor.moveToEndOfLine()
|
||||
|
||||
# Remove trailing whitespace from the current line
|
||||
scanRange = @cursor.getCurrentLineBufferRange()
|
||||
trailingWhitespaceRange = null
|
||||
@editor.scanInBufferRange /[ \t]+$/, scanRange, ({range}) ->
|
||||
trailingWhitespaceRange = range
|
||||
if trailingWhitespaceRange?
|
||||
@setBufferRange(trailingWhitespaceRange)
|
||||
@deleteSelectedText()
|
||||
|
||||
currentRow = selectedRange.start.row
|
||||
nextRow = currentRow + 1
|
||||
insertSpace = nextRow <= @editor.buffer.getLastRow() and
|
||||
@editor.buffer.lineLengthForRow(nextRow) > 0 and
|
||||
@editor.buffer.lineLengthForRow(currentRow) > 0
|
||||
@insertText(' ') if insertSpace
|
||||
|
||||
@cursor.moveToEndOfLine()
|
||||
|
||||
# Remove leading whitespace from the line below
|
||||
@modifySelection =>
|
||||
@cursor.moveRight()
|
||||
@cursor.moveToFirstCharacterOfLine()
|
||||
@deleteSelectedText()
|
||||
|
||||
@cursor.moveLeft() if insertSpace
|
||||
|
||||
if joinMarker?
|
||||
newSelectedRange = joinMarker.getBufferRange()
|
||||
@setBufferRange(newSelectedRange)
|
||||
|
||||
@@ -19,7 +19,8 @@ NativeEventNames = new Set
|
||||
NativeEventNames.add(nativeEvent) for nativeEvent in ["blur", "focus", "focusin",
|
||||
"focusout", "load", "resize", "scroll", "unload", "click", "dblclick", "mousedown",
|
||||
"mouseup", "mousemove", "mouseover", "mouseout", "mouseenter", "mouseleave", "change",
|
||||
"select", "submit", "keydown", "keypress", "keyup", "error", "contextmenu"]
|
||||
"select", "submit", "keydown", "keypress", "keyup", "error", "contextmenu", "textInput",
|
||||
"textinput"]
|
||||
|
||||
JQueryTrigger = jQuery.fn.trigger
|
||||
jQuery.fn.trigger = (eventName, data) ->
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
{Emitter, Disposable} = require 'event-kit'
|
||||
|
||||
module.exports =
|
||||
class StyleManager
|
||||
constructor: ->
|
||||
@emitter = new Emitter
|
||||
@styleElements = []
|
||||
@styleElementsBySourcePath = {}
|
||||
|
||||
observeStyleElements: (callback) ->
|
||||
callback(styleElement) for styleElement in @getStyleElements()
|
||||
@onDidAddStyleElement(callback)
|
||||
|
||||
onDidAddStyleElement: (callback) ->
|
||||
@emitter.on 'did-add-style-element', callback
|
||||
|
||||
onDidRemoveStyleElement: (callback) ->
|
||||
@emitter.on 'did-remove-style-element', callback
|
||||
|
||||
onDidUpdateStyleElement: (callback) ->
|
||||
@emitter.on 'did-update-style-element', callback
|
||||
|
||||
getStyleElements: ->
|
||||
@styleElements.slice()
|
||||
|
||||
addStyleSheet: (source, params) ->
|
||||
sourcePath = params?.sourcePath
|
||||
group = params?.group
|
||||
|
||||
if sourcePath? and styleElement = @styleElementsBySourcePath[sourcePath]
|
||||
updated = true
|
||||
else
|
||||
styleElement = document.createElement('style')
|
||||
if sourcePath?
|
||||
styleElement.sourcePath = sourcePath
|
||||
styleElement.setAttribute('source-path', sourcePath)
|
||||
|
||||
if context?
|
||||
styleElement.context = context
|
||||
styleElement.setAttribute('context', context)
|
||||
|
||||
if group?
|
||||
styleElement.group = group
|
||||
styleElement.setAttribute('group', group)
|
||||
|
||||
styleElement.textContent = source
|
||||
|
||||
if updated
|
||||
@emitter.emit 'did-update-style-element', styleElement
|
||||
else
|
||||
@addStyleElement(styleElement)
|
||||
|
||||
new Disposable => @removeStyleElement(styleElement)
|
||||
|
||||
addStyleElement: (styleElement) ->
|
||||
{sourcePath, group} = styleElement
|
||||
|
||||
if group?
|
||||
for existingElement, index in @styleElements
|
||||
if existingElement.group is group
|
||||
insertIndex = index + 1
|
||||
else
|
||||
break if insertIndex?
|
||||
insertIndex ?= @styleElements.length
|
||||
|
||||
@styleElements.splice(insertIndex, 0, styleElement)
|
||||
@styleElementsBySourcePath[sourcePath] ?= styleElement if sourcePath?
|
||||
@emitter.emit 'did-add-style-element', styleElement
|
||||
|
||||
removeStyleElement: (styleElement) ->
|
||||
index = @styleElements.indexOf(styleElement)
|
||||
unless index is -1
|
||||
@styleElements.splice(index, 1)
|
||||
delete @styleElementsBySourcePath[styleElement.sourcePath] if styleElement.sourcePath?
|
||||
@emitter.emit 'did-remove-style-element', styleElement
|
||||
|
||||
getSnapshot: ->
|
||||
@styleElements.slice()
|
||||
|
||||
restoreSnapshot: (styleElementsToRestore) ->
|
||||
for styleElement in @getStyleElements()
|
||||
@removeStyleElement(styleElement) unless styleElement in styleElementsToRestore
|
||||
|
||||
existingStyleElements = @getStyleElements()
|
||||
for styleElement in styleElementsToRestore
|
||||
@addStyleElement(styleElement) unless styleElement in existingStyleElements
|
||||
@@ -0,0 +1,50 @@
|
||||
{Emitter, CompositeDisposable} = require 'event-kit'
|
||||
|
||||
class StylesElement extends HTMLElement
|
||||
createdCallback: ->
|
||||
@emitter = new Emitter
|
||||
|
||||
onDidAddStyleElement: (callback) ->
|
||||
@emitter.on 'did-add-style-element', callback
|
||||
|
||||
onDidRemoveStyleElement: (callback) ->
|
||||
@emitter.on 'did-remove-style-element', callback
|
||||
|
||||
onDidUpdateStyleElement: (callback) ->
|
||||
@emitter.on 'did-update-style-element', callback
|
||||
|
||||
attachedCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@styleElementClonesByOriginalElement = new WeakMap
|
||||
@subscriptions.add atom.styles.observeStyleElements(@styleElementAdded.bind(this))
|
||||
@subscriptions.add atom.styles.onDidRemoveStyleElement(@styleElementRemoved.bind(this))
|
||||
@subscriptions.add atom.styles.onDidUpdateStyleElement(@styleElementUpdated.bind(this))
|
||||
|
||||
styleElementAdded: (styleElement) ->
|
||||
styleElementClone = styleElement.cloneNode(true)
|
||||
@styleElementClonesByOriginalElement.set(styleElement, styleElementClone)
|
||||
|
||||
group = styleElement.getAttribute('group')
|
||||
if group?
|
||||
for child in @children
|
||||
if child.getAttribute('group') is group and child.nextSibling?.getAttribute('group') isnt group
|
||||
insertBefore = child.nextSibling
|
||||
break
|
||||
|
||||
@insertBefore(styleElementClone, insertBefore)
|
||||
@emitter.emit 'did-add-style-element', styleElementClone
|
||||
|
||||
styleElementRemoved: (styleElement) ->
|
||||
styleElementClone = @styleElementClonesByOriginalElement.get(styleElement)
|
||||
styleElementClone.remove()
|
||||
@emitter.emit 'did-remove-style-element', styleElementClone
|
||||
|
||||
styleElementUpdated: (styleElement) ->
|
||||
styleElementClone = @styleElementClonesByOriginalElement.get(styleElement)
|
||||
styleElementClone.textContent = styleElement.textContent
|
||||
@emitter.emit 'did-update-style-element', styleElementClone
|
||||
|
||||
detachedCallback: ->
|
||||
@subscriptions.dispose()
|
||||
|
||||
module.exports = StylesElement = document.registerElement 'atom-styles', prototype: StylesElement.prototype
|
||||
+1
-1
@@ -32,7 +32,7 @@ class Syntax extends GrammarRegistry
|
||||
serialize: ->
|
||||
{deserializer: @constructor.name, @grammarOverridesByPath}
|
||||
|
||||
createToken: (value, scopeDescriptor) -> new Token({value, scopeDescriptor})
|
||||
createToken: (value, scopes) -> new Token({value, scopes})
|
||||
|
||||
# Deprecated: Used by settings-view to display snippets for packages
|
||||
@::accessor 'propertyStore', ->
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -482,6 +488,16 @@ TextEditorComponent = React.createClass
|
||||
|
||||
# Only scroll in one direction at a time
|
||||
{wheelDeltaX, wheelDeltaY} = event
|
||||
|
||||
# Ctrl+MouseWheel adjusts font size.
|
||||
if event.ctrlKey and atom.config.get('editor.zoomFontWhenCtrlScrolling')
|
||||
if wheelDeltaY > 0
|
||||
atom.workspace.increaseFontSize()
|
||||
else if wheelDeltaY < 0
|
||||
atom.workspace.decreaseFontSize()
|
||||
event.preventDefault()
|
||||
return
|
||||
|
||||
if Math.abs(wheelDeltaX) > Math.abs(wheelDeltaY)
|
||||
# Scrolling horizontally
|
||||
previousScrollLeft = editor.getScrollLeft()
|
||||
@@ -763,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,4 @@
|
||||
{View, $} = require 'space-pen'
|
||||
{View, $, callRemoveHooks} = require 'space-pen'
|
||||
React = require 'react-atom-fork'
|
||||
{defaults} = require 'underscore-plus'
|
||||
TextBuffer = require 'text-buffer'
|
||||
@@ -37,10 +37,15 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
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 +73,7 @@ class TextEditorElement extends HTMLElement
|
||||
|
||||
unmountComponent: ->
|
||||
return unless @component?.isMounted()
|
||||
callRemoveHooks(this)
|
||||
React.unmountComponentAtNode(this)
|
||||
@component = null
|
||||
|
||||
@@ -85,7 +91,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)
|
||||
|
||||
+39
-16
@@ -134,9 +134,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 +262,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.
|
||||
@@ -487,7 +497,7 @@ class TextEditor extends Model
|
||||
when 'decoration-updated'
|
||||
deprecate("Use Decoration::onDidChangeProperties instead. You will get the decoration back from `TextEditor::decorateMarker()`")
|
||||
when 'decoration-changed'
|
||||
deprecate("Use Marker::onDidChange instead. eg. `editor::decorateMarker(...).getMarker().onDidChange()`")
|
||||
deprecate("Use Marker::onDidChange instead. e.g. `editor::decorateMarker(...).getMarker().onDidChange()`")
|
||||
|
||||
when 'screen-lines-changed'
|
||||
deprecate("Use TextEditor::onDidChange instead")
|
||||
@@ -568,6 +578,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 +772,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()
|
||||
|
||||
@@ -1216,7 +1236,7 @@ class TextEditor extends Model
|
||||
# ## Arguments
|
||||
#
|
||||
# * `marker` A {Marker} you want this decoration to follow.
|
||||
# * `decorationParams` An {Object} representing the decoration eg. `{type: 'gutter', class: 'linter-error'}`
|
||||
# * `decorationParams` An {Object} representing the decoration e.g. `{type: 'gutter', class: 'linter-error'}`
|
||||
# * `type` There are a few supported decoration types: `gutter`, `line`, and `highlight`
|
||||
# * `class` This CSS class will be applied to the decorated line number,
|
||||
# line, or highlight.
|
||||
@@ -2370,8 +2390,8 @@ class TextEditor extends Model
|
||||
Section: Managing Syntax Scopes
|
||||
###
|
||||
|
||||
# Essential: Returns the scope descriptor that includes the language. eg.
|
||||
# `['.source.ruby']`, or `['.source.coffee']`. You can use this with
|
||||
# Essential: Returns a {ScopeDescriptor} that includes this editor's language.
|
||||
# e.g. `['.source.ruby']`, or `['.source.coffee']`. You can use this with
|
||||
# {Config::get} to get language specific config values.
|
||||
getRootScopeDescriptor: ->
|
||||
@displayBuffer.getRootScopeDescriptor()
|
||||
@@ -2385,11 +2405,12 @@ class TextEditor extends Model
|
||||
#
|
||||
# * `bufferPosition` A {Point} or {Array} of [row, column].
|
||||
#
|
||||
# Returns an {Array} of {String}s.
|
||||
scopeDescriptorForBufferPosition: (bufferPosition) -> @displayBuffer.scopeDescriptorForBufferPosition(bufferPosition)
|
||||
# Returns a {ScopeDescriptor}.
|
||||
scopeDescriptorForBufferPosition: (bufferPosition) ->
|
||||
@displayBuffer.scopeDescriptorForBufferPosition(bufferPosition)
|
||||
scopesForBufferPosition: (bufferPosition) ->
|
||||
deprecate 'Use ::scopeDescriptorForBufferPosition instead'
|
||||
@scopeDescriptorForBufferPosition(bufferPosition)
|
||||
deprecate 'Use ::scopeDescriptorForBufferPosition instead. The return value has changed! It now returns a `ScopeDescriptor`'
|
||||
@scopeDescriptorForBufferPosition(bufferPosition).getScopesArray()
|
||||
|
||||
# Extended: Get the range in buffer coordinates of all tokens surrounding the
|
||||
# cursor that match the given scope selector.
|
||||
@@ -2397,14 +2418,16 @@ class TextEditor extends Model
|
||||
# For example, if you wanted to find the string surrounding the cursor, you
|
||||
# could call `editor.bufferRangeForScopeAtCursor(".string.quoted")`.
|
||||
#
|
||||
# * `scopeSelector` {String} selector. e.g. `'.source.ruby'`
|
||||
#
|
||||
# Returns a {Range}.
|
||||
bufferRangeForScopeAtCursor: (selector) ->
|
||||
@displayBuffer.bufferRangeForScopeAtPosition(selector, @getCursorBufferPosition())
|
||||
bufferRangeForScopeAtCursor: (scopeSelector) ->
|
||||
@displayBuffer.bufferRangeForScopeAtPosition(scopeSelector, @getCursorBufferPosition())
|
||||
|
||||
# Extended: Determine if the given row is entirely a comment
|
||||
isBufferRowCommented: (bufferRow) ->
|
||||
if match = @lineTextForBufferRow(bufferRow).match(/\S/)
|
||||
scopeDescriptor = @tokenForBufferPosition([bufferRow, match.index]).scopeDescriptor
|
||||
scopeDescriptor = @tokenForBufferPosition([bufferRow, match.index]).scopes
|
||||
@commentScopeSelector ?= new TextMateScopeSelector('comment.*')
|
||||
@commentScopeSelector.matches(scopeDescriptor)
|
||||
|
||||
@@ -2415,10 +2438,10 @@ class TextEditor extends Model
|
||||
tokenForBufferPosition: (bufferPosition) -> @displayBuffer.tokenForBufferPosition(bufferPosition)
|
||||
|
||||
scopesAtCursor: ->
|
||||
deprecate 'Use editor.getLastCursor().scopesAtCursor() instead'
|
||||
@getLastCursor().getScopeDescriptor()
|
||||
deprecate 'Use editor.getLastCursor().getScopeDescriptor() instead'
|
||||
@getLastCursor().getScopeDescriptor().getScopesArray()
|
||||
getCursorScopes: ->
|
||||
deprecate 'Use editor.getLastCursor().scopesAtCursor() instead'
|
||||
deprecate 'Use editor.getLastCursor().getScopeDescriptor() instead'
|
||||
@scopesAtCursor()
|
||||
|
||||
###
|
||||
|
||||
+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.
|
||||
#
|
||||
|
||||
+41
-54
@@ -19,9 +19,39 @@ class ThemeManager
|
||||
|
||||
constructor: ({@packageManager, @resourcePath, @configDirPath, @safeMode}) ->
|
||||
@emitter = new Emitter
|
||||
@styleSheetDisposablesBySourcePath = {}
|
||||
@lessCache = null
|
||||
@initialLoadComplete = false
|
||||
@packageManager.registerPackageActivator(this, ['theme'])
|
||||
@sheetsByStyleElement = new WeakMap
|
||||
|
||||
stylesElement = document.head.querySelector('atom-styles')
|
||||
stylesElement.onDidAddStyleElement @styleElementAdded.bind(this)
|
||||
stylesElement.onDidRemoveStyleElement @styleElementRemoved.bind(this)
|
||||
stylesElement.onDidUpdateStyleElement @styleElementUpdated.bind(this)
|
||||
|
||||
styleElementAdded: (styleElement) ->
|
||||
{sheet} = styleElement
|
||||
@sheetsByStyleElement.set(styleElement, sheet)
|
||||
@emit 'stylesheet-added', sheet
|
||||
@emitter.emit 'did-add-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
styleElementRemoved: (styleElement) ->
|
||||
sheet = @sheetsByStyleElement.get(styleElement)
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
styleElementUpdated: ({sheet}) ->
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheet-added', sheet
|
||||
@emitter.emit 'did-add-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
###
|
||||
Section: Event Subscription
|
||||
@@ -129,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'
|
||||
@@ -188,7 +221,6 @@ class ThemeManager
|
||||
if fullPath = @resolveStylesheet(stylesheetPath)
|
||||
content = @loadStylesheet(fullPath)
|
||||
@applyStylesheet(fullPath, content, type)
|
||||
new Disposable => @removeStylesheet(fullPath)
|
||||
else
|
||||
throw new Error("Could not find a file at path '#{stylesheetPath}'")
|
||||
|
||||
@@ -204,8 +236,7 @@ class ThemeManager
|
||||
|
||||
@userStylesheetPath = userStylesheetPath
|
||||
@userStylesheetFile = new File(userStylesheetPath)
|
||||
@userStylesheetFile.on 'contents-changed moved removed', =>
|
||||
@loadUserStylesheet()
|
||||
@userStylesheetFile.on 'contents-changed moved removed', => @loadUserStylesheet()
|
||||
userStylesheetContents = @loadStylesheet(userStylesheetPath, true)
|
||||
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
|
||||
|
||||
@@ -219,7 +250,7 @@ class ThemeManager
|
||||
@requireStylesheet(nativeStylesheetPath)
|
||||
|
||||
stylesheetElementForId: (id) ->
|
||||
document.head.querySelector("""style[id="#{id}"]""")
|
||||
document.head.querySelector("atom-styles style[source-path=\"#{id}\"]")
|
||||
|
||||
resolveStylesheet: (stylesheetPath) ->
|
||||
if path.extname(stylesheetPath).length > 0
|
||||
@@ -256,40 +287,10 @@ class ThemeManager
|
||||
"""
|
||||
|
||||
removeStylesheet: (stylesheetPath) ->
|
||||
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
|
||||
element = @stylesheetElementForId(@stringToId(fullPath))
|
||||
if element?
|
||||
{sheet} = element
|
||||
element.remove()
|
||||
@emit 'stylesheet-removed', sheet
|
||||
@emitter.emit 'did-remove-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
@styleSheetDisposablesBySourcePath[stylesheetPath]?.dispose()
|
||||
|
||||
applyStylesheet: (path, text, type='bundled') ->
|
||||
styleId = @stringToId(path)
|
||||
styleElement = @stylesheetElementForId(styleId)
|
||||
|
||||
if styleElement?
|
||||
@emit 'stylesheet-removed', styleElement.sheet
|
||||
@emitter.emit 'did-remove-stylesheet', styleElement.sheet
|
||||
styleElement.textContent = text
|
||||
else
|
||||
styleElement = document.createElement('style')
|
||||
styleElement.setAttribute('class', type)
|
||||
styleElement.setAttribute('id', styleId)
|
||||
styleElement.textContent = text
|
||||
|
||||
elementToInsertBefore = _.last(document.head.querySelectorAll("style.#{type}"))?.nextElementSibling
|
||||
if elementToInsertBefore?
|
||||
document.head.insertBefore(styleElement, elementToInsertBefore)
|
||||
else
|
||||
document.head.appendChild(styleElement)
|
||||
|
||||
@emit 'stylesheet-added', styleElement.sheet
|
||||
@emitter.emit 'did-add-stylesheet', styleElement.sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
@styleSheetDisposablesBySourcePath[path] = atom.styles.addStyleSheet(text, sourcePath: path, group: type)
|
||||
|
||||
###
|
||||
Section: Private
|
||||
@@ -358,17 +359,3 @@ class ThemeManager
|
||||
themePaths.push(path.join(themePath, Package.stylesheetsDir))
|
||||
|
||||
themePaths.filter (themePath) -> fs.isDirectorySync(themePath)
|
||||
|
||||
updateGlobalEditorStyle: (property, value) ->
|
||||
unless styleNode = @stylesheetElementForId('global-editor-styles')
|
||||
@applyStylesheet('global-editor-styles', 'atom-text-editor {}')
|
||||
styleNode = @stylesheetElementForId('global-editor-styles')
|
||||
|
||||
{sheet} = styleNode
|
||||
editorRule = sheet.cssRules[0]
|
||||
editorRule.style[property] = value
|
||||
|
||||
@emit 'stylesheet-updated', sheet
|
||||
@emitter.emit 'did-update-stylesheet', sheet
|
||||
@emit 'stylesheets-changed'
|
||||
@emitter.emit 'did-change-stylesheets'
|
||||
|
||||
+14
-20
@@ -14,35 +14,28 @@ module.exports =
|
||||
class Token
|
||||
value: null
|
||||
hasPairedCharacter: false
|
||||
scopeDescriptor: null
|
||||
scopes: null
|
||||
isAtomic: null
|
||||
isHardTab: null
|
||||
firstNonWhitespaceIndex: null
|
||||
firstTrailingWhitespaceIndex: null
|
||||
hasInvisibleCharacters: false
|
||||
|
||||
Object.defineProperty @::, 'scopes', get: ->
|
||||
deprecate 'Use ::scopeDescriptor instead'
|
||||
@scopeDescriptor
|
||||
|
||||
constructor: ({@value, @scopeDescriptor, @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
|
||||
scopeDescriptor = other.scopeDescriptor ? other.scopes
|
||||
deprecate 'Test the Token for `scopeDescriptor` rather than `scopes`' if other.scopes?
|
||||
|
||||
@value == other.value and _.isEqual(@scopeDescriptor, scopeDescriptor) and !!@isAtomic == !!other.isAtomic
|
||||
@value == other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic == !!other.isAtomic
|
||||
|
||||
isBracket: ->
|
||||
/^meta\.brace\b/.test(_.last(@scopeDescriptor))
|
||||
/^meta\.brace\b/.test(_.last(@scopes))
|
||||
|
||||
splitAt: (splitIndex) ->
|
||||
leftToken = new Token(value: @value.substring(0, splitIndex), scopeDescriptor: @scopeDescriptor)
|
||||
rightToken = new Token(value: @value.substring(splitIndex), scopeDescriptor: @scopeDescriptor)
|
||||
leftToken = new Token(value: @value.substring(0, splitIndex), scopes: @scopes)
|
||||
rightToken = new Token(value: @value.substring(splitIndex), scopes: @scopes)
|
||||
|
||||
if @firstNonWhitespaceIndex?
|
||||
leftToken.firstNonWhitespaceIndex = Math.min(splitIndex, @firstNonWhitespaceIndex)
|
||||
@@ -101,7 +94,7 @@ class Token
|
||||
else
|
||||
breakOutLeadingSoftTabs = false
|
||||
value = match[0]
|
||||
token = new Token({value, @scopeDescriptor})
|
||||
token = new Token({value, @scopes})
|
||||
column += token.value.length
|
||||
outputTokens.push(token)
|
||||
|
||||
@@ -115,7 +108,7 @@ class Token
|
||||
while index < @value.length
|
||||
if textUtils.isPairedCharacter(@value, index)
|
||||
if nonPairStart isnt index
|
||||
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopeDescriptor}))
|
||||
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopes}))
|
||||
outputTokens.push(@buildPairedCharacterToken(@value, index))
|
||||
index += 2
|
||||
nonPairStart = index
|
||||
@@ -123,15 +116,16 @@ class Token
|
||||
index++
|
||||
|
||||
if nonPairStart isnt index
|
||||
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopeDescriptor}))
|
||||
outputTokens.push(new Token({value: @value[nonPairStart...index], @scopes}))
|
||||
|
||||
outputTokens
|
||||
|
||||
buildPairedCharacterToken: (value, index) ->
|
||||
new Token(
|
||||
value: value[index..index + 1]
|
||||
scopeDescriptor: @scopeDescriptor
|
||||
scopes: @scopes
|
||||
isAtomic: true
|
||||
hasPairedCharacter: true
|
||||
)
|
||||
|
||||
buildHardTabToken: (tabLength, column) ->
|
||||
@@ -144,7 +138,7 @@ class Token
|
||||
tabStop = tabLength - (column % tabLength)
|
||||
new Token(
|
||||
value: _.multiplyString(" ", tabStop)
|
||||
scopeDescriptor: @scopeDescriptor
|
||||
scopes: @scopes
|
||||
bufferDelta: if isHardTab then 1 else tabStop
|
||||
isAtomic: true
|
||||
isHardTab: isHardTab
|
||||
@@ -155,7 +149,7 @@ class Token
|
||||
|
||||
matchesScopeSelector: (selector) ->
|
||||
targetClasses = selector.replace(StartDotRegex, '').split('.')
|
||||
_.any @scopeDescriptor, (scope) ->
|
||||
_.any @scopes, (scope) ->
|
||||
scopeClasses = scope.split('.')
|
||||
_.isSubset(targetClasses, scopeClasses)
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ EmitterMixin = require('emissary').Emitter
|
||||
Serializable = require 'serializable'
|
||||
TokenizedLine = require './tokenized-line'
|
||||
Token = require './token'
|
||||
ScopeDescriptor = require './scope-descriptor'
|
||||
Grim = require 'grim'
|
||||
|
||||
module.exports =
|
||||
@@ -28,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()
|
||||
@@ -79,7 +80,7 @@ class TokenizedBuffer extends Model
|
||||
return if grammar is @grammar
|
||||
@unsubscribe(@grammar) if @grammar
|
||||
@grammar = grammar
|
||||
@rootScopeDescriptor = [@grammar.scopeName]
|
||||
@rootScopeDescriptor = new ScopeDescriptor(scopes: [@grammar.scopeName])
|
||||
@currentGrammarScore = score ? grammar.getScore(@buffer.getPath(), @buffer.getText())
|
||||
@subscribe @grammar.onDidUpdate => @retokenizeLines()
|
||||
|
||||
@@ -105,7 +106,7 @@ class TokenizedBuffer extends Model
|
||||
hasTokenForSelector: (selector) ->
|
||||
for {tokens} in @tokenizedLines
|
||||
for token in tokens
|
||||
return true if selector.matches(token.scopeDescriptor)
|
||||
return true if selector.matches(token.scopes)
|
||||
false
|
||||
|
||||
retokenizeLines: ->
|
||||
@@ -247,7 +248,7 @@ class TokenizedBuffer extends Model
|
||||
|
||||
buildPlaceholderTokenizedLineForRow: (row) ->
|
||||
line = @buffer.lineForRow(row)
|
||||
tokens = [new Token(value: line, scopeDescriptor: [@grammar.scopeName])]
|
||||
tokens = [new Token(value: line, scopes: [@grammar.scopeName])]
|
||||
tabLength = @getTabLength()
|
||||
indentLevel = @indentLevelForRow(row)
|
||||
lineEnding = @buffer.lineEndingForRow(row)
|
||||
@@ -303,7 +304,7 @@ class TokenizedBuffer extends Model
|
||||
0
|
||||
|
||||
scopeDescriptorForPosition: (position) ->
|
||||
@tokenForPosition(position).scopeDescriptor
|
||||
new ScopeDescriptor(scopes: @tokenForPosition(position).scopes)
|
||||
|
||||
tokenForPosition: (position) ->
|
||||
{row, column} = Point.fromObject(position)
|
||||
|
||||
@@ -194,9 +194,9 @@ class TokenizedLine
|
||||
|
||||
isComment: ->
|
||||
for token in @tokens
|
||||
continue if token.scopeDescriptor.length is 1
|
||||
continue if token.scopes.length is 1
|
||||
continue if token.isOnlyWhitespace()
|
||||
for scope in token.scopeDescriptor
|
||||
for scope in token.scopes
|
||||
return true if _.contains(scope.split('.'), 'comment')
|
||||
break
|
||||
false
|
||||
@@ -226,7 +226,7 @@ class TokenizedLine
|
||||
|
||||
scopeStack = []
|
||||
for token in @tokens
|
||||
@updateScopeStack(scopeStack, token.scopeDescriptor)
|
||||
@updateScopeStack(scopeStack, token.scopes)
|
||||
_.last(scopeStack).children.push(token)
|
||||
|
||||
@scopeTree = scopeStack[0]
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
# Like sands through the hourglass, so are the days of our lives.
|
||||
startTime = Date.now()
|
||||
|
||||
require './window'
|
||||
|
||||
Atom = require './atom'
|
||||
window.atom = Atom.loadOrCreate('editor')
|
||||
atom.initialize()
|
||||
atom.startEditorWindow()
|
||||
window.atom.loadTime = Date.now() - startTime
|
||||
console.log "Window load time: #{atom.getWindowLoadTime()}ms"
|
||||
|
||||
# Workaround for focus getting cleared upon window creation
|
||||
windowFocused = ->
|
||||
|
||||
@@ -8,8 +8,11 @@ WorkspaceView = null
|
||||
|
||||
module.exports =
|
||||
class WorkspaceElement extends HTMLElement
|
||||
globalTextEditorStyleSheet: null
|
||||
|
||||
createdCallback: ->
|
||||
@subscriptions = new CompositeDisposable
|
||||
@initializeGlobalTextEditorStyleSheet()
|
||||
@initializeContent()
|
||||
@observeScrollbarStyle()
|
||||
@observeTextEditorFontConfig()
|
||||
@@ -22,6 +25,10 @@ class WorkspaceElement extends HTMLElement
|
||||
detachedCallback: ->
|
||||
@model.destroy()
|
||||
|
||||
initializeGlobalTextEditorStyleSheet: ->
|
||||
atom.styles.addStyleSheet('atom-text-editor {}', sourcePath: 'global-text-editor-styles')
|
||||
@globalTextEditorStyleSheet = document.head.querySelector('style[source-path="global-text-editor-styles"]').sheet
|
||||
|
||||
initializeContent: ->
|
||||
@classList.add 'workspace'
|
||||
@setAttribute 'tabindex', -1
|
||||
@@ -46,9 +53,9 @@ class WorkspaceElement extends HTMLElement
|
||||
@classList.add("scrollbars-visible-when-scrolling")
|
||||
|
||||
observeTextEditorFontConfig: ->
|
||||
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize
|
||||
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily
|
||||
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight
|
||||
@subscriptions.add atom.config.observe 'editor.fontSize', @setTextEditorFontSize.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.fontFamily', @setTextEditorFontFamily.bind(this)
|
||||
@subscriptions.add atom.config.observe 'editor.lineHeight', @setTextEditorLineHeight.bind(this)
|
||||
|
||||
createSpacePenShim: ->
|
||||
WorkspaceView ?= require './workspace-view'
|
||||
@@ -65,16 +72,33 @@ class WorkspaceElement extends HTMLElement
|
||||
window.addEventListener 'focus', handleWindowFocus
|
||||
@subscriptions.add(new Disposable -> window.removeEventListener 'focus', handleWindowFocus)
|
||||
|
||||
@panelContainers =
|
||||
top: @model.panelContainers.top.getView()
|
||||
left: @model.panelContainers.left.getView()
|
||||
right: @model.panelContainers.right.getView()
|
||||
bottom: @model.panelContainers.bottom.getView()
|
||||
|
||||
@horizontalAxis.insertBefore(@panelContainers.left, @verticalAxis)
|
||||
@horizontalAxis.appendChild(@panelContainers.right)
|
||||
|
||||
@verticalAxis.insertBefore(@panelContainers.top, @paneContainer)
|
||||
@verticalAxis.appendChild(@panelContainers.bottom)
|
||||
|
||||
@__spacePenView.setModel(@model)
|
||||
|
||||
setTextEditorFontSize: (fontSize) ->
|
||||
atom.themes.updateGlobalEditorStyle('font-size', fontSize + 'px')
|
||||
@updateGlobalEditorStyle('font-size', fontSize + 'px')
|
||||
|
||||
setTextEditorFontFamily: (fontFamily) ->
|
||||
atom.themes.updateGlobalEditorStyle('font-family', fontFamily)
|
||||
@updateGlobalEditorStyle('font-family', fontFamily)
|
||||
|
||||
setTextEditorLineHeight: (lineHeight) ->
|
||||
atom.themes.updateGlobalEditorStyle('line-height', lineHeight)
|
||||
@updateGlobalEditorStyle('line-height', lineHeight)
|
||||
|
||||
updateGlobalEditorStyle: (property, value) ->
|
||||
editorRule = @globalTextEditorStyleSheet.cssRules[0]
|
||||
editorRule.style[property] = value
|
||||
atom.themes.emitter.emit 'did-update-stylesheet', @globalTextEditorStyleSheet
|
||||
|
||||
handleFocus: (event) ->
|
||||
@model.getActivePane().activate()
|
||||
|
||||
@@ -141,59 +141,36 @@ class WorkspaceView extends View
|
||||
Section: Adding elements to the workspace
|
||||
###
|
||||
|
||||
# Essential: Prepend an element or view to the panels at the top of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
prependToTop: (element) ->
|
||||
deprecate 'Please use Workspace::addTopPanel() instead'
|
||||
@vertical.prepend(element)
|
||||
|
||||
# Essential: Append an element or view to the panels at the top of the workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
appendToTop: (element) ->
|
||||
deprecate 'Please use Workspace::addTopPanel() instead'
|
||||
@panes.before(element)
|
||||
|
||||
# Essential: Prepend an element or view to the panels at the bottom of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
prependToBottom: (element) ->
|
||||
deprecate 'Please use Workspace::addBottomPanel() instead'
|
||||
@panes.after(element)
|
||||
|
||||
# Essential: Append an element or view to the panels at the bottom of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
appendToBottom: (element) ->
|
||||
deprecate 'Please use Workspace::addBottomPanel() instead'
|
||||
@vertical.append(element)
|
||||
|
||||
# Essential: Prepend an element or view to the panels at the left of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
prependToLeft: (element) ->
|
||||
deprecate 'Please use Workspace::addLeftPanel() instead'
|
||||
@horizontal.prepend(element)
|
||||
|
||||
# Essential: Append an element or view to the panels at the left of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
appendToLeft: (element) ->
|
||||
deprecate 'Please use Workspace::addLeftPanel() instead'
|
||||
@vertical.before(element)
|
||||
|
||||
# Essential: Prepend an element or view to the panels at the right of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
prependToRight: (element) ->
|
||||
deprecate 'Please use Workspace::addRightPanel() instead'
|
||||
@vertical.after(element)
|
||||
|
||||
# Essential: Append an element or view to the panels at the right of the
|
||||
# workspace.
|
||||
#
|
||||
# * `element` jQuery object or DOM element
|
||||
appendToRight: (element) ->
|
||||
deprecate 'Please use Workspace::addRightPanel() instead'
|
||||
@horizontal.append(element)
|
||||
|
||||
###
|
||||
|
||||
+89
-1
@@ -10,6 +10,10 @@ Grim = require 'grim'
|
||||
TextEditor = require './text-editor'
|
||||
PaneContainer = require './pane-container'
|
||||
Pane = require './pane'
|
||||
Panel = require './panel'
|
||||
PanelElement = require './panel-element'
|
||||
PanelContainer = require './panel-container'
|
||||
PanelContainerElement = require './panel-container-element'
|
||||
ViewRegistry = require './view-registry'
|
||||
WorkspaceElement = require './workspace-element'
|
||||
|
||||
@@ -45,6 +49,12 @@ class Workspace extends Model
|
||||
@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'})
|
||||
|
||||
@subscribeToActiveItem()
|
||||
|
||||
@addOpener (filePath) =>
|
||||
@@ -62,6 +72,14 @@ class Workspace extends Model
|
||||
modelConstructor: Workspace
|
||||
viewConstructor: WorkspaceElement
|
||||
|
||||
@addViewProvider
|
||||
modelConstructor: PanelContainer
|
||||
viewConstructor: PanelContainerElement
|
||||
|
||||
@addViewProvider
|
||||
modelConstructor: Panel
|
||||
viewConstructor: PanelElement
|
||||
|
||||
# Called by the Serializable mixin during deserialization
|
||||
deserializeParams: (params) ->
|
||||
for packageName in params.packagesWithActiveGrammars ? []
|
||||
@@ -578,6 +596,76 @@ class Workspace extends Model
|
||||
@paneContainer.destroy()
|
||||
@activeItemSubscriptions?.dispose()
|
||||
|
||||
|
||||
###
|
||||
Section: Panels
|
||||
###
|
||||
|
||||
# Essential: Adds a panel item to the bottom of the editor window.
|
||||
#
|
||||
# * `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.
|
||||
# * `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
|
||||
# forced closer to the edges of the window. (default: 100)
|
||||
#
|
||||
# Returns a {Panel}
|
||||
addBottomPanel: (options) ->
|
||||
@addPanel('bottom', options)
|
||||
|
||||
# Essential: Adds a panel item to the left of the editor window.
|
||||
#
|
||||
# * `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.
|
||||
# * `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
|
||||
# forced closer to the edges of the window. (default: 100)
|
||||
#
|
||||
# Returns a {Panel}
|
||||
addLeftPanel: (options) ->
|
||||
@addPanel('left', options)
|
||||
|
||||
# Essential: Adds a panel item to the right of the editor window.
|
||||
#
|
||||
# * `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.
|
||||
# * `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
|
||||
# forced closer to the edges of the window. (default: 100)
|
||||
#
|
||||
# Returns a {Panel}
|
||||
addRightPanel: (options) ->
|
||||
@addPanel('right', options)
|
||||
|
||||
# Essential: Adds a panel item to the top of the editor window above the tabs.
|
||||
#
|
||||
# * `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.
|
||||
# * `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
|
||||
# forced closer to the edges of the window. (default: 100)
|
||||
#
|
||||
# Returns a {Panel}
|
||||
addTopPanel: (options) ->
|
||||
@addPanel('top', options)
|
||||
|
||||
addPanel: (location, options) ->
|
||||
options ?= {}
|
||||
options.viewRegistry = @viewRegistry
|
||||
@panelContainers[location].addPanel(new Panel(options))
|
||||
|
||||
###
|
||||
Section: View Management
|
||||
###
|
||||
@@ -628,7 +716,7 @@ class Workspace extends Model
|
||||
# makes [HTML 5 custom elements](http://www.html5rocks.com/en/tutorials/webcomponents/customelements/)
|
||||
# an ideal tool for implementing views in Atom.
|
||||
#
|
||||
# ## Example
|
||||
# ## 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
|
||||
|
||||
+31
-5
@@ -1,10 +1,26 @@
|
||||
window.onload = function() {
|
||||
var path = require('path');
|
||||
var ipc = require('ipc');
|
||||
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 (devMode) {
|
||||
require('coffee-script').register();
|
||||
}
|
||||
|
||||
ModuleCache = require('../src/module-cache');
|
||||
ModuleCache.register(loadSettings);
|
||||
ModuleCache.add(loadSettings.resourcePath);
|
||||
|
||||
// Start the crash reporter before anything else.
|
||||
require('crash-reporter').start({
|
||||
productName: 'Atom',
|
||||
@@ -15,10 +31,20 @@ window.onload = function() {
|
||||
});
|
||||
|
||||
require('vm-compatibility-layer');
|
||||
require('coffee-script').register();
|
||||
require(path.resolve(__dirname, '..', 'src', 'coffee-cache')).register();
|
||||
|
||||
if (!devMode) {
|
||||
require('coffee-script').register();
|
||||
}
|
||||
|
||||
require('../src/coffee-cache').register();
|
||||
|
||||
require(loadSettings.bootstrapScript);
|
||||
ipc.sendChannel('window-command', 'window:loaded')
|
||||
require('ipc').sendChannel('window-command', 'window:loaded');
|
||||
|
||||
if (global.atom) {
|
||||
global.atom.loadTime = Date.now() - startTime;
|
||||
console.log('Window load time: ' + global.atom.getWindowLoadTime() + 'ms');
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
var currentWindow = require('remote').getCurrentWindow();
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
@import "ui-variables";
|
||||
|
||||
atom-panel-container[location="left"],
|
||||
atom-panel-container[location="right"] {
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: row;
|
||||
-webkit-align-items: stretch;
|
||||
height: 100%;
|
||||
atom-panel {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
// Override bootstrap styles here.
|
||||
.panel {
|
||||
border-radius: 0;
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário