Merge branch 'master' into farnabaz-master

This commit is contained in:
Nathan Sobo
2016-12-14 13:34:21 -07:00
93 changed files with 1184 additions and 721 deletions

View File

@@ -1,6 +1,6 @@
![Atom](https://cloud.githubusercontent.com/assets/72919/2874231/3af1db48-d3dd-11e3-98dc-6066f8bc766f.png)
[![macOS Build Status](https://circleci.com/gh/atom/atom.svg?style=svg)](https://circleci.com/gh/atom/atom) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom)
[![macOS Build Status](https://circleci.com/gh/atom/atom/tree/master.svg?style=shield)](https://circleci.com/gh/atom/atom) [![Linux Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom)
[![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom)
[![Join the Atom Community on Slack](http://atom-slack.herokuapp.com/badge.svg)](http://atom-slack.herokuapp.com/)
@@ -33,15 +33,14 @@ Atom will automatically update when a new release is available.
### Windows
Download the latest [AtomSetup.exe installer](https://github.com/atom/atom/releases/latest).
Download the latest [Atom installer](https://github.com/atom/atom/releases/latest). AtomSetup.exe is 32-bit, AtomSetup-x64.exe for 64-bit systems.
Atom will automatically update when a new release is available.
You can also download an `atom-windows.zip` file from the [releases page](https://github.com/atom/atom/releases/latest).
You can also download `atom-windows.zip` (32-bit) or `atom-x64-windows.zip` (64-bit) from the [releases page](https://github.com/atom/atom/releases/latest).
The `.zip` version will not automatically update.
Using [chocolatey](https://chocolatey.org/)? Run `cinst Atom` to install
the latest version of Atom.
Using [chocolatey](https://chocolatey.org/)? Run `cinst Atom` to install the latest version of Atom.
### Debian Linux (Ubuntu)
@@ -54,7 +53,7 @@ Atom is only available for 64-bit Linux systems.
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 21 and under, CentOS, Red Hat)
### Red Hat Enterprise Linux (RHEL) / CentOS
Atom is only available for 64-bit Linux systems.
@@ -65,12 +64,12 @@ Atom is only available for 64-bit Linux systems.
The Linux version does not currently automatically update so you will need to
repeat these steps to upgrade to future releases.
### Fedora 22+
### Fedora
Atom is only available for 64-bit Linux systems.
1. Download `atom.x86_64.rpm` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
2. Run `sudo dnf install ./atom.x86_64.rpm` on the downloaded package.
2. Run `sudo dnf install 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

View File

@@ -6,6 +6,6 @@
"url": "https://github.com/atom/atom.git"
},
"dependencies": {
"atom-package-manager": "1.14.1"
"atom-package-manager": "1.15.1"
}
}

View File

@@ -8,13 +8,14 @@ clone_depth: 10
platform:
- x86
- x64
environment:
global:
ATOM_DEV_RESOURCE_PATH: c:\projects\atom
matrix:
- NODE_VERSION: 4.4.5
- NODE_VERSION: 6.8.0
install:
- SET PATH=C:\Program Files\Atom\resources\cli;%PATH%
@@ -49,6 +50,4 @@ cache:
- '%APPVEYOR_BUILD_FOLDER%\node_modules'
- '%APPVEYOR_BUILD_FOLDER%\electron'
- '%USERPROFILE%\.atom\.apm'
- '%USERPROFILE%\.atom\.node-gyp\.atom'
- '%USERPROFILE%\.atom\.npm'
- '%USERPROFILE%\.atom\compile-cache'

15
atom.sh
View File

@@ -55,11 +55,22 @@ if [ $EXPECT_OUTPUT ]; then
fi
if [ $OS == 'Mac' ]; then
if [ -L "$0" ]; then
SCRIPT="$(readlink "$0")"
else
SCRIPT="$0"
fi
ATOM_APP="$(dirname "$(dirname "$(dirname "$(dirname "$SCRIPT")")")")"
if [ "$ATOM_APP" == . ]; then
unset ATOM_APP
else
ATOM_PATH="$(dirname "$ATOM_APP")"
ATOM_APP_NAME="$(basename "$ATOM_APP")"
fi
if [ -n "$BETA_VERSION" ]; then
ATOM_APP_NAME="Atom Beta.app"
ATOM_EXECUTABLE_NAME="Atom Beta"
else
ATOM_APP_NAME="Atom.app"
ATOM_EXECUTABLE_NAME="Atom"
fi

View File

@@ -2,111 +2,112 @@
| System | macOS | Windows | Dependencies |
|--------|------|---------|--------------|
| Atom | [![macOS Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) |
| APM | [![macOS Build Status](https://travis-ci.org/atom/apm.svg?branch=master)](https://travis-ci.org/atom/apm) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/j6ixw374a397ugkb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/apm/branch/master) | [![Dependency Status](https://david-dm.org/atom/apm.svg)](https://david-dm.org/atom/apm) |
| Electron | [![macOS Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kvxe4byi7jcxbe26/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/electron) | [![Dependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron)
| [Atom](https://github.com/atom/atom) | [![macOS Build Status](https://travis-ci.org/atom/atom.svg?branch=master)](https://travis-ci.org/atom/atom) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1tkktwh654w07eim?svg=true)](https://ci.appveyor.com/project/Atom/atom) | [![Dependency Status](https://david-dm.org/atom/atom.svg)](https://david-dm.org/atom/atom) |
| [APM](https://github.com/atom/apm) | [![macOS Build Status](https://travis-ci.org/atom/apm.svg?branch=master)](https://travis-ci.org/atom/apm) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/j6ixw374a397ugkb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/apm/branch/master) | [![Dependency Status](https://david-dm.org/atom/apm.svg)](https://david-dm.org/atom/apm) |
| [Electron](https://github.com/electron/electron) | [![macOS Build Status](https://travis-ci.org/electron/electron.svg?branch=master)](https://travis-ci.org/electron/electron) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kvxe4byi7jcxbe26/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/electron) | [![Dependency Status](https://david-dm.org/electron/electron/dev-status.svg)](https://david-dm.org/electron/electron)
## Packages
| Package | macOS | Windows | Dependencies |
|---------|------|---------|--------------|
| About | [![macOS Build Status](https://travis-ci.org/atom/about.svg?branch=master)](https://travis-ci.org/atom/about) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/msprea3vq47l8oce/branch/master?svg=true)](https://ci.appveyor.com/project/atom/about/branch/master) | [![Dependency Status](https://david-dm.org/atom/about.svg)](https://david-dm.org/atom/about) |
| Archive View | [![macOS Build Status](https://travis-ci.org/atom/archive-view.svg?branch=master)](https://travis-ci.org/atom/archive-view) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/u3qfgaod4lhriqlj/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/archive-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/archive-view.svg)](https://david-dm.org/atom/archive-view) |
| AutoComplete Atom API | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-atom-api.svg?branch=master)](https://travis-ci.org/atom/autocomplete-atom-api) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1x3uqd9ddchpe555/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-atom-api/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-atom-api.svg)](https://david-dm.org/atom/autocomplete-atom-api) |
| Atom Space Pen Views | [![macOS Build Status](https://travis-ci.org/atom/atom-space-pen-views.svg?branch=master)](https://travis-ci.org/atom/atom-space-pen-views) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5lgv47has6n8uhuv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/atom-space-pen-views/branch/master) | [![Dependency Status](https://david-dm.org/atom/atom-space-pen-views.svg)](https://david-dm.org/atom/atom-space-pen-views) |
| AutoComplete CSS | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-css.svg?branch=master)](https://travis-ci.org/atom/autocomplete-css) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k3e5uvpmpc5bkja9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-css/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-css.svg)](https://david-dm.org/atom/autocomplete-css) |
| AutoComplete HTML | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-html.svg?branch=master)](https://travis-ci.org/atom/autocomplete-html) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/bsaqbg1fljpd9q1b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-html/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-html.svg)](https://david-dm.org/atom/autocomplete-html) |
| AutoComplete+ | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-plus.svg?branch=master)](https://travis-ci.org/atom/autocomplete-plus) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/9bpokrud2apgqsq0/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-plus.svg)](https://david-dm.org/atom/autocomplete-plus) |
| AutoComplete Snippets | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-snippets.svg)](https://travis-ci.org/atom/autocomplete-snippets) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/72kfi83l6cw90joy/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-snippets/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-snippets.svg)](https://david-dm.org/atom/autocomplete-snippets) |
| AutoFlow | [![macOS Build Status](https://travis-ci.org/atom/autoflow.svg?branch=master)](https://travis-ci.org/atom/autoflow) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kpmsnkbooa29x907/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autoflow/branch/master) | [![Dependency Status](https://david-dm.org/atom/autoflow.svg)](https://david-dm.org/atom/autoflow) |
| AutoSave | [![macOS Build Status](https://travis-ci.org/atom/autosave.svg?branch=master)](https://travis-ci.org/atom/autosave) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/3aktr9updp722fqx/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autosave/branch/master) | [![Dependency Status](https://david-dm.org/atom/autosave.svg)](https://david-dm.org/atom/autosave) |
| Background Tips | [![macOS Build Status](https://travis-ci.org/atom/background-tips.svg?branch=master)](https://travis-ci.org/atom/background-tips) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/2utcugietl5vjc7w/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/background-tips/branch/master) | [![Dependency Status](https://david-dm.org/atom/background-tips.svg)](https://david-dm.org/atom/background-tips) |
| Bookmarks | [![macOS Build Status](https://travis-ci.org/atom/bookmarks.svg?branch=master)](https://travis-ci.org/atom/bookmarks) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/vjsf78pj4rw6ibcw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/bookmarks/branch/master) | [![Dependency Status](https://david-dm.org/atom/bookmarks.svg)](https://david-dm.org/atom/bookmarks) |
| Bracket Matcher | [![macOS Build Status](https://travis-ci.org/atom/bracket-matcher.svg?branch=master)](https://travis-ci.org/atom/bracket-matcher) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/rrsl2h7e0od26k54/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/bracket-matcher/branch/master) | [![Dependency Status](https://david-dm.org/atom/bracket-matcher.svg)](https://david-dm.org/atom/bracket-matcher) |
| Command Palette | [![macOS Build Status](https://travis-ci.org/atom/command-palette.svg?branch=master)](https://travis-ci.org/atom/command-palette) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/jqgwetayr0enorun/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/command-palette/branch/master) | [![Dependency Status](https://david-dm.org/atom/command-palette.svg)](https://david-dm.org/atom/command-palette) |
| Deprecation Cop | [![macOS Build Status](https://travis-ci.org/atom/deprecation-cop.svg?branch=master)](https://travis-ci.org/atom/deprecation-cop) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/0s870q5fj3vwihjx/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/deprecation-cop/branch/master) | [![Dependency Status](https://david-dm.org/atom/deprecation-cop.svg)](https://david-dm.org/atom/deprecation-cop) |
| Dev Live Reload | [![macOS Build Status](https://travis-ci.org/atom/dev-live-reload.svg?branch=master)](https://travis-ci.org/atom/dev-live-reload) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/g3sd27ylba1fun1v/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/dev-live-reload/branch/master) | [![Dependency Status](https://david-dm.org/atom/dev-live-reload.svg)](https://david-dm.org/atom/dev-live-reload) |
| Encoding Selector | [![macOS Build Status](https://travis-ci.org/atom/encoding-selector.svg?branch=master)](https://travis-ci.org/atom/encoding-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/e08x6k2b68wpwxxc/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/encoding-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/encoding-selector.svg)](https://david-dm.org/atom/encoding-selector) |
| Exception Reporting | [![macOS Build Status](https://travis-ci.org/atom/exception-reporting.svg?branch=master)](https://travis-ci.org/atom/exception-reporting) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/i0pla7qbpv7celg2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/exception-reporting/branch/master) | [![Dependency Status](https://david-dm.org/atom/exception-reporting.svg)](https://david-dm.org/atom/exception-reporting) |
| Find and Replace | [![macOS Build Status](https://travis-ci.org/atom/find-and-replace.svg?branch=master)](https://travis-ci.org/atom/find-and-replace) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/6w4baiiq5mw4nxky/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/find-and-replace/branch/master) | [![Dependency Status](https://david-dm.org/atom/find-and-replace.svg)](https://david-dm.org/atom/find-and-replace) |
| Fuzzy Finder | [![macOS Build Status](https://travis-ci.org/atom/fuzzy-finder.svg?branch=master)](https://travis-ci.org/atom/fuzzy-finder) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b4b2dg5n9r1wdqad/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/fuzzy-finder/branch/master) | [![Dependency Status](https://david-dm.org/atom/fuzzy-finder.svg)](https://david-dm.org/atom/fuzzy-finder) |
| Git Diff | [![macOS Build Status](https://travis-ci.org/atom/git-diff.svg?branch=master)](https://travis-ci.org/atom/git-diff) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/9auj52cs0vso66nv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/git-diff/branch/master) | [![Dependency Status](https://david-dm.org/atom/git-diff.svg)](https://david-dm.org/atom/git-diff) |
| Go to Line | [![macOS Build Status](https://travis-ci.org/atom/go-to-line.svg?branch=master)](https://travis-ci.org/atom/go-to-line) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/qf0isc8ulw4wxi0b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/go-to-line/branch/master) | [![Dependency Status](https://david-dm.org/atom/go-to-line.svg)](https://david-dm.org/atom/go-to-line) |
| Grammar Selector | [![macOS Build Status](https://travis-ci.org/atom/grammar-selector.svg?branch=master)](https://travis-ci.org/atom/grammar-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/pg8qss03bfh4ngqm/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/grammar-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/grammar-selector.svg)](https://david-dm.org/atom/grammar-selector) |
| Image View | [![macOS Build Status](https://travis-ci.org/atom/image-view.svg?branch=master)](https://travis-ci.org/atom/image-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/notavaawrswk0g10/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/image-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/image-view.svg)](https://david-dm.org/atom/image-view) |
| Incompatible Packages | [![macOS Build Status](https://travis-ci.org/atom/incompatible-packages.svg?branch=master)](https://travis-ci.org/atom/incompatible-packages) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/neet595s038x7w70/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/incompatible-packages/branch/master) | [![Dependency Status](https://david-dm.org/atom/incompatible-packages.svg)](https://david-dm.org/atom/incompatible-packages) |
| Keybinding Resolver | [![macOS Build Status](https://travis-ci.org/atom/keybinding-resolver.svg?branch=master)](https://travis-ci.org/atom/keybinding-resolver) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/9jf31itx01hnn4nh/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/keybinding-resolver/branch/master) | [![Dependency Status](https://david-dm.org/atom/keybinding-resolver.svg)](https://david-dm.org/atom/keybinding-resolver) |
| Line Ending Selector | [![macOS Build Status](https://travis-ci.org/atom/line-ending-selector.svg?branch=master)](https://travis-ci.org/atom/line-ending-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b3743n9ojomlpn1g/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/line-ending-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/line-ending-selector.svg)](https://david-dm.org/atom/line-ending-selector) |
| Link | [![macOS Build Status](https://travis-ci.org/atom/link.svg?branch=master)](https://travis-ci.org/atom/link) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1d3cb8ktd48k9vnl/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/link/branch/master) | [![Dependency Status](https://david-dm.org/atom/link.svg)](https://david-dm.org/atom/link) |
| Markdown Preview | [![macOS Build Status](https://travis-ci.org/atom/markdown-preview.svg?branch=master)](https://travis-ci.org/atom/markdown-preview) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/bvh0evhh4v6w9b29/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/markdown-preview/branch/master) | [![Dependency Status](https://david-dm.org/atom/markdown-preview.svg)](https://david-dm.org/atom/markdown-preview) |
| Metrics | [![macOS Build Status](https://travis-ci.org/atom/metrics.svg?branch=master)](https://travis-ci.org/atom/metrics) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b5doi205xl3iex04/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/metrics/branch/master) | [![Dependency Status](https://david-dm.org/atom/metrics.svg)](https://david-dm.org/atom/metrics) |
| Notifications | [![macOS Build Status](https://travis-ci.org/atom/notifications.svg?branch=master)](https://travis-ci.org/atom/notifications) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ps3p8tj2okw57x0e/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/notifications/branch/master) | [![Dependency Status](https://david-dm.org/atom/notifications.svg)](https://david-dm.org/atom/notifications) |
| Open on Github | [![macOS Build Status](https://travis-ci.org/atom/open-on-github.svg?branch=master)](https://travis-ci.org/atom/open-on-github) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ccl6na4qsna5wncr/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/open-on-github/branch/master) | [![Dependency Status](https://david-dm.org/atom/open-on-github.svg)](https://david-dm.org/atom/open-on-github) |
| Package Generator | [![macOS Build Status](https://travis-ci.org/atom/package-generator.svg?branch=master)](https://travis-ci.org/atom/package-generator)| [![Windows Build Status](https://ci.appveyor.com/api/projects/status/7t1i4hdmljhigp9u/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/package-generator/branch/master) | [![Dependency Status](https://david-dm.org/atom/package-generator.svg)](https://david-dm.org/atom/package-generator) |
| Settings View | [![macOS Build Status](https://travis-ci.org/atom/settings-view.svg?branch=master)](https://travis-ci.org/atom/settings-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/hatgxg6k2g3grafq/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/settings-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/settings-view.svg)](https://david-dm.org/atom/settings-view) |
| Snippets | [![macOS Build Status](https://travis-ci.org/atom/snippets.svg?branch=master)](https://travis-ci.org/atom/snippets) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/8hlc0onofkgbxw53/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/snippets/branch/master) | [![Dependency Status](https://david-dm.org/atom/snippets.svg)](https://david-dm.org/atom/snippets) |
| Spell Check | [![macOS Build Status](https://travis-ci.org/atom/spell-check.svg?branch=master)](https://travis-ci.org/atom/spell-check) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1620a5reqw6kdolv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/spell-check/branch/master) | [![Dependency Status](https://david-dm.org/atom/spell-check.svg)](https://david-dm.org/atom/spell-check) |
| Status Bar | [![macOS Build Status](https://travis-ci.org/atom/status-bar.svg?branch=master)](https://travis-ci.org/atom/status-bar) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gu8tv4h6cnpeesg2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/status-bar/branch/master) | [![Dependency Status](https://david-dm.org/atom/status-bar.svg)](https://david-dm.org/atom/status-bar) |
| Styleguide | [![macOS Build Status](https://travis-ci.org/atom/styleguide.svg?branch=master)](https://travis-ci.org/atom/styleguide) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/88dt9jxexkpindhw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/styleguide/branch/master) | [![Dependency Status](https://david-dm.org/atom/styleguide.svg)](https://david-dm.org/atom/styleguide) |
| Symbols View | [![macOS Build Status](https://travis-ci.org/atom/symbols-view.svg?branch=master)](https://travis-ci.org/atom/symbols-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/al68vtv83x49eu5d/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/symbols-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/symbols-view.svg)](https://david-dm.org/atom/symbols-view) |
| Tabs | [![macOS Build Status](https://travis-ci.org/atom/tabs.svg?branch=master)](https://travis-ci.org/atom/tabs) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/nf4hdmuk4i9xkfmb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/tabs/branch/master) | [![Dependency Status](https://david-dm.org/atom/tabs.svg)](https://david-dm.org/atom/tabs) |
| Timecop | [![macOS Build Status](https://travis-ci.org/atom/timecop.svg?branch=master)](https://travis-ci.org/atom/timecop) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/37fhichmvx90sd97/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/timecop/branch/master) | [![Dependency Status](https://david-dm.org/atom/timecop.svg)](https://david-dm.org/atom/timecop) |
| Tree View | [![macOS Build Status](https://travis-ci.org/atom/tree-view.svg?branch=master)](https://travis-ci.org/atom/tree-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/com793ehi0hajrkd/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/tree-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/tree-view.svg)](https://david-dm.org/atom/tree-view) |
| Update Package Dependencies | [![macOS Build Status](https://travis-ci.org/atom/update-package-dependencies.svg?branch=master)](https://travis-ci.org/atom/update-package-dependencies) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5xqtoc3xk1e7lt2y/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/update-package-dependencies/branch/master) | [![Dependency Status](https://david-dm.org/atom/update-package-dependencies.svg)](https://david-dm.org/atom/update-package-dependencies) |
| Welcome | [![macOS Build Status](https://travis-ci.org/atom/welcome.svg?branch=master)](https://travis-ci.org/atom/welcome) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/c3ssyte35ivvnt62/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/welcome/branch/master) | [![Dependency Status](https://david-dm.org/atom/welcome.svg)](https://david-dm.org/atom/welcome) |
| Whitespace | [![macOS Build Status](https://travis-ci.org/atom/whitespace.svg?branch=master)](https://travis-ci.org/atom/whitespace) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/sf8pdb3ausdk1vtb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/whitespace/branch/master) | [![Dependency Status](https://david-dm.org/atom/whitespace.svg)](https://david-dm.org/atom/whitespace) |
| Wrap Guide | [![macOS Build Status](https://travis-ci.org/atom/wrap-guide.svg?branch=master)](https://travis-ci.org/atom/wrap-guide) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5qk1io3uar5j8hol/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/wrap-guide/branch/master) | [![Dependency Status](https://david-dm.org/atom/wrap-guide.svg)](https://david-dm.org/atom/wrap-guide) |
| [About](https://github.com/atom/about) | [![macOS Build Status](https://travis-ci.org/atom/about.svg?branch=master)](https://travis-ci.org/atom/about) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/msprea3vq47l8oce/branch/master?svg=true)](https://ci.appveyor.com/project/atom/about/branch/master) | [![Dependency Status](https://david-dm.org/atom/about.svg)](https://david-dm.org/atom/about) |
| [Archive View](https://github.com/atom/archive-view) | [![macOS Build Status](https://travis-ci.org/atom/archive-view.svg?branch=master)](https://travis-ci.org/atom/archive-view) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/u3qfgaod4lhriqlj/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/archive-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/archive-view.svg)](https://david-dm.org/atom/archive-view) |
| [AutoComplete Atom API](https://github.com/atom/autocomplete-atom-api) | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-atom-api.svg?branch=master)](https://travis-ci.org/atom/autocomplete-atom-api) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1x3uqd9ddchpe555/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-atom-api/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-atom-api.svg)](https://david-dm.org/atom/autocomplete-atom-api) |
| [AutoComplete CSS](https://github.com/atom/autocomplete-css) | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-css.svg?branch=master)](https://travis-ci.org/atom/autocomplete-css) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k3e5uvpmpc5bkja9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-css/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-css.svg)](https://david-dm.org/atom/autocomplete-css) |
| [AutoComplete HTML](https://github.com/atom/autocomplete-html) | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-html.svg?branch=master)](https://travis-ci.org/atom/autocomplete-html) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/bsaqbg1fljpd9q1b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-html/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-html.svg)](https://david-dm.org/atom/autocomplete-html) |
| [AutoComplete+](https://github.com/atom/autocomplete-plus) | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-plus.svg?branch=master)](https://travis-ci.org/atom/autocomplete-plus) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/9bpokrud2apgqsq0/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-plus.svg)](https://david-dm.org/atom/autocomplete-plus) |
| [AutoComplete Snippets](https://github.com/atom/autocomplete-snippets) | [![macOS Build Status](https://travis-ci.org/atom/autocomplete-snippets.svg)](https://travis-ci.org/atom/autocomplete-snippets) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/72kfi83l6cw90joy/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autocomplete-snippets/branch/master) | [![Dependency Status](https://david-dm.org/atom/autocomplete-snippets.svg)](https://david-dm.org/atom/autocomplete-snippets) |
| [AutoFlow](https://github.com/atom/autoflow) | [![macOS Build Status](https://travis-ci.org/atom/autoflow.svg?branch=master)](https://travis-ci.org/atom/autoflow) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kpmsnkbooa29x907/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autoflow/branch/master) | [![Dependency Status](https://david-dm.org/atom/autoflow.svg)](https://david-dm.org/atom/autoflow) |
| [AutoSave](https://github.com/atom/autosave) | [![macOS Build Status](https://travis-ci.org/atom/autosave.svg?branch=master)](https://travis-ci.org/atom/autosave) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/3aktr9updp722fqx/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/autosave/branch/master) | [![Dependency Status](https://david-dm.org/atom/autosave.svg)](https://david-dm.org/atom/autosave) |
| [Background Tips](https://github.com/atom/background-tips) | [![macOS Build Status](https://travis-ci.org/atom/background-tips.svg?branch=master)](https://travis-ci.org/atom/background-tips) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/2utcugietl5vjc7w/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/background-tips/branch/master) | [![Dependency Status](https://david-dm.org/atom/background-tips.svg)](https://david-dm.org/atom/background-tips) |
| [Bookmarks](https://github.com/atom/bookmarks) | [![macOS Build Status](https://travis-ci.org/atom/bookmarks.svg?branch=master)](https://travis-ci.org/atom/bookmarks) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/vjsf78pj4rw6ibcw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/bookmarks/branch/master) | [![Dependency Status](https://david-dm.org/atom/bookmarks.svg)](https://david-dm.org/atom/bookmarks) |
| [Bracket Matcher](https://github.com/atom/bracket-matcher) | [![macOS Build Status](https://travis-ci.org/atom/bracket-matcher.svg?branch=master)](https://travis-ci.org/atom/bracket-matcher) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/rrsl2h7e0od26k54/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/bracket-matcher/branch/master) | [![Dependency Status](https://david-dm.org/atom/bracket-matcher.svg)](https://david-dm.org/atom/bracket-matcher) |
| [Command Palette](https://github.com/atom/command-palette) | [![macOS Build Status](https://travis-ci.org/atom/command-palette.svg?branch=master)](https://travis-ci.org/atom/command-palette) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/jqgwetayr0enorun/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/command-palette/branch/master) | [![Dependency Status](https://david-dm.org/atom/command-palette.svg)](https://david-dm.org/atom/command-palette) |
| [Deprecation Cop](https://github.com/atom/deprecation-cop) | [![macOS Build Status](https://travis-ci.org/atom/deprecation-cop.svg?branch=master)](https://travis-ci.org/atom/deprecation-cop) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/0s870q5fj3vwihjx/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/deprecation-cop/branch/master) | [![Dependency Status](https://david-dm.org/atom/deprecation-cop.svg)](https://david-dm.org/atom/deprecation-cop) |
| [Dev Live Reload](https://github.com/atom/dev-live-reload) | [![macOS Build Status](https://travis-ci.org/atom/dev-live-reload.svg?branch=master)](https://travis-ci.org/atom/dev-live-reload) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/g3sd27ylba1fun1v/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/dev-live-reload/branch/master) | [![Dependency Status](https://david-dm.org/atom/dev-live-reload.svg)](https://david-dm.org/atom/dev-live-reload) |
| [Encoding Selector](https://github.com/atom/encoding-selector) | [![macOS Build Status](https://travis-ci.org/atom/encoding-selector.svg?branch=master)](https://travis-ci.org/atom/encoding-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/e08x6k2b68wpwxxc/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/encoding-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/encoding-selector.svg)](https://david-dm.org/atom/encoding-selector) |
| [Exception Reporting](https://github.com/atom/exception-reporting) | [![macOS Build Status](https://travis-ci.org/atom/exception-reporting.svg?branch=master)](https://travis-ci.org/atom/exception-reporting) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/i0pla7qbpv7celg2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/exception-reporting/branch/master) | [![Dependency Status](https://david-dm.org/atom/exception-reporting.svg)](https://david-dm.org/atom/exception-reporting) |
| [Find and Replace](https://github.com/atom/find-and-replace) | [![macOS Build Status](https://travis-ci.org/atom/find-and-replace.svg?branch=master)](https://travis-ci.org/atom/find-and-replace) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/6w4baiiq5mw4nxky/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/find-and-replace/branch/master) | [![Dependency Status](https://david-dm.org/atom/find-and-replace.svg)](https://david-dm.org/atom/find-and-replace) |
| [Fuzzy Finder](https://github.com/atom/fuzzy-finder) | [![macOS Build Status](https://travis-ci.org/atom/fuzzy-finder.svg?branch=master)](https://travis-ci.org/atom/fuzzy-finder) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b4b2dg5n9r1wdqad/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/fuzzy-finder/branch/master) | [![Dependency Status](https://david-dm.org/atom/fuzzy-finder.svg)](https://david-dm.org/atom/fuzzy-finder) |
| [Git Diff](https://github.com/atom/git-diff) | [![macOS Build Status](https://travis-ci.org/atom/git-diff.svg?branch=master)](https://travis-ci.org/atom/git-diff) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/9auj52cs0vso66nv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/git-diff/branch/master) | [![Dependency Status](https://david-dm.org/atom/git-diff.svg)](https://david-dm.org/atom/git-diff) |
| [Go to Line](https://github.com/atom/go-to-line) | [![macOS Build Status](https://travis-ci.org/atom/go-to-line.svg?branch=master)](https://travis-ci.org/atom/go-to-line) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/qf0isc8ulw4wxi0b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/go-to-line/branch/master) | [![Dependency Status](https://david-dm.org/atom/go-to-line.svg)](https://david-dm.org/atom/go-to-line) |
| [Grammar Selector](https://github.com/atom/grammar-selector) | [![macOS Build Status](https://travis-ci.org/atom/grammar-selector.svg?branch=master)](https://travis-ci.org/atom/grammar-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/pg8qss03bfh4ngqm/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/grammar-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/grammar-selector.svg)](https://david-dm.org/atom/grammar-selector) |
| [Image View](https://github.com/atom/image-view) | [![macOS Build Status](https://travis-ci.org/atom/image-view.svg?branch=master)](https://travis-ci.org/atom/image-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/notavaawrswk0g10/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/image-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/image-view.svg)](https://david-dm.org/atom/image-view) |
| [Incompatible Packages](https://github.com/atom/incompatible-packages) | [![macOS Build Status](https://travis-ci.org/atom/incompatible-packages.svg?branch=master)](https://travis-ci.org/atom/incompatible-packages) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/neet595s038x7w70/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/incompatible-packages/branch/master) | [![Dependency Status](https://david-dm.org/atom/incompatible-packages.svg)](https://david-dm.org/atom/incompatible-packages) |
| [Keybinding Resolver](https://github.com/atom/keybinding-resolver) | [![macOS Build Status](https://travis-ci.org/atom/keybinding-resolver.svg?branch=master)](https://travis-ci.org/atom/keybinding-resolver) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/9jf31itx01hnn4nh/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/keybinding-resolver/branch/master) | [![Dependency Status](https://david-dm.org/atom/keybinding-resolver.svg)](https://david-dm.org/atom/keybinding-resolver) |
| [Line Ending Selector](https://github.com/atom/line-ending-selector) | [![macOS Build Status](https://travis-ci.org/atom/line-ending-selector.svg?branch=master)](https://travis-ci.org/atom/line-ending-selector) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b3743n9ojomlpn1g/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/line-ending-selector/branch/master) | [![Dependency Status](https://david-dm.org/atom/line-ending-selector.svg)](https://david-dm.org/atom/line-ending-selector) |
| [Link](https://github.com/atom/link) | [![macOS Build Status](https://travis-ci.org/atom/link.svg?branch=master)](https://travis-ci.org/atom/link) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1d3cb8ktd48k9vnl/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/link/branch/master) | [![Dependency Status](https://david-dm.org/atom/link.svg)](https://david-dm.org/atom/link) |
| [Markdown Preview](https://github.com/atom/markdown-preview) | [![macOS Build Status](https://travis-ci.org/atom/markdown-preview.svg?branch=master)](https://travis-ci.org/atom/markdown-preview) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/bvh0evhh4v6w9b29/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/markdown-preview/branch/master) | [![Dependency Status](https://david-dm.org/atom/markdown-preview.svg)](https://david-dm.org/atom/markdown-preview) |
| [Metrics](https://github.com/atom/metrics) | [![macOS Build Status](https://travis-ci.org/atom/metrics.svg?branch=master)](https://travis-ci.org/atom/metrics) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/b5doi205xl3iex04/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/metrics/branch/master) | [![Dependency Status](https://david-dm.org/atom/metrics.svg)](https://david-dm.org/atom/metrics) |
| [Notifications](https://github.com/atom/notifications) | [![macOS Build Status](https://travis-ci.org/atom/notifications.svg?branch=master)](https://travis-ci.org/atom/notifications) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ps3p8tj2okw57x0e/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/notifications/branch/master) | [![Dependency Status](https://david-dm.org/atom/notifications.svg)](https://david-dm.org/atom/notifications) |
| [Open on Github](https://github.com/atom/open-on-github) | [![macOS Build Status](https://travis-ci.org/atom/open-on-github.svg?branch=master)](https://travis-ci.org/atom/open-on-github) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ccl6na4qsna5wncr/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/open-on-github/branch/master) | [![Dependency Status](https://david-dm.org/atom/open-on-github.svg)](https://david-dm.org/atom/open-on-github) |
| [Package Generator](https://github.com/atom/package-generator) | [![macOS Build Status](https://travis-ci.org/atom/package-generator.svg?branch=master)](https://travis-ci.org/atom/package-generator)| [![Windows Build Status](https://ci.appveyor.com/api/projects/status/7t1i4hdmljhigp9u/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/package-generator/branch/master) | [![Dependency Status](https://david-dm.org/atom/package-generator.svg)](https://david-dm.org/atom/package-generator) |
| [Settings View](https://github.com/atom/settings-view) | [![macOS Build Status](https://travis-ci.org/atom/settings-view.svg?branch=master)](https://travis-ci.org/atom/settings-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/hatgxg6k2g3grafq/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/settings-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/settings-view.svg)](https://david-dm.org/atom/settings-view) |
| [Snippets](https://github.com/atom/snippets) | [![macOS Build Status](https://travis-ci.org/atom/snippets.svg?branch=master)](https://travis-ci.org/atom/snippets) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/8hlc0onofkgbxw53/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/snippets/branch/master) | [![Dependency Status](https://david-dm.org/atom/snippets.svg)](https://david-dm.org/atom/snippets) |
| [Spell Check](https://github.com/atom/spell-check) | [![macOS Build Status](https://travis-ci.org/atom/spell-check.svg?branch=master)](https://travis-ci.org/atom/spell-check) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/1620a5reqw6kdolv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/spell-check/branch/master) | [![Dependency Status](https://david-dm.org/atom/spell-check.svg)](https://david-dm.org/atom/spell-check) |
| [Status Bar](https://github.com/atom/status-bar) | [![macOS Build Status](https://travis-ci.org/atom/status-bar.svg?branch=master)](https://travis-ci.org/atom/status-bar) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gu8tv4h6cnpeesg2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/status-bar/branch/master) | [![Dependency Status](https://david-dm.org/atom/status-bar.svg)](https://david-dm.org/atom/status-bar) |
| [Styleguide](https://github.com/atom/styleguide) | [![macOS Build Status](https://travis-ci.org/atom/styleguide.svg?branch=master)](https://travis-ci.org/atom/styleguide) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/88dt9jxexkpindhw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/styleguide/branch/master) | [![Dependency Status](https://david-dm.org/atom/styleguide.svg)](https://david-dm.org/atom/styleguide) |
| [Symbols View](https://github.com/atom/symbols-view) | [![macOS Build Status](https://travis-ci.org/atom/symbols-view.svg?branch=master)](https://travis-ci.org/atom/symbols-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/al68vtv83x49eu5d/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/symbols-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/symbols-view.svg)](https://david-dm.org/atom/symbols-view) |
| [Tabs](https://github.com/atom/tabs) | [![macOS Build Status](https://travis-ci.org/atom/tabs.svg?branch=master)](https://travis-ci.org/atom/tabs) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/nf4hdmuk4i9xkfmb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/tabs/branch/master) | [![Dependency Status](https://david-dm.org/atom/tabs.svg)](https://david-dm.org/atom/tabs) |
| [Timecop](https://github.com/atom/timecop) | [![macOS Build Status](https://travis-ci.org/atom/timecop.svg?branch=master)](https://travis-ci.org/atom/timecop) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/37fhichmvx90sd97/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/timecop/branch/master) | [![Dependency Status](https://david-dm.org/atom/timecop.svg)](https://david-dm.org/atom/timecop) |
| [Tree View](https://github.com/atom/tree-view) | [![macOS Build Status](https://travis-ci.org/atom/tree-view.svg?branch=master)](https://travis-ci.org/atom/tree-view) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/com793ehi0hajrkd/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/tree-view/branch/master) | [![Dependency Status](https://david-dm.org/atom/tree-view.svg)](https://david-dm.org/atom/tree-view) |
| [Update Package Dependencies](https://github.com/atom/update-package-dependencies) | [![macOS Build Status](https://travis-ci.org/atom/update-package-dependencies.svg?branch=master)](https://travis-ci.org/atom/update-package-dependencies) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5xqtoc3xk1e7lt2y/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/update-package-dependencies/branch/master) | [![Dependency Status](https://david-dm.org/atom/update-package-dependencies.svg)](https://david-dm.org/atom/update-package-dependencies) |
| [Welcome](https://github.com/atom/welcome) | [![macOS Build Status](https://travis-ci.org/atom/welcome.svg?branch=master)](https://travis-ci.org/atom/welcome) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/c3ssyte35ivvnt62/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/welcome/branch/master) | [![Dependency Status](https://david-dm.org/atom/welcome.svg)](https://david-dm.org/atom/welcome) |
| [Whitespace](https://github.com/atom/whitespace) | [![macOS Build Status](https://travis-ci.org/atom/whitespace.svg?branch=master)](https://travis-ci.org/atom/whitespace) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/sf8pdb3ausdk1vtb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/whitespace/branch/master) | [![Dependency Status](https://david-dm.org/atom/whitespace.svg)](https://david-dm.org/atom/whitespace) |
| [Wrap Guide](https://github.com/atom/wrap-guide) | [![macOS Build Status](https://travis-ci.org/atom/wrap-guide.svg?branch=master)](https://travis-ci.org/atom/wrap-guide) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5qk1io3uar5j8hol/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/wrap-guide/branch/master) | [![Dependency Status](https://david-dm.org/atom/wrap-guide.svg)](https://david-dm.org/atom/wrap-guide) |
## Libraries
| Library | macOS | Windows | Dependencies |
|---------|------|---------|--------------|
| Clear Cut | [![macOS Build Status](https://travis-ci.org/atom/clear-cut.svg?branch=master)](https://travis-ci.org/atom/clear-cut) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/civ54x89l06286m9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/clear-cut/branch/master) | [![Dependency Status](https://david-dm.org/atom/clear-cut.svg)](https://david-dm.org/atom/clear-cut) |
| Event Kit | [![macOS Build Status](https://travis-ci.org/atom/event-kit.svg?branch=master)](https://travis-ci.org/atom/event-kit) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/lb32q70204lpmlxo/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/event-kit/branch/master) | [![Dependency Status](https://david-dm.org/atom/event-kit.svg)](https://david-dm.org/atom/event-kit) |
| Fs Plus | [![macOS Build Status](https://travis-ci.org/atom/fs-plus.svg?branch=master)](https://travis-ci.org/atom/fs-plus) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gf2tleqp0hdek3o3/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/fs-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/fs-plus.svg)](https://david-dm.org/atom/fs-plus) |
| Grim | [![macOS Build Status](https://travis-ci.org/atom/grim.svg)](https://travis-ci.org/atom/grim) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/i4m37pol77vygrvb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/grim/branch/master) | [![Dependency Status](https://david-dm.org/atom/grim.svg)](https://david-dm.org/atom/grim) |
| Jasmine Focused | [![macOS Build Status](https://travis-ci.org/atom/grim.svg)](https://travis-ci.org/atom/grim) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/af0ipfqqxn7aygoe/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/jasmine-focused/branch/master) | [![Dependency Status](https://david-dm.org/atom/jasmine-focused.svg)](https://david-dm.org/atom/jasmine-focused) |
| Property Accessors | [![macOS Build Status](https://travis-ci.org/atom/property-accessors.svg?branch=master)](https://travis-ci.org/atom/property-accessors) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ww4d10hi4v5h7kbp/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/property-accessors/branch/master) | [![Dependency Status](https://david-dm.org/atom/property-accessors.svg)](https://david-dm.org/atom/property-accessors) |
| TextBuffer | [![macOS Build Status](https://travis-ci.org/atom/text-buffer.svg?branch=master)](https://travis-ci.org/atom/text-buffer) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/48xl8do1sm2thf5p/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/text-buffer/branch/master) | [![Dependency Status](https://david-dm.org/atom/text-buffer.svg)](https://david-dm.org/atom/text-buffer) |
| Underscore-Plus | [![macOS Build Status](https://travis-ci.org/atom/underscore-plus.svg?branch=master)](https://travis-ci.org/atom/underscore-plus) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/c7l8009vgpaojxcd/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/underscore-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/underscore-plus.svg)](https://david-dm.org/atom/underscore-plus) |
| [Clear Cut](https://github.com/atom/clear-cut) | [![macOS Build Status](https://travis-ci.org/atom/clear-cut.svg?branch=master)](https://travis-ci.org/atom/clear-cut) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/civ54x89l06286m9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/clear-cut/branch/master) | [![Dependency Status](https://david-dm.org/atom/clear-cut.svg)](https://david-dm.org/atom/clear-cut) |
| [Event Kit](https://github.com/atom/event-kit) | [![macOS Build Status](https://travis-ci.org/atom/event-kit.svg?branch=master)](https://travis-ci.org/atom/event-kit) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/lb32q70204lpmlxo/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/event-kit/branch/master) | [![Dependency Status](https://david-dm.org/atom/event-kit.svg)](https://david-dm.org/atom/event-kit) |
| [First Mate](https://github.com/atom/first-mate) | [![macOS Build Status](https://travis-ci.org/atom/first-mate.svg?branch=master)](https://travis-ci.org/atom/first-mate) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/p5im21uq22cwgb6d/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/first-mate) | [![Dependency Status](https://david-dm.org/atom/first-mate/status.svg)](https://david-dm.org/atom/first-mate) |
| [Fs Plus](https://github.com/atom/fs-plus) | [![macOS Build Status](https://travis-ci.org/atom/fs-plus.svg?branch=master)](https://travis-ci.org/atom/fs-plus) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gf2tleqp0hdek3o3/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/fs-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/fs-plus.svg)](https://david-dm.org/atom/fs-plus) |
| [Grim](https://github.com/atom/grim) | [![macOS Build Status](https://travis-ci.org/atom/grim.svg)](https://travis-ci.org/atom/grim) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/i4m37pol77vygrvb/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/grim/branch/master) | [![Dependency Status](https://david-dm.org/atom/grim.svg)](https://david-dm.org/atom/grim) |
| [Jasmine Focused](https://github.com/atom/jasmine-focused) | [![macOS Build Status](https://travis-ci.org/atom/grim.svg)](https://travis-ci.org/atom/grim) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/af0ipfqqxn7aygoe/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/jasmine-focused/branch/master) | [![Dependency Status](https://david-dm.org/atom/jasmine-focused.svg)](https://david-dm.org/atom/jasmine-focused) |
| [Keyboard Layout](https://github.com/atom/keyboard-layout) | [![macOS Build Status](https://travis-ci.org/atom/keyboard-layout.svg?branch=master)](https://travis-ci.org/atom/keyboard-layout) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/rk8wooeyh689apgd/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/keyboard-layout) | [![Dependency Status](https://david-dm.org/atom/keyboard-layout/status.svg)](https://david-dm.org/atom/keyboard-layout) |
| [Oniguruma](https://github.com/atom/node-oniguruma) | [![macOS Build Status](https://travis-ci.org/atom/node-oniguruma.svg?branch=master)](https://travis-ci.org/atom/node-oniguruma) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/s9twhi451ef2butr/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/node-oniguruma/branch/master) | [![Dependency Status](https://david-dm.org/atom/node-oniguruma.svg)](https://david-dm.org/atom/node-oniguruma) |
| [PathWatcher](https://github.com/atom/node-pathwatcher) | [![macOS Build Status](https://travis-ci.org/atom/node-pathwatcher.svg?branch=master)](https://travis-ci.org/atom/node-pathwatcher) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/li8dkoucdrc2ryts/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/node-pathwatcher) | [![Dependency Status](https://david-dm.org/atom/node-pathwatcher/status.svg)](https://david-dm.org/atom/node-pathwatcher) |
| [Property Accessors](https://github.com/atom/property-accessors) | [![macOS Build Status](https://travis-ci.org/atom/property-accessors.svg?branch=master)](https://travis-ci.org/atom/property-accessors) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ww4d10hi4v5h7kbp/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/property-accessors/branch/master) | [![Dependency Status](https://david-dm.org/atom/property-accessors.svg)](https://david-dm.org/atom/property-accessors) |
| [TextBuffer](https://github.com/atom/text-buffer) | [![macOS Build Status](https://travis-ci.org/atom/text-buffer.svg?branch=master)](https://travis-ci.org/atom/text-buffer) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/48xl8do1sm2thf5p/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/text-buffer/branch/master) | [![Dependency Status](https://david-dm.org/atom/text-buffer.svg)](https://david-dm.org/atom/text-buffer) |
| [Underscore-Plus](https://github.com/atom/underscore-plus) | [![macOS Build Status](https://travis-ci.org/atom/underscore-plus.svg?branch=master)](https://travis-ci.org/atom/underscore-plus) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/c7l8009vgpaojxcd/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/underscore-plus/branch/master) | [![Dependency Status](https://david-dm.org/atom/underscore-plus.svg)](https://david-dm.org/atom/underscore-plus) |
## Tools
| Language | macOS | Windows | Dependencies |
|----------|------|---------|--------------|
| AtomDoc | [![macOS Build Status](https://travis-ci.org/atom/atomdoc.svg?branch=master)](https://travis-ci.org/atom/atomdoc) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/chi2bmaafr3puyq2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/atomdoc/branch/master) | [![Dependency Status](https://david-dm.org/atom/atomdoc.svg)](https://david-dm.org/atom/atomdoc)
| [AtomDoc](https://github.com/atom/atomdoc) | [![macOS Build Status](https://travis-ci.org/atom/atomdoc.svg?branch=master)](https://travis-ci.org/atom/atomdoc) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/chi2bmaafr3puyq2/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/atomdoc/branch/master) | [![Dependency Status](https://david-dm.org/atom/atomdoc.svg)](https://david-dm.org/atom/atomdoc)
## Languages
| Language | macOS | Windows |
|----------|------|---------|
| C/C++ | [![macOS Build Status](https://travis-ci.org/atom/language-c.svg?branch=master)](https://travis-ci.org/atom/language-c) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/8oy1hmp4yrij7c32/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-c/branch/master) |
| C# | [![macOS Build Status](https://travis-ci.org/atom/language-csharp.svg?branch=master)](https://travis-ci.org/atom/language-csharp) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/j1as3753y5t90obn/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-csharp/branch/master) |
| Clojure | [![macOS Build Status](https://travis-ci.org/atom/language-clojure.svg?branch=master)](https://travis-ci.org/atom/language-clojure) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/6kd5fs48y5hixde6/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-clojure/branch/master) |
| CoffeeScript | [![macOS Build Status](https://travis-ci.org/atom/language-coffee-script.svg?branch=master)](https://travis-ci.org/atom/language-coffee-script) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/4j9aak7iwn2f2x7a/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-coffee-script/branch/master) |
| CSS | [![macOS Build Status](https://travis-ci.org/atom/language-css.svg?branch=master)](https://travis-ci.org/atom/language-css) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/v8rvm88dxp73ko2y/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-css/branch/master) |
| Git | [![macOS Build Status](https://travis-ci.org/atom/language-git.svg?branch=master)](https://travis-ci.org/atom/language-git) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/481319gyrr1feo8b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-git/branch/master) |
| GitHub Flavored Markdown | [![macOS Build Status](https://travis-ci.org/atom/language-gfm.svg?branch=master)](https://travis-ci.org/atom/language-gfm) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/rpub8qjyd8lt7wai/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-gfm/branch/master) |
| Go | [![macOS Build Status](https://travis-ci.org/atom/language-go.svg?branch=master)](https://travis-ci.org/atom/language-go) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/3fxxvv05p4hv92pn/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-go/branch/master) |
| HTML | [![macOS Build Status](https://travis-ci.org/atom/language-html.svg?branch=master)](https://travis-ci.org/atom/language-html) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/t6pk6mmdgcelfg85/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-html/branch/master) |
| Hyperlink | [![macOS Build Status](https://travis-ci.org/atom/language-hyperlink.svg?branch=master)](https://travis-ci.org/atom/language-hyperlink) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5tgvhph394r684l8/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-hyperlink/branch/master) |
| Java | [![macOS Build Status](https://travis-ci.org/atom/language-java.svg?branch=master)](https://travis-ci.org/atom/language-java) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/utoftje56n9u5x4h/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-java/branch/master) |
| JavaScript | [![macOS Build Status](https://travis-ci.org/atom/language-javascript.svg?branch=master)](https://travis-ci.org/atom/language-javascript) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ktooccwna96ssiyr/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-javascript-dijf8/branch/master) |
| JSON | [![macOS Build Status](https://travis-ci.org/atom/language-json.svg?branch=master)](https://travis-ci.org/atom/language-json) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5rx05vhdikk6c4cl/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-json/branch/master) |
| Less | [![macOS Build Status](https://travis-ci.org/atom/language-less.svg?branch=master)](https://travis-ci.org/atom/language-less) | [![Windows Build Sstatus](https://ci.appveyor.com/api/projects/status/aeina4fr4b0i7yay/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-less/branch/master) |
| Make | [![macOS Build Status](https://travis-ci.org/atom/language-make.svg?branch=master)](https://travis-ci.org/atom/language-make) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/vq1aascey21wxjh7/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-make/branch/master) |
| Mustache | [![macOS Build Status](https://travis-ci.org/atom/language-mustache.svg?branch=master)](https://travis-ci.org/atom/language-mustache) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mbxnxaojqp0g7ldv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-mustache/branch/master) |
| Objective-C | [![macOS Build Status](https://travis-ci.org/atom/language-objective-c.svg?branch=master)](https://travis-ci.org/atom/language-objective-c) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/27j8vfv5u95fjhkw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-objective-c/branch/master) |
| Perl | [![macOS Build Status](https://travis-ci.org/atom/language-perl.svg?branch=master)](https://travis-ci.org/atom/language-perl) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/dfs9inkkg40hchf8/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-perl/branch/master) |
| PHP | [![macOS Build Status](https://travis-ci.org/atom/language-php.svg?branch=master)](https://travis-ci.org/atom/language-php) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/y9h45ag4b72726jy/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-php/branch/master) |
| Python | [![macOS Build Status](https://travis-ci.org/atom/language-python.svg?branch=master)](https://travis-ci.org/atom/language-python) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/hmxrb9jttjh41es9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-python/branch/master) |
| Ruby | [![macOS Build Status](https://travis-ci.org/atom/language-ruby.svg?branch=master)](https://travis-ci.org/atom/language-ruby) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/71as182rm1adf2br/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-ruby/branch/master) |
| Ruby on Rails | [![macOS Build Status](https://travis-ci.org/atom/language-ruby-on-rails.svg?branch=master)](https://travis-ci.org/atom/language-ruby-on-rails) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5t4pa451fu5e0ghg/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-ruby-on-rails/branch/master) |
| Sass | [![macOS Build Status](https://travis-ci.org/atom/language-sass.svg?branch=master)](https://travis-ci.org/atom/language-sass) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/g7p16vainm4iuoot/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-sass/branch/master) |
| ShellScript | [![macOS Build Status](https://travis-ci.org/atom/language-shellscript.svg?branch=master)](https://travis-ci.org/atom/language-shellscript) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/p4um3lowgrg8y0ty/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-shellscript/branch/master) |
| SQL | [![macOS Build Status](https://travis-ci.org/atom/language-sql.svg?branch=master)](https://travis-ci.org/atom/language-sql) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ji31ouk5ehs4jdu1/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-sql/branch/master) |
| TODO | [![macOS Build Status](https://travis-ci.org/atom/language-todo.svg?branch=master)](https://travis-ci.org/atom/language-todo) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gcgb9m7h146lv6qp/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-todo/branch/master) |
| TOML | [![macOS Build Status](https://travis-ci.org/atom/language-toml.svg?branch=master)](https://travis-ci.org/atom/language-toml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kohao3fjyk6xv0sc/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-toml/branch/master) |
| XML | [![macOS Build Status](https://travis-ci.org/atom/language-xml.svg?branch=master)](https://travis-ci.org/atom/language-xml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/m5f6rn74a6h3q5uq/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-xml/branch/master) |
| YAML | [![macOS Build Status](https://travis-ci.org/atom/language-yaml.svg?branch=master)](https://travis-ci.org/atom/language-yaml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/eaa4ql7kipgphc2n/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-yaml/branch/master) |
| [C/C++](https://github.com/atom/language-c) | [![macOS Build Status](https://travis-ci.org/atom/language-c.svg?branch=master)](https://travis-ci.org/atom/language-c) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/8oy1hmp4yrij7c32/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-c/branch/master) |
| [C#](https://github.com/atom/language-csharp) | [![macOS Build Status](https://travis-ci.org/atom/language-csharp.svg?branch=master)](https://travis-ci.org/atom/language-csharp) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/j1as3753y5t90obn/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-csharp/branch/master) |
| [Clojure](https://github.com/atom/language-clojure) | [![macOS Build Status](https://travis-ci.org/atom/language-clojure.svg?branch=master)](https://travis-ci.org/atom/language-clojure) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/6kd5fs48y5hixde6/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-clojure/branch/master) |
| [CoffeeScript](https://github.com/atom/language-coffee-script) | [![macOS Build Status](https://travis-ci.org/atom/language-coffee-script.svg?branch=master)](https://travis-ci.org/atom/language-coffee-script) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/4j9aak7iwn2f2x7a/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-coffee-script/branch/master) |
| [CSS](https://github.com/atom/language-css) | [![macOS Build Status](https://travis-ci.org/atom/language-css.svg?branch=master)](https://travis-ci.org/atom/language-css) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/v8rvm88dxp73ko2y/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-css/branch/master) |
| [Git](https://github.com/atom/language-git) | [![macOS Build Status](https://travis-ci.org/atom/language-git.svg?branch=master)](https://travis-ci.org/atom/language-git) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/481319gyrr1feo8b/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-git/branch/master) |
| [GitHub Flavored Markdown](https://github.com/atom/language-gfm) | [![macOS Build Status](https://travis-ci.org/atom/language-gfm.svg?branch=master)](https://travis-ci.org/atom/language-gfm) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/rpub8qjyd8lt7wai/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-gfm/branch/master) |
| [Go](https://github.com/atom/language-go) | [![macOS Build Status](https://travis-ci.org/atom/language-go.svg?branch=master)](https://travis-ci.org/atom/language-go) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/3fxxvv05p4hv92pn/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-go/branch/master) |
| [HTML](https://github.com/atom/language-html) | [![macOS Build Status](https://travis-ci.org/atom/language-html.svg?branch=master)](https://travis-ci.org/atom/language-html) | [![Windows Build status](https://ci.appveyor.com/api/projects/status/t6pk6mmdgcelfg85/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-html/branch/master) |
| [Hyperlink](https://github.com/atom/language-hyperlink) | [![macOS Build Status](https://travis-ci.org/atom/language-hyperlink.svg?branch=master)](https://travis-ci.org/atom/language-hyperlink) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5tgvhph394r684l8/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-hyperlink/branch/master) |
| [Java](https://github.com/atom/language-java) | [![macOS Build Status](https://travis-ci.org/atom/language-java.svg?branch=master)](https://travis-ci.org/atom/language-java) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/utoftje56n9u5x4h/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-java/branch/master) |
| [JavaScript](https://github.com/atom/language-javascript) | [![macOS Build Status](https://travis-ci.org/atom/language-javascript.svg?branch=master)](https://travis-ci.org/atom/language-javascript) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ktooccwna96ssiyr/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-javascript-dijf8/branch/master) |
| [JSON](https://github.com/atom/language-json) | [![macOS Build Status](https://travis-ci.org/atom/language-json.svg?branch=master)](https://travis-ci.org/atom/language-json) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5rx05vhdikk6c4cl/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-json/branch/master) |
| [Less](https://github.com/atom/language-less) | [![macOS Build Status](https://travis-ci.org/atom/language-less.svg?branch=master)](https://travis-ci.org/atom/language-less) | [![Windows Build Sstatus](https://ci.appveyor.com/api/projects/status/aeina4fr4b0i7yay/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-less/branch/master) |
| [Make](https://github.com/atom/language-make) | [![macOS Build Status](https://travis-ci.org/atom/language-make.svg?branch=master)](https://travis-ci.org/atom/language-make) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/vq1aascey21wxjh7/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-make/branch/master) |
| [Mustache](https://github.com/atom/language-mustache) | [![macOS Build Status](https://travis-ci.org/atom/language-mustache.svg?branch=master)](https://travis-ci.org/atom/language-mustache) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/mbxnxaojqp0g7ldv/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-mustache/branch/master) |
| [Objective-C](https://github.com/atom/language-objective-c) | [![macOS Build Status](https://travis-ci.org/atom/language-objective-c.svg?branch=master)](https://travis-ci.org/atom/language-objective-c) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/27j8vfv5u95fjhkw/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-objective-c/branch/master) |
| [Perl](https://github.com/atom/language-perl) | [![macOS Build Status](https://travis-ci.org/atom/language-perl.svg?branch=master)](https://travis-ci.org/atom/language-perl) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/dfs9inkkg40hchf8/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-perl/branch/master) |
| [PHP](https://github.com/atom/language-php) | [![macOS Build Status](https://travis-ci.org/atom/language-php.svg?branch=master)](https://travis-ci.org/atom/language-php) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/y9h45ag4b72726jy/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-php/branch/master) |
| [Python](https://github.com/atom/language-python) | [![macOS Build Status](https://travis-ci.org/atom/language-python.svg?branch=master)](https://travis-ci.org/atom/language-python) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/hmxrb9jttjh41es9/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-python/branch/master) |
| [Ruby](https://github.com/atom/language-ruby) | [![macOS Build Status](https://travis-ci.org/atom/language-ruby.svg?branch=master)](https://travis-ci.org/atom/language-ruby) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/71as182rm1adf2br/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-ruby/branch/master) |
| [Ruby on Rails](https://github.com/atom/language-ruby-on-rails) | [![macOS Build Status](https://travis-ci.org/atom/language-ruby-on-rails.svg?branch=master)](https://travis-ci.org/atom/language-ruby-on-rails) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/5t4pa451fu5e0ghg/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-ruby-on-rails/branch/master) |
| [Sass](https://github.com/atom/language-sass) | [![macOS Build Status](https://travis-ci.org/atom/language-sass.svg?branch=master)](https://travis-ci.org/atom/language-sass) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/g7p16vainm4iuoot/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-sass/branch/master) |
| [ShellScript](https://github.com/atom/language-shellscript) | [![macOS Build Status](https://travis-ci.org/atom/language-shellscript.svg?branch=master)](https://travis-ci.org/atom/language-shellscript) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/p4um3lowgrg8y0ty/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-shellscript/branch/master) |
| [SQL](https://github.com/atom/language-sql) | [![macOS Build Status](https://travis-ci.org/atom/language-sql.svg?branch=master)](https://travis-ci.org/atom/language-sql) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/ji31ouk5ehs4jdu1/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-sql/branch/master) |
| [TODO](https://github.com/atom/language-todo) | [![macOS Build Status](https://travis-ci.org/atom/language-todo.svg?branch=master)](https://travis-ci.org/atom/language-todo) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/gcgb9m7h146lv6qp/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-todo/branch/master) |
| [TOML](https://github.com/atom/language-toml) | [![macOS Build Status](https://travis-ci.org/atom/language-toml.svg?branch=master)](https://travis-ci.org/atom/language-toml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/kohao3fjyk6xv0sc/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-toml/branch/master) |
| [XML](https://github.com/atom/language-xml) | [![macOS Build Status](https://travis-ci.org/atom/language-xml.svg?branch=master)](https://travis-ci.org/atom/language-xml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/m5f6rn74a6h3q5uq/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-xml/branch/master) |
| [YAML](https://github/atom/language-yaml) | [![macOS Build Status](https://travis-ci.org/atom/language-yaml.svg?branch=master)](https://travis-ci.org/atom/language-yaml) | [![Windows Build Status](https://ci.appveyor.com/api/projects/status/eaa4ql7kipgphc2n/branch/master?svg=true)](https://ci.appveyor.com/project/Atom/language-yaml/branch/master) |

View File

@@ -49,9 +49,13 @@ To also install the newly built application, use `--create-debian-package` or `-
sudo update-alternatives --config gcc # choose gcc-5 from the list
```
### Fedora / CentOS / RHEL
### Fedora
* `sudo dnf --assumeyes install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools libX11-devel libxkbfile-devel`
* `sudo dnf install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools libX11-devel libxkbfile-devel`
### RHEL / CentOS
* `sudo yum install make gcc gcc-c++ glibc-devel git-core libgnome-keyring-devel rpmdevtools libX11-devel libxkbfile-devel`
### Arch

View File

@@ -26,4 +26,4 @@ To also install the newly built application, use `script/build --install`.
## Troubleshooting
### macOS build error reports in atom/atom
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Aos-x&type=Issues) to get a list of reports about build errors on macOS.
* Use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Amac&type=Issues) to get a list of reports about build errors on macOS.

View File

@@ -2,20 +2,21 @@
## Requirements
* Node.js 4.4.x or later
* Node.js 4.4.x or later (the architecture of node available to the build system will determine whether you build 32-bit or 64-bit Atom)
* Python v2.7.x
* The python.exe must be available at `%SystemDrive%\Python27\python.exe`. If it is installed elsewhere, you can create a symbolic link to the directory containing the python.exe using: `mklink /d %SystemDrive%\Python27 D:\elsewhere\Python27`
* The python.exe must be available at `%SystemDrive%\Python27\python.exe`. If it is installed elsewhere create a symbolic link to the directory containing the python.exe using: `mklink /d %SystemDrive%\Python27 D:\elsewhere\Python27`
* 7zip (7z.exe available from the command line) - for unpacking Chromedriver and creating distribution zips
* Visual Studio, either:
* [Visual C++ Build Tools 2015](http://landinghub.visualstudio.com/visual-cpp-build-tools)
* [Visual Studio 2013 Update 5](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs) (Express Edition or better)
* [Visual Studio 2015](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs) (Community Edition or better)
Whichever version you use, ensure that:
Also ensure that:
* The default installation folder is chosen so the build tools can find it
* If using Visual Studio make sure Visual C++ support is selected/installed
* If using Visual C++ Build Tools make sure Windows 8 SDK is selected/installed
* A `git` command is in your path
* Set the `GYP_MSVS_VERSION` environment variable to the Visual Studio/Build Tools version (`2013` or `2015`) e.g. ``[Environment]::SetEnvironmentVariable("GYP_MSVS_VERSION", "2015", "User")`` in PowerShell or set it in Windows advanced system settings control panel.
* Set the `GYP_MSVS_VERSION` environment variable to the Visual Studio/Build Tools version (`2013` or `2015`) e.g. ``[Environment]::SetEnvironmentVariable("GYP_MSVS_VERSION", "2015", "User")`` in PowerShell (or set it in Windows advanced system settings).
## Instructions
@@ -32,8 +33,8 @@ To also install the newly built application, use `script\build --create-windows-
### `script\build` Options
* `--code-sign`: signs the application with the GitHub certificate specified in `$WIN_P12KEY_URL`.
* `--compress-artifacts`: zips the generated application as `out/atom-windows.zip` (requires 7-zip).
* `--create-windows-installer`: creates an `.msi`, an `.exe` and a `.nupkg` installer in the `out/` directory.
* `--compress-artifacts`: zips the generated application as `out\atom-windows.zip` (requires [7-Zip](http://www.7-zip.org)).
* `--create-windows-installer`: creates an `.msi`, an `.exe` and two `.nupkg` packages in the `out` directory.
* `--install`: installs the application in `%LOCALAPPDATA%\Atom\app-dev\`.
### Running tests
@@ -53,22 +54,18 @@ When building Atom from source, the `apm` command is not added to the system pat
### Common Errors
* `node is not recognized`
* If you just installed Node.js, you'll need to restart Command Prompt before the `node` command is available on your Path.
* If you just installed Node.js, you'll need to restart Command Prompt before the `node` command is available on your path.
* `msbuild.exe failed with exit code: 1`
* If you installed Visual Studio, ensure you have Visual C++ support installed. Go into Add/Remove Programs, select Visual Studio, press Modify, and then check the Visual C++ box.
* If you installed Visual C++ Build Tools, ensure you have Windows 8 SDK support installed. Go into Add/Remove Programs, select Visual Studio, press Modify and then check the Windows 8 SDK box.
* If using **Visual Studio**, ensure you have the **Visual C++** component installed. Go into Add/Remove Programs, select Visual Studio, press Modify, and then check the Visual C++ box.
* If using **Visual C++ Build Tools**, ensure you have the **Windows 8 SDK** component installed. Go into Add/Remove Programs, select Visual C++ Build Tools, press Modify and then check the Windows 8 SDK box.
* `script\build` stop with no error or warning shortly after displaying the versions of node, npm and Python
* `script\build` stops with no error or warning shortly after displaying the versions of node, npm and Python
* Make sure that the path where you have checked out Atom does not include a space. For example, use `C:\atom` instead of `C:\my stuff\atom`.
* `script\build` outputs only the Node.js and Python versions before returning
* Try moving the repository to `C:\atom`. Most likely, the path is too long.
See [issue #2200](https://github.com/atom/atom/issues/2200).
* Try moving the repository to `C:\atom`. Most likely, the path is too long. See [issue #2200](https://github.com/atom/atom/issues/2200).
* `error MSB4025: The project file could not be loaded. Invalid character in the given encoding.`
* This can occur because your home directory (`%USERPROFILE%`) has non-ASCII
characters in it. This is a bug in [gyp](https://code.google.com/p/gyp/)
* This can occur because your home directory (`%USERPROFILE%`) has non-ASCII characters in it. This is a bug in [gyp](https://code.google.com/p/gyp/)
which is used to build native Node.js modules and there is no known workaround.
* https://github.com/TooTallNate/node-gyp/issues/297
* https://code.google.com/p/gyp/issues/detail?id=393
@@ -80,14 +77,14 @@ When building Atom from source, the `apm` command is not added to the system pat
* See the next item.
* `error MSB8020: The build tools for Visual Studio 201? (Platform Toolset = 'v1?0') cannot be found.`
* Try setting the `GYP_MSVS_VERSION` environment variable to 2013 or 2015 depending on what version of Visual Studio/Build Tools is installed and then `script\clean` followed by `script\build` (re-open the Command Prompt if you set the variable using the GUI).
* Try setting the `GYP_MSVS_VERSION` environment variable to **2013** or **2015** depending on what version of Visual Studio/Build Tools is installed and then `script\clean` followed by `script\build` (re-open the Command Prompt if you set the variable using the GUI).
* `'node-gyp' is not recognized as an internal or external command, operable program or batch file.`
* Try running `npm install -g node-gyp`, and run `script\build` again.
* Other `node-gyp` errors on first build attempt, even though the right Node.js and Python versions are installed.
* Do try the build command one more time, as experience shows it often works on second try in many of these cases.
* Do try the build command one more time as experience shows it often works on second try in many cases.
### Windows build error reports in atom/atom
* If all fails, use [this search](https://github.com/atom/atom/search?q=label%3Abuild-error+label%3Awindows&type=Issues) to get a list of reports about build errors on Windows, and see if yours has already been reported.
* If it hasn't, please open a new issue with your Windows version, architecture (x86 or amd64), and a screenshot of your build output, including the Node.js and Python versions.
* If it hasn't, please open a new issue with your Windows version, architecture (x86 or x64), and a screenshot of your build output, including the Node.js and Python versions.

View File

@@ -6,11 +6,11 @@
'down': 'core:move-down'
'left': 'core:move-left'
'right': 'core:move-right'
'ctrl-alt-r': 'window:reload'
'ctrl-shift-f5': 'window:reload'
'ctrl-shift-i': 'window:toggle-dev-tools'
'ctrl-alt-p': 'window:run-package-specs'
'ctrl-shift-y': 'window:run-package-specs'
'ctrl-shift-o': 'application:open-folder'
'ctrl-alt-o': 'application:add-project-folder'
'ctrl-shift-a': 'application:add-project-folder'
'ctrl-shift-pageup': 'pane:move-item-left'
'ctrl-shift-pagedown': 'pane:move-item-right'
'f11': 'window:toggle-full-screen'
@@ -70,12 +70,12 @@
'ctrl-k left': 'pane:split-left-and-copy-active-item' # Atom Specific
'ctrl-k right': 'pane:split-right-and-copy-active-item' # Atom Specific
'ctrl-k ctrl-w': 'pane:close' # Atom Specific
'ctrl-k alt-ctrl-w': 'pane:close-other-items' # Atom Specific
'ctrl-k ctrl-alt-w': 'pane:close-other-items' # Atom Specific
'ctrl-k ctrl-p': 'window:focus-previous-pane'
'ctrl-k ctrl-n': 'window:focus-next-pane'
'ctrl-k ctrl-up': 'window:focus-pane-above'
'ctrl-k ctrl-down': 'window:focus-pane-below'
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
'ctrl-k ctrl-up': 'window:focus-pane-above'
'ctrl-k ctrl-down': 'window:focus-pane-below'
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
'alt-1': 'pane:show-item-1'
'alt-2': 'pane:show-item-2'
@@ -108,16 +108,14 @@
# Sublime Parity
'ctrl-a': 'core:select-all'
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
'ctrl-k ctrl-u': 'editor:upper-case'
'ctrl-k ctrl-l': 'editor:lower-case'
'ctrl-l': 'editor:select-line'
'atom-workspace atom-text-editor:not([mini])':
# Atom specific
'alt-ctrl-z': 'editor:checkout-head-revision'
'ctrl-<': 'editor:scroll-to-cursor'
'alt-ctrl-f': 'editor:fold-selection'
'ctrl-alt-shift-[': 'editor:fold-selection'
# Sublime Parity
'ctrl-enter': 'editor:newline-below'

View File

@@ -12,11 +12,11 @@
'ctrl-down': 'core:move-down'
'left': 'core:move-left'
'right': 'core:move-right'
'ctrl-alt-r': 'window:reload'
'ctrl-shift-f5': 'window:reload'
'ctrl-shift-i': 'window:toggle-dev-tools'
'ctrl-alt-p': 'window:run-package-specs'
'ctrl-shift-y': 'window:run-package-specs'
'ctrl-shift-o': 'application:open-folder'
'ctrl-alt-o': 'application:add-project-folder'
'ctrl-shift-a': 'application:add-project-folder'
'ctrl-shift-left': 'pane:move-item-left'
'ctrl-shift-right': 'pane:move-item-right'
'f11': 'window:toggle-full-screen'
@@ -75,12 +75,12 @@
'ctrl-k left': 'pane:split-left-and-copy-active-item' # Atom Specific
'ctrl-k right': 'pane:split-right-and-copy-active-item' # Atom Specific
'ctrl-k ctrl-w': 'pane:close' # Atom Specific
'ctrl-k alt-ctrl-w': 'pane:close-other-items' # Atom Specific
'ctrl-k ctrl-alt-w': 'pane:close-other-items' # Atom Specific
'ctrl-k ctrl-p': 'window:focus-previous-pane'
'ctrl-k ctrl-n': 'window:focus-next-pane'
'ctrl-k ctrl-up': 'window:focus-pane-above'
'ctrl-k ctrl-down': 'window:focus-pane-below'
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
'ctrl-k ctrl-up': 'window:focus-pane-above'
'ctrl-k ctrl-down': 'window:focus-pane-below'
'ctrl-k ctrl-left': 'window:focus-pane-on-left'
'ctrl-k ctrl-right': 'window:focus-pane-on-right'
'alt-1': 'pane:show-item-1'
'alt-2': 'pane:show-item-2'
@@ -113,16 +113,14 @@
# Sublime Parity
'ctrl-a': 'core:select-all'
'ctrl-alt-shift-p': 'editor:log-cursor-scope'
'ctrl-k ctrl-u': 'editor:upper-case'
'ctrl-k ctrl-l': 'editor:lower-case'
'ctrl-l': 'editor:select-line'
'atom-workspace atom-text-editor:not([mini])':
# Atom specific
'alt-ctrl-z': 'editor:checkout-head-revision'
'ctrl-<': 'editor:scroll-to-cursor'
'alt-ctrl-f': 'editor:fold-selection'
'ctrl-alt-shift-[': 'editor:fold-selection'
# Sublime Parity
'ctrl-enter': 'editor:newline-below'

View File

@@ -108,9 +108,9 @@
submenu: [
{ label: 'Fold', command: 'editor:fold-current-row' }
{ label: 'Unfold', command: 'editor:unfold-current-row' }
{ label: 'Fold All', command: 'editor:fold-all' }
{ label: 'Unfold All', command: 'editor:unfold-all' }
{ type: 'separator' }
{ label: 'Fold All', command: 'editor:fold-all' }
{ label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' }
{ label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' }
{ label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' }

View File

@@ -81,9 +81,9 @@
submenu: [
{ label: '&Fold', command: 'editor:fold-current-row' }
{ label: '&Unfold', command: 'editor:unfold-current-row' }
{ label: 'Fol&d All', command: 'editor:fold-all' }
{ label: 'Unfold &All', command: 'editor:unfold-all' }
{ type: 'separator' }
{ label: 'Fol&d All', command: 'editor:fold-all' }
{ label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' }
{ label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' }
{ label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' }

View File

@@ -89,9 +89,9 @@
submenu: [
{ label: '&Fold', command: 'editor:fold-current-row' }
{ label: '&Unfold', command: 'editor:unfold-current-row' }
{ label: 'Fol&d All', command: 'editor:fold-all' }
{ label: 'Unfold &All', command: 'editor:unfold-all' }
{ type: 'separator' }
{ label: 'Fol&d All', command: 'editor:fold-all' }
{ label: 'Fold Level 1', command: 'editor:fold-at-indent-level-1' }
{ label: 'Fold Level 2', command: 'editor:fold-at-indent-level-2' }
{ label: 'Fold Level 3', command: 'editor:fold-at-indent-level-3' }

View File

@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "1.13.0-dev",
"version": "1.14.0-dev",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/main-process/main.js",
"repository": {
@@ -12,11 +12,11 @@
"url": "https://github.com/atom/atom/issues"
},
"license": "MIT",
"electronVersion": "1.3.6",
"electronVersion": "1.3.13",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "7.1.1",
"atom-space-pen-views": "^2.0.0",
"atom-keymap": "7.1.15",
"atom-select-list": "0.0.6",
"atom-ui": "0.4.1",
"babel-core": "5.8.38",
"cached-run-in-this-context": "0.4.1",
@@ -33,7 +33,7 @@
"fs-plus": "2.9.2",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
"git-utils": "^4.1.2",
"git-utils": "4.1.2",
"glob": "^7.1.1",
"grim": "1.5.0",
"jasmine-json": "~0.0",
@@ -45,17 +45,18 @@
"marked": "^0.3.6",
"minimatch": "^3.0.3",
"mocha": "2.5.1",
"mock-spawn": "^0.2.6",
"normalize-package-data": "^2.0.0",
"nslog": "^3",
"oniguruma": "6.1.0",
"pathwatcher": "~6.5",
"pathwatcher": "^6.7.1",
"postcss": "5.2.4",
"postcss-selector-parser": "2.2.1",
"property-accessors": "^1.1.3",
"random-words": "0.0.1",
"resolve": "^1.1.6",
"runas": "^3.1",
"scandal": "^2.2.1",
"scandal": "2.2.2",
"scoped-property-store": "^0.17.0",
"scrollbar-style": "^3.2",
"season": "^5.4.1",
@@ -64,7 +65,7 @@
"sinon": "1.17.4",
"source-map-support": "^0.3.2",
"temp": "0.8.1",
"text-buffer": "9.4.1",
"text-buffer": "9.4.3",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.6",
"winreg": "^1.2.1",
@@ -77,88 +78,88 @@
"atom-light-ui": "0.46.0",
"base16-tomorrow-dark-theme": "1.4.0",
"base16-tomorrow-light-theme": "1.4.0",
"one-dark-ui": "1.8.2",
"one-light-ui": "1.8.2",
"one-dark-ui": "1.9.0",
"one-light-ui": "1.9.0",
"one-dark-syntax": "1.6.0",
"one-light-syntax": "1.6.0",
"solarized-dark-syntax": "1.1.1",
"solarized-light-syntax": "1.1.1",
"about": "1.7.2",
"archive-view": "0.62.0",
"archive-view": "0.62.2",
"autocomplete-atom-api": "0.10.0",
"autocomplete-css": "0.14.1",
"autocomplete-html": "0.7.2",
"autocomplete-plus": "2.33.1",
"autocomplete-plus": "2.34.2",
"autocomplete-snippets": "1.11.0",
"autoflow": "0.27.0",
"autoflow": "0.29.0",
"autosave": "0.23.2",
"background-tips": "0.26.1",
"bookmarks": "0.43.2",
"bracket-matcher": "0.82.2",
"command-palette": "0.39.1",
"bookmarks": "0.43.4",
"bracket-matcher": "0.85.0",
"command-palette": "0.39.2",
"deprecation-cop": "0.55.1",
"dev-live-reload": "0.47.0",
"encoding-selector": "0.22.0",
"exception-reporting": "0.40.0",
"find-and-replace": "0.204.1",
"fuzzy-finder": "1.4.0",
"exception-reporting": "0.40.1",
"find-and-replace": "0.204.7",
"fuzzy-finder": "1.4.1",
"git-diff": "1.2.0",
"go-to-line": "0.31.2",
"grammar-selector": "0.48.2",
"image-view": "0.60.0",
"incompatible-packages": "0.26.1",
"keybinding-resolver": "0.35.0",
"line-ending-selector": "0.5.0",
"line-ending-selector": "0.5.1",
"link": "0.31.2",
"markdown-preview": "0.159.1",
"metrics": "1.0.0",
"notifications": "0.65.1",
"metrics": "1.1.2",
"notifications": "0.65.2",
"open-on-github": "1.2.1",
"package-generator": "1.0.2",
"settings-view": "0.244.0",
"snippets": "1.0.3",
"spell-check": "0.68.5",
"status-bar": "1.6.0",
"snippets": "1.0.4",
"spell-check": "0.69.0",
"status-bar": "1.7.0",
"styleguide": "0.48.0",
"symbols-view": "0.113.1",
"symbols-view": "0.113.2",
"tabs": "0.103.1",
"timecop": "0.33.2",
"tree-view": "0.211.1",
"update-package-dependencies": "0.10.0",
"welcome": "0.35.1",
"welcome": "0.35.2",
"whitespace": "0.35.0",
"wrap-guide": "0.39.0",
"language-c": "0.54.0",
"language-clojure": "0.22.1",
"language-coffee-script": "0.48.1",
"language-csharp": "0.12.1",
"language-css": "0.40.1",
"language-coffee-script": "0.48.2",
"language-csharp": "0.13.0",
"language-css": "0.41.0",
"language-gfm": "0.88.0",
"language-git": "0.15.0",
"language-git": "0.19.0",
"language-go": "0.43.0",
"language-html": "0.46.1",
"language-html": "0.47.1",
"language-hyperlink": "0.16.1",
"language-java": "0.24.0",
"language-javascript": "0.122.0",
"language-javascript": "0.124.0",
"language-json": "0.18.3",
"language-less": "0.29.6",
"language-make": "0.22.2",
"language-mustache": "0.13.0",
"language-less": "0.30.0",
"language-make": "0.22.3",
"language-mustache": "0.13.1",
"language-objective-c": "0.15.1",
"language-perl": "0.37.0",
"language-php": "0.37.3",
"language-property-list": "0.8.0",
"language-property-list": "0.9.0",
"language-python": "0.45.1",
"language-ruby": "0.70.2",
"language-ruby": "0.70.3",
"language-ruby-on-rails": "0.25.1",
"language-sass": "0.57.0",
"language-shellscript": "0.23.0",
"language-sass": "0.57.1",
"language-shellscript": "0.24.0",
"language-source": "0.9.0",
"language-sql": "0.25.0",
"language-sql": "0.25.1",
"language-text": "0.7.1",
"language-todo": "0.29.1",
"language-toml": "0.18.1",
"language-xml": "0.34.12",
"language-xml": "0.34.13",
"language-yaml": "0.27.1"
},
"private": true,

View File

@@ -8,6 +8,11 @@ AutoReqProv: no # Avoid libchromiumcontent.so missing dependency
Prefix: <%= installDir %>
Requires: lsb-core-noarch
%if 0%{?fedora} || 0%{?rhel}
Requires: libXScrnSaver
%else
Requires: libXss1
%endif
%description
<%= description %>

View File

@@ -1,3 +1,3 @@
@echo off
"%~dp0\..\app\apm\bin\node.exe" "%~dp0\..\app\apm\lib\cli.js" %*
"%~dp0\..\app\apm\bin\apm.cmd" %*

View File

@@ -1,4 +1,3 @@
#!/bin/sh
directory=$(dirname "$0")
"$directory/../app/apm/bin/node.exe" "$directory/../app/apm/lib/cli.js" "$@"
"$(dirname "$0")/../app/apm/apm.sh" "$@"

View File

@@ -866,6 +866,10 @@
"hasDeprecations": true,
"latestHasDeprecations": true
},
"language-nlf": {
"hasAlternative": true,
"alternative": "language-nsis"
},
"language-rspec": {
"version": "<=0.2.1",
"hasDeprecations": true,

View File

@@ -7,23 +7,7 @@ const spawnSync = require('./spawn-sync')
const CONFIG = require('../config')
module.exports = function (packagedAppPath) {
let appArchiveName
if (process.platform === 'darwin') {
appArchiveName = 'atom-mac.zip'
} else if (process.platform === 'win32') {
appArchiveName = 'atom-windows.zip'
} else {
let arch
if (process.arch === 'ia32') {
arch = 'i386'
} else if (process.arch === 'x64') {
arch = 'amd64'
} else {
arch = process.arch
}
appArchiveName = `atom-${arch}.tar.gz`
}
const appArchivePath = path.join(CONFIG.buildOutputPath, appArchiveName)
const appArchivePath = path.join(CONFIG.buildOutputPath, getArchiveName())
compress(packagedAppPath, appArchivePath)
if (process.platform === 'darwin') {
@@ -32,6 +16,22 @@ module.exports = function (packagedAppPath) {
}
}
function getArchiveName () {
switch (process.platform) {
case 'darwin': return 'atom-mac.zip'
case 'win32': return `atom-windows.zip`
default: return `atom-${getLinuxArchiveArch()}.tar.gz`
}
}
function getLinuxArchiveArch () {
switch (process.arch) {
case 'ia32': return 'i386'
case 'x64' : return 'amd64'
default: return process.arch
}
}
function compress (inputDirPath, outputArchivePath) {
if (fs.existsSync(outputArchivePath)) {
console.log(`Deleting "${outputArchivePath}"`)

View File

@@ -11,30 +11,36 @@ const spawnSync = require('./spawn-sync')
const CONFIG = require('../config')
module.exports = function (packagedAppPath, codeSign) {
const archSuffix = process.arch === 'ia32' ? '' : '-' + process.arch
const options = {
appDirectory: packagedAppPath,
authors: 'GitHub Inc.',
iconUrl: `https://raw.githubusercontent.com/atom/atom/master/resources/app-icons/${CONFIG.channel}/atom.ico`,
loadingGif: path.join(CONFIG.repositoryRootPath, 'resources', 'win', 'loading.gif'),
outputDirectory: CONFIG.buildOutputPath,
remoteReleases: `https://atom.io/api/updates?version=${CONFIG.appMetadata.version}`,
remoteReleases: `https://atom.io/api/updates${archSuffix}`,
setupIcon: path.join(CONFIG.repositoryRootPath, 'resources', 'app-icons', CONFIG.channel, 'atom.ico')
}
// Remove this once an x64 version is published or atom.io is returning blank instead of 404 for RELEASES-X64
if (process.arch === 'x64') {
options.remoteReleases = null
}
const certPath = path.join(os.tmpdir(), 'win.p12')
const signing = codeSign && process.env.WIN_P12KEY_URL
const signing = codeSign && process.env.ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL
if (signing) {
downloadFileFromGithub(process.env.WIN_P12KEY_URL, certPath)
downloadFileFromGithub(process.env.ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL, certPath)
var signParams = []
signParams.push(`/f ${certPath}`) // Signing cert file
signParams.push(`/p ${process.env.WIN_P12KEY_PASSWORD}`) // Signing cert password
signParams.push(`/p ${process.env.ATOM_WIN_CODE_SIGNING_CERT_PASSWORD}`) // Signing cert password
signParams.push('/fd sha256') // File digest algorithm
signParams.push('/tr http://timestamp.digicert.com') // Time stamp server
signParams.push('/td sha256') // Times stamp algorithm
options.signWithParams = signParams.join(' ')
} else {
console.log('Skipping code-signing. Specify the --code-sign option and provide a WIN_P12KEY_URL environment variable to perform code-signing'.gray)
console.log('Skipping code-signing. Specify the --code-sign option and provide a ATOM_WIN_CODE_SIGNING_CERT_DOWNLOAD_URL environment variable to perform code-signing'.gray)
}
const cleanUp = function () {

View File

@@ -22,7 +22,7 @@ module.exports = {
// Include the electron minor version in the fingerprint since that changing requires a re-install
const electronVersion = CONFIG.appMetadata.electronVersion.replace(/\.\d+$/, '')
const apmVersion = CONFIG.apmMetadata.dependencies['atom-package-manager']
const body = electronVersion + apmVersion + process.platform + process.version
const body = electronVersion + apmVersion + process.platform + process.version + process.arch
return crypto.createHash('sha1').update(body).digest('hex')
}
}

View File

@@ -11,26 +11,23 @@ const syncRequest = require('sync-request')
const CONFIG = require('../config')
module.exports = function () {
if (process.platform === 'darwin') {
// Chromedriver is only distributed with the first patch release for any given
// major and minor version of electron.
const electronVersion = semver.parse(CONFIG.appMetadata.electronVersion)
const electronVersionWithChromedriver = `${electronVersion.major}.${electronVersion.minor}.0`
const electronAssets = getElectronAssetsForVersion(electronVersionWithChromedriver)
const chromedriverAssets = electronAssets.filter(e => /chromedriver.*darwin-x64/.test(e.name))
assert(chromedriverAssets.length === 1, 'Found more than one chrome driver asset to download!')
const chromedriverAsset = chromedriverAssets[0]
// Chromedriver is only distributed with the first patch release for any given
// major and minor version of electron.
const electronVersion = semver.parse(CONFIG.appMetadata.electronVersion)
const electronVersionWithChromedriver = `${electronVersion.major}.${electronVersion.minor}.0`
const electronAssets = getElectronAssetsForVersion(electronVersionWithChromedriver)
const chromeDriverMatch = new RegExp(`^chromedriver-v.*-${process.platform}-${process.arch}`)
const chromedriverAssets = electronAssets.filter(e => chromeDriverMatch.test(e.name))
assert(chromedriverAssets.length === 1, 'Found more than one chrome driver asset to download!')
const chromedriverAsset = chromedriverAssets[0]
const chromedriverZipPath = path.join(CONFIG.electronDownloadPath, `electron-${electronVersionWithChromedriver}-${chromedriverAsset.name}`)
if (!fs.existsSync(chromedriverZipPath)) {
downloadFileFromGithub(chromedriverAsset.url, chromedriverZipPath)
}
const chromedriverDirPath = path.join(CONFIG.electronDownloadPath, 'chromedriver')
unzipPath(chromedriverZipPath, chromedriverDirPath)
} else {
console.log('Skipping Chromedriver download because it is used only on macOS'.gray)
const chromedriverZipPath = path.join(CONFIG.electronDownloadPath, `electron-${electronVersionWithChromedriver}-${chromedriverAsset.name}`)
if (!fs.existsSync(chromedriverZipPath)) {
downloadFileFromGithub(chromedriverAsset.url, chromedriverZipPath)
}
const chromedriverDirPath = path.join(CONFIG.electronDownloadPath, 'chromedriver')
unzipPath(chromedriverZipPath, chromedriverDirPath)
}
function getElectronAssetsForVersion (version) {
@@ -52,5 +49,16 @@ function unzipPath (inputPath, outputPath) {
}
console.log(`Unzipping "${inputPath}" to "${outputPath}"`)
spawnSync('unzip', [inputPath, '-d', outputPath])
try {
spawnSync('unzip', [inputPath, '-d', outputPath])
}
catch(err) {
if (err.code === 'ENOENT') {
// Unzip might not be available on Windows even though it comes with git so fall back to 7zip
spawnSync('7z', ['x', inputPath, `-o${outputPath}`])
}
else {
throw err;
}
}
}

View File

@@ -12,10 +12,6 @@ module.exports = function () {
// Set our target (Electron) version so that node-pre-gyp can download the
// proper binaries.
installEnv.npm_config_target = CONFIG.appMetadata.electronVersion;
// Force 32-bit modules on Windows. (Ref.: https://github.com/atom/atom/issues/10450)
if (process.platform === 'win32') {
installEnv.npm_config_target_arch = 'ia32'
}
childProcess.execFileSync(
CONFIG.getApmBinPath(),
['--loglevel=error', 'install'],

View File

@@ -18,12 +18,7 @@ module.exports = function () {
'app-bundle-id': 'com.github.atom',
'app-copyright': `Copyright © 2014-${(new Date()).getFullYear()} GitHub, Inc. All rights reserved.`,
'app-version': CONFIG.appMetadata.version,
'arch': (() => {
if (process.platform === 'linux') {
return process.arch
} else {
return process.platform === 'win32' ? 'ia32' : 'x64'
}})(),
'arch': process.platform === 'darwin' ? 'x64' : process.arch, // OS X is 64-bit only
'asar': {unpack: buildAsarUnpackGlobExpression()},
'build-version': CONFIG.appMetadata.version,
'download': {cache: CONFIG.electronDownloadPath},
@@ -174,6 +169,9 @@ function renamePackagedAppDir (packageOutputDirPath) {
} else {
const appName = CONFIG.channel === 'beta' ? 'Atom Beta' : 'Atom'
packagedAppPath = path.join(CONFIG.buildOutputPath, appName)
if (process.platform === 'win32' && process.arch !== 'ia32') {
packagedAppPath += ` ${process.arch}`
}
if (fs.existsSync(packagedAppPath)) fs.removeSync(packagedAppPath)
fs.renameSync(packageOutputDirPath, packagedAppPath)
}

View File

@@ -9,7 +9,7 @@
"csslint": "1.0.2",
"donna": "1.0.13",
"electron-packager": "7.3.0",
"electron-winstaller": "2.3.4",
"electron-winstaller": "2.5.0",
"fs-extra": "0.30.0",
"glob": "7.0.3",
"joanna": "0.0.6",

View File

@@ -93,11 +93,15 @@ function runBenchmarkTests (callback) {
cp.on('close', exitCode => { callback(null, exitCode) })
}
let testSuitesToRun
if (process.platform === 'darwin') {
testSuitesToRun = [runCoreMainProcessTests, runCoreRenderProcessTests, runBenchmarkTests].concat(packageTestSuites)
} else {
testSuitesToRun = [runCoreMainProcessTests]
let testSuitesToRun = testSuitesForPlatform(process.platform)
function testSuitesForPlatform(platform) {
switch(platform) {
case 'darwin': return [runCoreMainProcessTests, runCoreRenderProcessTests, runBenchmarkTests].concat(packageTestSuites)
case 'win32': return (process.arch === 'x64') ? [runCoreMainProcessTests, runCoreRenderProcessTests] : [runCoreMainProcessTests]
case 'linux': return [runCoreMainProcessTests]
default: return []
}
}
async.series(testSuitesToRun, function (err, exitCodes) {

View File

@@ -1,10 +1,13 @@
_ = require 'underscore-plus'
path = require 'path'
temp = require 'temp'
temp = require('temp').track()
AtomEnvironment = require '../src/atom-environment'
StorageFolder = require '../src/storage-folder'
describe "AtomEnvironment", ->
afterEach ->
temp.cleanupSync()
describe 'window sizing methods', ->
describe '::getPosition and ::setPosition', ->
originalPosition = null
@@ -324,7 +327,7 @@ describe "AtomEnvironment", ->
describe "::unloadEditorWindow()", ->
it "saves the BlobStore so it can be loaded after reload", ->
configDirPath = temp.mkdirSync()
configDirPath = temp.mkdirSync('atom-spec-environment')
fakeBlobStore = jasmine.createSpyObj("blob store", ["save"])
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, enablePersistence: true, configDirPath, blobStore: fakeBlobStore, window, document})
@@ -336,7 +339,7 @@ describe "AtomEnvironment", ->
describe "::destroy()", ->
it "does not throw exceptions when unsubscribing from ipc events (regression)", ->
configDirPath = temp.mkdirSync()
configDirPath = temp.mkdirSync('atom-spec-environment')
fakeDocument = {
addEventListener: ->
removeEventListener: ->
@@ -401,6 +404,8 @@ describe "AtomEnvironment", ->
subscription?.dispose()
it "invokes onUpdateAvailable listeners", ->
return unless process.platform is 'darwin' # Test tied to electron autoUpdater, we use something else on Linux and Win32
atom.listenForUpdates()
updateAvailableHandler = jasmine.createSpy("update-available-handler")

119
spec/atom-paths-spec.js Normal file
View File

@@ -0,0 +1,119 @@
/** @babel */
import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers'
import {app} from 'remote'
import atomPaths from '../src/atom-paths'
import fs from 'fs-plus'
import path from 'path'
const temp = require('temp').track()
describe("AtomPaths", () => {
const portableAtomHomePath = path.join(atomPaths.getAppDirectory(), '.atom')
console.log(portableAtomHomePath)
afterEach(() => {
atomPaths.setAtomHome(app.getPath('home'))
})
describe('SetAtomHomePath', () => {
describe('when a portable .atom folder exists', () => {
beforeEach(() => {
delete process.env.ATOM_HOME
if (!fs.existsSync(portableAtomHomePath))
fs.mkdirSync(portableAtomHomePath)
})
afterEach(() => {
delete process.env.ATOM_HOME
fs.removeSync(portableAtomHomePath)
})
it('sets ATOM_HOME to the portable .atom folder if it has permission', () => {
atomPaths.setAtomHome(app.getPath('home'))
expect(process.env.ATOM_HOME).toEqual(portableAtomHomePath)
})
it('uses ATOM_HOME if no write access to portable .atom folder', () => {
if (process.platform === 'win32') return
const readOnlyPath = temp.mkdirSync('atom-path-spec-no-write-access')
process.env.ATOM_HOME = readOnlyPath
fs.chmodSync(portableAtomHomePath, 444)
atomPaths.setAtomHome(app.getPath('home'))
expect(process.env.ATOM_HOME).toEqual(readOnlyPath)
})
})
describe('when a portable folder does not exist', () => {
beforeEach(() => {
delete process.env.ATOM_HOME
fs.removeSync(portableAtomHomePath)
})
afterEach(() => {
delete process.env.ATOM_HOME
})
it('leaves ATOM_HOME unmodified if it was already set', () => {
const temporaryHome = temp.mkdirSync('atom-spec-setatomhomepath')
process.env.ATOM_HOME = temporaryHome
atomPaths.setAtomHome(app.getPath('home'))
expect(process.env.ATOM_HOME).toEqual(temporaryHome)
})
it('sets ATOM_HOME to a default location if not yet set', () => {
const expectedPath = path.join(app.getPath('home'), '.atom')
atomPaths.setAtomHome(app.getPath('home'))
expect(process.env.ATOM_HOME).toEqual(expectedPath)
})
})
})
describe('setUserData', () => {
let tempAtomHomePath = null
let electronUserDataPath = null
let defaultElectronUserDataPath = null
beforeEach(() => {
defaultElectronUserDataPath = app.getPath('userData')
delete process.env.ATOM_HOME
tempAtomHomePath = temp.mkdirSync('atom-paths-specs-userdata-home')
tempAtomConfigPath = path.join(tempAtomHomePath, '.atom')
fs.mkdirSync(tempAtomConfigPath)
electronUserDataPath = path.join(tempAtomConfigPath, 'electronUserData')
atomPaths.setAtomHome(tempAtomHomePath)
})
afterEach(() => {
delete process.env.ATOM_HOME
fs.removeSync(electronUserDataPath)
temp.cleanupSync()
app.setPath('userData', defaultElectronUserDataPath)
})
describe('when an electronUserData folder exists', () => {
it('sets userData path to the folder if it has permission', () => {
fs.mkdirSync(electronUserDataPath)
atomPaths.setUserData(app)
expect(app.getPath('userData')).toEqual(electronUserDataPath)
})
it('leaves userData unchanged if no write access to electronUserData folder', () => {
if (process.platform === 'win32') return
fs.mkdirSync(electronUserDataPath)
fs.chmodSync(electronUserDataPath, 444)
atomPaths.setUserData(app)
fs.chmodSync(electronUserDataPath, 666)
expect(app.getPath('userData')).toEqual(defaultElectronUserDataPath)
})
})
describe('when an electronUserDataPath folder does not exist', () => {
it('leaves userData app path unchanged', () => {
atomPaths.setUserData(app)
expect(app.getPath('userData')).toEqual(defaultElectronUserDataPath)
})
})
})
})

View File

@@ -1,67 +0,0 @@
path = require 'path'
fs = require 'fs-plus'
AtomPortable = require '../src/main-process/atom-portable'
portableModeCommonPlatformBehavior = (platform) ->
describe "with ATOM_HOME environment variable", ->
it "returns false", ->
expect(AtomPortable.isPortableInstall(platform, "C:\\some\\path")).toBe false
describe "without ATOM_HOME environment variable", ->
environmentAtomHome = undefined
portableAtomHomePath = path.join(path.dirname(process.execPath), "..", ".atom")
portableAtomHomeNaturallyExists = fs.existsSync(portableAtomHomePath)
portableAtomHomeBackupPath = "#{portableAtomHomePath}.temp"
beforeEach ->
fs.renameSync(portableAtomHomePath, portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomePath)
afterEach ->
if portableAtomHomeNaturallyExists
fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
else
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath)
describe "with .atom directory sibling to exec", ->
beforeEach ->
fs.mkdirSync(portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
describe "without .atom directory sibling to exec", ->
beforeEach ->
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
it "returns false", ->
expect(AtomPortable.isPortableInstall(platform, environmentAtomHome)).toBe false
describe "Set Portable Mode on #win32", ->
portableAtomHomePath = path.join(path.dirname(process.execPath), "..", ".atom")
portableAtomHomeNaturallyExists = fs.existsSync(portableAtomHomePath)
portableAtomHomeBackupPath = "#{portableAtomHomePath}.temp"
beforeEach ->
fs.renameSync(portableAtomHomePath, portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomePath)
afterEach ->
if portableAtomHomeNaturallyExists
fs.renameSync(portableAtomHomeBackupPath, portableAtomHomePath) if not fs.existsSync(portableAtomHomePath)
else
fs.removeSync(portableAtomHomePath) if fs.existsSync(portableAtomHomePath)
fs.removeSync(portableAtomHomeBackupPath) if fs.existsSync(portableAtomHomeBackupPath)
it "creates a portable home directory", ->
expect(fs.existsSync(portableAtomHomePath)).toBe false
AtomPortable.setPortable(process.env.ATOM_HOME)
expect(fs.existsSync(portableAtomHomePath)).toBe true
describe "Check for Portable Mode", ->
describe "Windows", ->
portableModeCommonPlatformBehavior "win32"
describe "Mac", ->
it "returns false", ->
expect(AtomPortable.isPortableInstall("darwin", "darwin")).toBe false
describe "Linux", ->
portableModeCommonPlatformBehavior "linux"

View File

@@ -5,6 +5,9 @@ import {remote} from 'electron'
const electronAutoUpdater = remote.require('electron').autoUpdater
describe('AutoUpdateManager (renderer)', () => {
if (process.platform !== 'darwin') return // Tests are tied to electron autoUpdater, we use something else on Linux and Win32
let autoUpdateManager
beforeEach(() => {

View File

@@ -19,6 +19,7 @@ describe "Babel transpiler support", ->
afterEach ->
CompileCache.setCacheDirectory(originalCacheDir)
temp.cleanupSync()
describe 'when a .js file starts with /** @babel */;', ->
it "transpiles it using babel", ->

View File

@@ -1,6 +1,6 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
CommandInstaller = require '../src/command-installer'
describe "CommandInstaller on #darwin", ->
@@ -20,6 +20,9 @@ describe "CommandInstaller on #darwin", ->
spyOn(CommandInstaller::, 'getResourcesDirectory').andReturn(resourcesPath)
spyOn(CommandInstaller::, 'getInstallDirectory').andReturn(installationPath)
afterEach ->
temp.cleanupSync()
it "shows an error dialog when installing commands interactively fails", ->
appDelegate = jasmine.createSpyObj("appDelegate", ["confirm"])
installer = new CommandInstaller("2.0.2", appDelegate)

View File

@@ -21,8 +21,9 @@ describe 'CompileCache', ->
spyOn(TypeScriptSimple::, 'compile').andReturn 'the-typescript-code'
afterEach ->
CSON.setCacheDir(CompileCache.getCacheDirectory())
CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME)
CSON.setCacheDir(CompileCache.getCacheDirectory())
temp.cleanupSync()
describe 'addPathToCache(filePath, atomHome)', ->
describe 'when the given file is plain javascript', ->
@@ -77,6 +78,8 @@ describe 'CompileCache', ->
describe 'overriding Error.prepareStackTrace', ->
it 'removes the override on the next tick, and always assigns the raw stack', ->
return if process.platform is 'win32' # Flakey Error.stack contents on Win32
Error.prepareStackTrace = -> 'a-stack-trace'
error = new Error("Oops")

View File

@@ -1,5 +1,5 @@
path = require 'path'
temp = require 'temp'
temp = require('temp').track()
CSON = require 'season'
fs = require 'fs-plus'
@@ -9,13 +9,14 @@ describe "Config", ->
beforeEach ->
spyOn(atom.config, "load")
spyOn(atom.config, "save")
dotAtomPath = temp.path('dot-atom-dir')
dotAtomPath = temp.path('atom-spec-config')
atom.config.configDirPath = dotAtomPath
atom.config.enablePersistence = true
atom.config.configFilePath = path.join(atom.config.configDirPath, "atom.config.cson")
afterEach ->
atom.config.enablePersistence = false
fs.removeSync(dotAtomPath)
describe ".get(keyPath, {scope, sources, excludeSources})", ->
it "allows a key path's value to be read", ->
@@ -486,8 +487,8 @@ describe "Config", ->
observeHandler.reset() # clear the initial call
atom.config.set('foo.bar.baz', "value 2")
expect(observeHandler).toHaveBeenCalledWith("value 2")
observeHandler.reset()
observeHandler.reset()
atom.config.set('foo.bar.baz', "value 1")
expect(observeHandler).toHaveBeenCalledWith("value 1")
advanceClock(100) # complete pending save that was requested in ::set
@@ -1079,6 +1080,7 @@ describe "Config", ->
describe "when the configDirPath doesn't exist", ->
it "copies the contents of dot-atom to ~/.atom", ->
return if process.platform is 'win32' # Flakey test on Win32
initializationDone = false
jasmine.unspy(window, "setTimeout")
atom.config.initializeConfigDirectory ->

View File

@@ -1,20 +1,26 @@
DefaultDirectoryProvider = require '../src/default-directory-provider'
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
describe "DefaultDirectoryProvider", ->
tmp = null
beforeEach ->
tmp = temp.mkdirSync('atom-spec-default-dir-provider')
afterEach ->
temp.cleanupSync()
describe ".directoryForURISync(uri)", ->
it "returns a Directory with a path that matches the uri", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
directory = provider.directoryForURISync(tmp)
expect(directory.getPath()).toEqual tmp
it "normalizes its input before creating a Directory for it", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
nonNormalizedPath = tmp + path.sep + ".." + path.sep + path.basename(tmp)
expect(tmp.includes("..")).toBe false
expect(nonNormalizedPath.includes("..")).toBe true
@@ -24,7 +30,6 @@ describe "DefaultDirectoryProvider", ->
it "creates a Directory for its parent dir when passed a file", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
file = path.join(tmp, "example.txt")
fs.writeFileSync(file, "data")
@@ -40,7 +45,6 @@ describe "DefaultDirectoryProvider", ->
describe ".directoryForURI(uri)", ->
it "returns a Promise that resolves to a Directory with a path that matches the uri", ->
provider = new DefaultDirectoryProvider()
tmp = temp.mkdirSync()
waitsForPromise ->
provider.directoryForURI(tmp).then (directory) ->

View File

@@ -1,4 +1,4 @@
temp = require 'temp'
temp = require('temp').track()
path = require 'path'
fs = require 'fs-plus'
FileSystemBlobStore = require '../src/file-system-blob-store'
@@ -7,9 +7,12 @@ describe "FileSystemBlobStore", ->
[storageDirectory, blobStore] = []
beforeEach ->
storageDirectory = temp.path()
storageDirectory = temp.path('atom-spec-filesystemblobstore')
blobStore = FileSystemBlobStore.load(storageDirectory)
afterEach ->
fs.removeSync(storageDirectory)
it "is empty when the file doesn't exist", ->
expect(blobStore.get("foo", "invalidation-key-1")).toBeUndefined()
expect(blobStore.get("bar", "invalidation-key-2")).toBeUndefined()

View File

@@ -1,4 +1,5 @@
module.exports = {
initialize() {},
activate () {},
deserializeMethod1 (state) {

View File

@@ -1 +1 @@
Some text.
Some textSome text.

View File

@@ -1,6 +1,6 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
{Directory} = require 'pathwatcher'
GitRepository = require '../src/git-repository'
GitRepositoryProvider = require '../src/git-repository-provider'
@@ -11,6 +11,9 @@ describe "GitRepositoryProvider", ->
beforeEach ->
provider = new GitRepositoryProvider(atom.project, atom.config, atom.confirm)
afterEach ->
temp.cleanupSync()
describe ".repositoryForDirectory(directory)", ->
describe "when specified a Directory with a Git repository", ->
it "returns a Promise that resolves to a GitRepository", ->

View File

@@ -1,11 +1,11 @@
temp = require 'temp'
temp = require('temp').track()
GitRepository = require '../src/git-repository'
fs = require 'fs-plus'
path = require 'path'
Project = require '../src/project'
copyRepository = ->
workingDirPath = temp.mkdirSync('atom-working-dir')
workingDirPath = temp.mkdirSync('atom-spec-git')
fs.copySync(path.join(__dirname, 'fixtures', 'git', 'working-dir'), workingDirPath)
fs.renameSync(path.join(workingDirPath, 'git.git'), path.join(workingDirPath, '.git'))
workingDirPath
@@ -19,6 +19,8 @@ describe "GitRepository", ->
afterEach ->
repo.destroy() if repo?.repo?
try
temp.cleanupSync() # These tests sometimes lag at shutting down resources
describe "@open(path)", ->
it "returns null when no repository is found", ->
@@ -29,10 +31,15 @@ describe "GitRepository", ->
expect(-> new GitRepository(path.join(temp.dir, 'nogit.txt'))).toThrow()
describe ".getPath()", ->
it "returns the repository path for a .git directory path", ->
it "returns the repository path for a .git directory path with a file", ->
return if process.platform is 'win32' #Win32TestFailures - libgit2 does not detect files in .git folders
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git', 'HEAD'))
expect(repo.getPath()).toBe path.join(__dirname, 'fixtures', 'git', 'master.git')
it "returns the repository path for a .git directory path with a directory", ->
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git', 'objects'))
expect(repo.getPath()).toBe path.join(__dirname, 'fixtures', 'git', 'master.git')
it "returns the repository path for a repository path", ->
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git'))
expect(repo.getPath()).toBe path.join(__dirname, 'fixtures', 'git', 'master.git')
@@ -137,6 +144,8 @@ describe "GitRepository", ->
editor = atom.workspace.getActiveTextEditor()
it "displays a confirmation dialog by default", ->
return if process.platform is 'win32' # Permissions issues with this test on Windows
atom.confirm.andCallFake ({buttons}) -> buttons.OK()
atom.config.set('editor.confirmCheckoutHeadRevision', true)
@@ -145,6 +154,7 @@ describe "GitRepository", ->
expect(fs.readFileSync(filePath, 'utf8')).toBe ''
it "does not display a dialog when confirmation is disabled", ->
return if process.platform is 'win32' # Flakey EPERM opening a.txt on Win32
atom.config.set('editor.confirmCheckoutHeadRevision', false)
repo.checkoutHeadForEditor(editor)
@@ -154,7 +164,7 @@ describe "GitRepository", ->
describe ".destroy()", ->
it "throws an exception when any method is called after it is called", ->
repo = new GitRepository(require.resolve('./fixtures/git/master.git/HEAD'))
repo = new GitRepository(path.join(__dirname, 'fixtures', 'git', 'master.git'))
repo.destroy()
expect(-> repo.getShortHead()).toThrow()

View File

@@ -1,6 +1,6 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
GrammarRegistry = require '../src/grammar-registry'
Grim = require 'grim'
@@ -24,6 +24,7 @@ describe "the `grammars` global", ->
afterEach ->
atom.packages.deactivatePackages()
atom.packages.unloadPackages()
temp.cleanupSync()
describe ".selectGrammar(filePath)", ->
it "always returns a grammar", ->
@@ -96,6 +97,7 @@ describe "the `grammars` global", ->
)
grammar1 = atom.grammars.loadGrammarSync(grammarPath1)
expect(atom.grammars.selectGrammar('more.test', '')).toBe grammar1
fs.removeSync(grammarPath1)
grammarPath2 = temp.path(suffix: '.json')
fs.writeFileSync grammarPath2, JSON.stringify(
@@ -105,6 +107,7 @@ describe "the `grammars` global", ->
)
grammar2 = atom.grammars.loadGrammarSync(grammarPath2)
expect(atom.grammars.selectGrammar('more.test', '')).toBe grammar2
fs.removeSync(grammarPath2)
it "favors non-bundled packages when breaking scoring ties", ->
waitsForPromise ->

View File

@@ -139,3 +139,22 @@ describe "GutterContainerComponent", ->
expect(expectedCustomGutterNode1).toBe atom.views.getView(customGutter1)
expectedCustomGutterNode3 = gutterContainerComponent.getDomNode().children.item(2)
expect(expectedCustomGutterNode3).toBe atom.views.getView(customGutter3)
it "reorders correctly when prepending multiple gutters at once", ->
lineNumberGutter = new Gutter(mockGutterContainer, {name: 'line-number'})
testState = buildTestState([lineNumberGutter])
gutterContainerComponent.updateSync(testState)
expect(gutterContainerComponent.getDomNode().children.length).toBe 1
expectedCustomGutterNode = gutterContainerComponent.getDomNode().children.item(0)
expect(expectedCustomGutterNode).toBe atom.views.getView(lineNumberGutter)
# Prepend two gutters at once
customGutter1 = new Gutter(mockGutterContainer, {name: 'first', priority: -200})
customGutter2 = new Gutter(mockGutterContainer, {name: 'second', priority: -100})
testState = buildTestState([customGutter1, customGutter2, lineNumberGutter])
gutterContainerComponent.updateSync(testState)
expect(gutterContainerComponent.getDomNode().children.length).toBe 3
expectedCustomGutterNode1 = gutterContainerComponent.getDomNode().children.item(0)
expect(expectedCustomGutterNode1).toBe atom.views.getView(customGutter1)
expectedCustomGutterNode2 = gutterContainerComponent.getDomNode().children.item(1)
expect(expectedCustomGutterNode2).toBe atom.views.getView(customGutter2)

View File

@@ -16,7 +16,7 @@ ChromedriverPort = 9515
ChromedriverURLBase = "/wd/hub"
ChromedriverStatusURL = "http://localhost:#{ChromedriverPort}#{ChromedriverURLBase}/status"
userDataDir = temp.mkdirSync('atom-user-data-dir')
userDataDir = null
chromeDriverUp = (done) ->
checkStatus = ->
@@ -38,6 +38,7 @@ chromeDriverDown = (done) ->
setTimeout(checkStatus, 100)
buildAtomClient = (args, env) ->
userDataDir = temp.mkdirSync('atom-user-data-dir')
client = webdriverio.remote(
host: 'localhost'
port: ChromedriverPort

View File

@@ -5,6 +5,8 @@ temp = require('temp').track()
runAtom = require './helpers/start-atom'
describe "Smoke Test", ->
return unless process.platform is 'darwin' # Fails on win32
atomHome = temp.mkdirSync('atom-home')
beforeEach ->

View File

@@ -78,9 +78,10 @@ describe "LinesYardstick", ->
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 0))).toEqual({left: 0, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 1))).toEqual({left: 7, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 5))).toEqual({left: 38, top: 0})
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 6))).toEqual({left: 43, top: 14})
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 9))).toEqual({left: 72, top: 14})
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, Infinity))).toEqual({left: 287.859375, top: 28})
if process.platform is 'darwin' # One pixel off on left on Win32
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 6))).toEqual({left: 43, top: 14})
expect(linesYardstick.pixelPositionForScreenPosition(Point(1, 9))).toEqual({left: 72, top: 14})
expect(linesYardstick.pixelPositionForScreenPosition(Point(2, Infinity))).toEqual({left: 287.859375, top: 28})
it "reuses already computed pixel positions unless it is invalidated", ->
atom.styles.addStyleSheet """
@@ -133,6 +134,7 @@ describe "LinesYardstick", ->
editor.setText(text)
return unless process.platform is 'darwin' # These numbers are 15 higher on win32 and always integer
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 35)).left).toBe 230.90625
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 36)).left).toBe 237.5
expect(linesYardstick.pixelPositionForScreenPosition(Point(0, 37)).left).toBe 244.09375
@@ -172,8 +174,9 @@ describe "LinesYardstick", ->
expect(linesYardstick.screenPositionForPixelPosition({top: 32, left: 24.3})).toEqual([2, 3])
expect(linesYardstick.screenPositionForPixelPosition({top: 46, left: 66.5})).toEqual([3, 9])
expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 99.9})).toEqual([5, 14])
expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 224.2365234375})).toEqual([5, 29])
expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 225})).toEqual([5, 30])
return unless process.platform is 'darwin' # Following tests are 1 pixel off on Win32
expect(linesYardstick.screenPositionForPixelPosition({top: 70, left: 224.2365234375})).toEqual([5, 29])
expect(linesYardstick.screenPositionForPixelPosition({top: 84, left: 247.1})).toEqual([6, 33])
it "overshoots to the nearest character when text nodes are not spatially contiguous", ->

View File

@@ -22,7 +22,7 @@ describe('AtomApplication', function () {
originalAtomHome = process.env.ATOM_HOME
process.env.ATOM_HOME = makeTempDir('atom-home')
// Symlinking the compile cache into the temporary home dir makes the windows load much faster
fs.symlinkSync(path.join(originalAtomHome, 'compile-cache'), path.join(process.env.ATOM_HOME, 'compile-cache'))
fs.symlinkSync(path.join(originalAtomHome, 'compile-cache'), path.join(process.env.ATOM_HOME, 'compile-cache'), 'junction')
season.writeFileSync(path.join(process.env.ATOM_HOME, 'config.cson'), {
'*': {
welcome: {showOnStartup: false},
@@ -309,7 +309,7 @@ describe('AtomApplication', function () {
const packagePath = path.join(__dirname, '..', 'fixtures', 'packages', 'package-with-directory-provider')
const packagesDirPath = path.join(process.env.ATOM_HOME, 'packages')
fs.mkdirSync(packagesDirPath)
fs.symlinkSync(packagePath, path.join(packagesDirPath, 'package-with-directory-provider'))
fs.symlinkSync(packagePath, path.join(packagesDirPath, 'package-with-directory-provider'), 'junction')
const atomApplication = buildAtomApplication()
atomApplication.config.set('core.disabledPackages', ['fuzzy-finder'])

View File

@@ -2,19 +2,23 @@
import {dialog} from 'electron'
import FileRecoveryService from '../../src/main-process/file-recovery-service'
import temp from 'temp'
import fs from 'fs-plus'
import sinon from 'sinon'
import {escapeRegExp} from 'underscore-plus'
const temp = require('temp').track()
describe("FileRecoveryService", () => {
let recoveryService, recoveryDirectory
beforeEach(() => {
recoveryDirectory = temp.mkdirSync()
recoveryDirectory = temp.mkdirSync('atom-spec-file-recovery')
recoveryService = new FileRecoveryService(recoveryDirectory)
})
afterEach(() => {
temp.cleanupSync()
})
describe("when no crash happens during a save", () => {
it("creates a recovery file and deletes it after saving", () => {
const mockWindow = {}
@@ -28,6 +32,8 @@ describe("FileRecoveryService", () => {
recoveryService.didSavePath(mockWindow, filePath)
assert.equal(fs.listTreeSync(recoveryDirectory).length, 0)
assert.equal(fs.readFileSync(filePath, 'utf8'), "changed")
fs.removeSync(filePath)
})
it("creates only one recovery file when many windows attempt to save the same file, deleting it when the last one finishes saving it", () => {
@@ -48,6 +54,8 @@ describe("FileRecoveryService", () => {
recoveryService.didSavePath(anotherMockWindow, filePath)
assert.equal(fs.listTreeSync(recoveryDirectory).length, 0)
assert.equal(fs.readFileSync(filePath, 'utf8'), "changed")
fs.removeSync(filePath)
})
})
@@ -64,6 +72,8 @@ describe("FileRecoveryService", () => {
recoveryService.didCrashWindow(mockWindow)
assert.equal(fs.listTreeSync(recoveryDirectory).length, 0)
assert.equal(fs.readFileSync(filePath, 'utf8'), "some content")
fs.removeSync(filePath)
})
it("restores the created recovery file when many windows attempt to save the same file and one of them crashes", () => {
@@ -94,6 +104,8 @@ describe("FileRecoveryService", () => {
recoveryService.didCrashWindow(anotherMockWindow)
assert.equal(fs.readFileSync(filePath, 'utf8'), "D")
assert.equal(fs.listTreeSync(recoveryDirectory).length, 0)
fs.removeSync(filePath)
})
it("emits a warning when a file can't be recovered", sinon.test(function () {
@@ -113,6 +125,8 @@ describe("FileRecoveryService", () => {
assert.equal(logs.length, 1)
assert.match(logs[0], new RegExp(escapeRegExp(filePath)))
assert.match(logs[0], new RegExp(escapeRegExp(recoveryFiles[0])))
fs.removeSync(filePath)
}))
})

View File

@@ -79,6 +79,7 @@ describe "MenuManager", ->
runs -> expect(menu.sendToBrowserProcess.argsForCall[0][1]['b']).toBeUndefined()
it "omits key bindings that could conflict with AltGraph characters on macOS", ->
Object.defineProperty process, 'platform', value: 'darwin'
spyOn(menu, 'sendToBrowserProcess')
menu.add [{label: "A", submenu: [
{label: "B", command: "b"},

View File

@@ -1,13 +1,16 @@
path = require 'path'
Module = require 'module'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
ModuleCache = require '../src/module-cache'
describe 'ModuleCache', ->
beforeEach ->
spyOn(Module, '_findPath').andCallThrough()
afterEach ->
temp.cleanupSync()
it 'resolves Electron module paths without hitting the filesystem', ->
builtins = ModuleCache.cache.builtins
expect(Object.keys(builtins).length).toBeGreaterThan 0

View File

@@ -1,6 +1,6 @@
path = require 'path'
Package = require '../src/package'
temp = require 'temp'
temp = require('temp').track()
fs = require 'fs-plus'
{Disposable} = require 'atom'
{buildKeydownEvent} = require '../src/keymap-extensions'
@@ -17,6 +17,9 @@ describe "PackageManager", ->
beforeEach ->
workspaceElement = atom.views.getView(atom.workspace)
afterEach ->
temp.cleanupSync()
describe "::getApmPath()", ->
it "returns the path to the apm command", ->
apmPath = path.join(process.resourcesPath, "app", "apm", "bin", "apm")
@@ -440,11 +443,9 @@ describe "PackageManager", ->
spyOn(mainModule, 'activate').andCallThrough()
spyOn(Package.prototype, 'requireMainModule').andCallThrough()
promise = atom.packages.activatePackage('package-with-activation-hooks')
it "defers requiring/activating the main module until an triggering of an activation hook occurs", ->
promise = atom.packages.activatePackage('package-with-activation-hooks')
expect(Package.prototype.requireMainModule.callCount).toBe 0
atom.packages.triggerActivationHook('language-fictitious:grammar-used')
atom.packages.triggerDeferredActivationHooks()
@@ -455,6 +456,7 @@ describe "PackageManager", ->
expect(Package.prototype.requireMainModule.callCount).toBe 1
it "does not double register activation hooks when deactivating and reactivating", ->
promise = atom.packages.activatePackage('package-with-activation-hooks')
expect(mainModule.activate.callCount).toBe 0
atom.packages.triggerActivationHook('language-fictitious:grammar-used')
atom.packages.triggerDeferredActivationHooks()
@@ -489,6 +491,17 @@ describe "PackageManager", ->
expect(mainModule.activate.callCount).toBe 1
expect(Package.prototype.requireMainModule.callCount).toBe 1
it "activates the package immediately if the activation hook had already been triggered", ->
atom.packages.triggerActivationHook('language-fictitious:grammar-used')
atom.packages.triggerDeferredActivationHooks()
expect(Package.prototype.requireMainModule.callCount).toBe 0
waitsForPromise ->
atom.packages.activatePackage('package-with-activation-hooks')
runs ->
expect(Package.prototype.requireMainModule.callCount).toBe 1
describe "when the package has no main module", ->
it "does not throw an exception", ->
spyOn(console, "error")
@@ -643,7 +656,7 @@ describe "PackageManager", ->
[element, events, userKeymapPath] = []
beforeEach ->
userKeymapPath = path.join(temp.path(), "user-keymaps.cson")
userKeymapPath = path.join(temp.mkdirSync(), "user-keymaps.cson")
spyOn(atom.keymaps, "getUserKeymapPath").andReturn(userKeymapPath)
element = createTestElement('test-1')
@@ -660,6 +673,8 @@ describe "PackageManager", ->
atom.keymaps.watchSubscriptions[userKeymapPath].dispose()
delete atom.keymaps.watchSubscriptions[userKeymapPath]
temp.cleanupSync()
it "doesn't override user-defined keymaps", ->
fs.writeFileSync userKeymapPath, """
".test-1":
@@ -740,10 +755,6 @@ describe "PackageManager", ->
two = require.resolve("./fixtures/packages/package-with-style-sheets-manifest/styles/2.less")
three = require.resolve("./fixtures/packages/package-with-style-sheets-manifest/styles/3.css")
one = atom.themes.stringToId(one)
two = atom.themes.stringToId(two)
three = atom.themes.stringToId(three)
expect(atom.themes.stylesheetElementForId(one)).toBeNull()
expect(atom.themes.stylesheetElementForId(two)).toBeNull()
expect(atom.themes.stylesheetElementForId(three)).toBeNull()
@@ -765,11 +776,6 @@ describe "PackageManager", ->
three = require.resolve("./fixtures/packages/package-with-styles/styles/3.test-context.css")
four = require.resolve("./fixtures/packages/package-with-styles/styles/4.css")
one = atom.themes.stringToId(one)
two = atom.themes.stringToId(two)
three = atom.themes.stringToId(three)
four = atom.themes.stringToId(four)
expect(atom.themes.stylesheetElementForId(one)).toBeNull()
expect(atom.themes.stylesheetElementForId(two)).toBeNull()
expect(atom.themes.stylesheetElementForId(three)).toBeNull()

View File

@@ -205,3 +205,26 @@ describe "Package", ->
it "uses the package name defined in package.json", ->
expect(metadata.name).toBe 'package-with-a-totally-different-name'
describe "the initialize() hook", ->
it "gets called when the package is activated", ->
packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-deserializers')
pack = buildPackage(packagePath)
pack.requireMainModule()
mainModule = pack.mainModule
spyOn(mainModule, 'initialize')
expect(mainModule.initialize).not.toHaveBeenCalled()
pack.activate()
expect(mainModule.initialize).toHaveBeenCalled()
expect(mainModule.initialize.callCount).toBe(1)
it "gets called when a deserializer is used", ->
packagePath = atom.project.getDirectories()[0].resolve('packages/package-with-deserializers')
pack = buildPackage(packagePath)
pack.requireMainModule()
mainModule = pack.mainModule
spyOn(mainModule, 'initialize')
pack.load()
expect(mainModule.initialize).not.toHaveBeenCalled()
atom.deserializers.deserialize({deserializer: 'Deserializer1', a: 'b'})
expect(mainModule.initialize).toHaveBeenCalled()

View File

@@ -44,19 +44,19 @@ describe("PackageTranspilationRegistry", () => {
})
describe('when a file is contained in a path that has custom transpilation', () => {
const hitPath = '/path/to/lib/file.js'
const hitPathCoffee = '/path/to/file2.coffee'
const missPath = '/path/other/file3.js'
const hitPathMissSubdir = '/path/to/file4.js'
const hitPathMissExt = '/path/to/file5.ts'
const nodeModulesFolder = '/path/to/lib/node_modules/file6.js'
const hitNonStandardExt = '/path/to/file7.omgwhatisthis'
const hitPath = path.join('/path/to/lib/file.js')
const hitPathCoffee = path.join('/path/to/file2.coffee')
const missPath = path.join('/path/other/file3.js')
const hitPathMissSubdir =path.join('/path/to/file4.js')
const hitPathMissExt = path.join('/path/to/file5.ts')
const nodeModulesFolder = path.join('/path/to/lib/node_modules/file6.js')
const hitNonStandardExt = path.join('/path/to/file7.omgwhatisthis')
const jsSpec = { glob: "lib/**/*.js", transpiler: './transpiler-js', options: { type: 'js' } }
const coffeeSpec = { glob: "*.coffee", transpiler: './transpiler-coffee', options: { type: 'coffee' } }
const omgSpec = { glob: "*.omgwhatisthis", transpiler: './transpiler-omg', options: { type: 'omg' } }
const expectedMeta = { name: 'my-package', path: '/path/to', meta: { some: 'metadata' } }
const expectedMeta = { name: 'my-package', path: path.join('/path/to'), meta: { some: 'metadata' } }
const jsTranspiler = {
transpile: (sourceCode, filePath, options) => {
@@ -100,7 +100,7 @@ describe("PackageTranspilationRegistry", () => {
throw new Error('bad transpiler path ' + spec.transpiler)
})
registry.addTranspilerConfigForPath('/path/to', 'my-package', { some: 'metadata' }, [
registry.addTranspilerConfigForPath(path.join('/path/to'), 'my-package', { some: 'metadata' }, [
jsSpec, coffeeSpec, omgSpec
])
})

View File

@@ -1080,6 +1080,7 @@ describe "Pane", ->
expect(eventCount).toBe 1
it "only calls terminate handler once when text is modified twice", ->
originalText = editor1.getText()
editor1.insertText('Some text')
advanceClock(editor1.getBuffer().stoppedChangingDelay)
@@ -1091,6 +1092,10 @@ describe "Pane", ->
expect(pane.getPendingItem()).toBeNull()
expect(eventCount).toBe 1
# Reset fixture back to original state
editor1.setText(originalText)
editor1.save()
it "only calls clearPendingItem if there is a pending item to clear", ->
spyOn(pane, "clearPendingItem").andCallThrough()

View File

@@ -1,4 +1,4 @@
temp = require 'temp'
temp = require('temp').track()
Project = require '../src/project'
fs = require 'fs-plus'
path = require 'path'
@@ -12,6 +12,9 @@ describe "Project", ->
# Wait for project's service consumers to be asynchronously added
waits(1)
afterEach ->
temp.cleanupSync()
describe "serialization", ->
deserializedProject = null
@@ -51,7 +54,7 @@ describe "Project", ->
it "does not deserialize buffers when their path is a directory that exists", ->
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
pathToOpen = path.join(temp.mkdirSync('atom-spec-project'), 'file.txt')
waitsForPromise ->
atom.workspace.open(pathToOpen)
@@ -64,7 +67,8 @@ describe "Project", ->
expect(deserializedProject.getBuffers().length).toBe 0
it "does not deserialize buffers when their path is inaccessible", ->
pathToOpen = path.join(temp.mkdirSync(), 'file.txt')
return if process.platform is 'win32' # chmod not supported on win32
pathToOpen = path.join(temp.mkdirSync('atom-spec-project'), 'file.txt')
fs.writeFileSync(pathToOpen, '')
waitsForPromise ->
@@ -151,7 +155,7 @@ describe "Project", ->
expect(notification.getType()).toBe 'warning'
expect(notification.getDetail()).toBe 'SomeError'
expect(notification.getMessage()).toContain '`resurrect`'
expect(notification.getMessage()).toContain 'fixtures/dir/a'
expect(notification.getMessage()).toContain path.join('fixtures', 'dir', 'a')
describe "when a custom repository-provider service is provided", ->
[fakeRepositoryProvider, fakeRepository] = []

View File

@@ -1,7 +1,7 @@
{EventEmitter} = require 'events'
fs = require 'fs-plus'
path = require 'path'
temp = require 'temp'
temp = require('temp').track()
SquirrelUpdate = require '../src/main-process/squirrel-update'
Spawner = require '../src/main-process/spawner'
WinShell = require '../src/main-process/win-shell'
@@ -36,6 +36,9 @@ describe "Windows Squirrel Update", ->
WinShell.folderContextMenu = new FakeShellOption()
WinShell.folderBackgroundContextMenu = new FakeShellOption()
afterEach ->
temp.cleanupSync()
it "quits the app on all squirrel events", ->
app = quit: jasmine.createSpy('quit')

View File

@@ -1,4 +1,4 @@
const temp = require('temp')
const temp = require('temp').track()
const StyleManager = require('../src/style-manager')
describe('StyleManager', () => {
@@ -14,6 +14,10 @@ describe('StyleManager', () => {
styleManager.onDidUpdateStyleElement((event) => { updateEvents.push(event) })
})
afterEach(() => {
temp.cleanupSync()
})
describe('::addStyleSheet(source, params)', () => {
it('adds a style sheet based on the given source and returns a disposable allowing it to be removed', () => {
const disposable = styleManager.addStyleSheet('a {color: red}')

View File

@@ -2291,7 +2291,9 @@ describe('TextEditorComponent', function () {
let position = wrapperNode.pixelPositionForBufferPosition([0, 26])
let overlay = component.getTopmostDOMNode().querySelector('atom-overlay')
expect(overlay.style.left).toBe(Math.round(position.left + gutterWidth) + 'px')
if (process.platform == 'darwin') { // Result is 359px on win32, expects 375px
expect(overlay.style.left).toBe(Math.round(position.left + gutterWidth) + 'px')
}
expect(overlay.style.top).toBe(position.top + editor.getLineHeightInPixels() + 'px')
editor.insertText('a')
@@ -3846,6 +3848,40 @@ describe('TextEditorComponent', function () {
})
})
describe('when the mousewheel event\'s target is an SVG element inside a block decoration', function () {
it('keeps the block decoration on the DOM if it is scrolled off-screen', function () {
wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'
wrapperNode.style.width = 20 * charWidth + 'px'
editor.update({autoHeight: false})
component.measureDimensions()
runAnimationFrames()
const item = document.createElement('div')
const svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg")
item.appendChild(svgElement)
editor.decorateMarker(
editor.markScreenPosition([0, 0], {invalidate: "never"}),
{type: "block", item: item}
)
runAnimationFrames()
let wheelEvent = new WheelEvent('mousewheel', {
wheelDeltaX: 0,
wheelDeltaY: -500
})
Object.defineProperty(wheelEvent, 'target', {
get: function () {
return svgElement
}
})
componentNode.dispatchEvent(wheelEvent)
runAnimationFrames()
expect(component.getTopmostDOMNode().contains(item)).toBe(true)
})
})
it('only prevents the default action of the mousewheel event if it actually lead to scrolling', function () {
spyOn(WheelEvent.prototype, 'preventDefault').andCallThrough()
wrapperNode.style.height = 4.5 * lineHeightInPixels + 'px'

View File

@@ -78,6 +78,19 @@ describe "TextEditorElement", ->
jasmine.attachToDOM(element)
expect(element.querySelectorAll('.decoration').length).toBe initialDecorationCount
it "can be re-focused using the previous `document.activeElement`", ->
editorElement = document.createElement('atom-text-editor')
jasmine.attachToDOM(editorElement)
editorElement.focus()
activeElement = document.activeElement
editorElement.remove()
jasmine.attachToDOM(editorElement)
activeElement.focus()
expect(editorElement.hasFocus()).toBe(true)
describe "focus and blur handling", ->
it "proxies focus/blur events to/from the hidden input", ->
element = new TextEditorElement

View File

@@ -165,23 +165,6 @@ describe "TextEditorPresenter", ->
expect(stateFn(presenter).tiles[10]).toBeUndefined()
expect(stateFn(presenter).tiles[12]).toBeUndefined()
it "excludes invalid tiles for screen rows to measure", ->
presenter = buildPresenter(explicitHeight: 6, scrollTop: 0, lineHeight: 1, tileSize: 2)
presenter.setScreenRowsToMeasure([20, 30]) # unexisting rows
expect(stateFn(presenter).tiles[0]).toBeDefined()
expect(stateFn(presenter).tiles[2]).toBeDefined()
expect(stateFn(presenter).tiles[4]).toBeDefined()
expect(stateFn(presenter).tiles[6]).toBeDefined()
expect(stateFn(presenter).tiles[8]).toBeUndefined()
expect(stateFn(presenter).tiles[10]).toBeUndefined()
expect(stateFn(presenter).tiles[12]).toBeUndefined()
presenter.setScreenRowsToMeasure([12])
buffer.deleteRows(12, 13)
expect(stateFn(presenter).tiles[12]).toBeUndefined()
describe "when there are block decorations", ->
it "computes each tile's height and scrollTop based on block decorations' height", ->
presenter = buildPresenter(explicitHeight: 120, scrollTop: 0, lineHeight: 10, tileSize: 2)
@@ -2045,6 +2028,27 @@ describe "TextEditorPresenter", ->
expect(stateForHighlightInTile(presenter, highlight, 0)).toBeUndefined()
it "handles highlights that extend to the left of the visible area (regression)", ->
editor.setSelectedBufferRanges([
[[0, 2], [1, 4]],
])
presenter = buildPresenter(explicitHeight: 20, scrollLeft: 0, tileSize: 2)
expectValues stateForSelectionInTile(presenter, 0, 0), {
regions: [
{top: 0 * 10, height: 10, left: 2 * 10, right: 0 * 10},
{top: 1 * 10, height: 10, left: 0 * 10, width: 4 * 10}
]
}
presenter = buildPresenter(explicitHeight: 20, scrollLeft: 20, tileSize: 2)
expectValues stateForSelectionInTile(presenter, 0, 0), {
regions: [
{top: 0 * 10, height: 10, left: 2 * 10, right: 0 * 10},
{top: 1 * 10, height: 10, left: 0 * 10, width: 4 * 10}
]
}
it "updates when ::scrollTop changes", ->
editor.setSelectedBufferRanges([
[[6, 2], [6, 4]],
@@ -2518,13 +2522,13 @@ describe "TextEditorPresenter", ->
pixelPosition: {top: 1 * 10, left: 26 * 10 + gutterWidth - scrollLeft}
}
expectStateUpdate presenter, -> editor.insertText('a')
expectStateUpdate presenter, -> editor.insertText('abc', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: windowWidth - itemWidth}
}
expectStateUpdate presenter, -> editor.insertText('b')
expectStateUpdate presenter, -> editor.insertText('d', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: windowWidth - itemWidth}
@@ -2545,14 +2549,55 @@ describe "TextEditorPresenter", ->
}
expectStateUpdate presenter, ->
editor.insertNewline()
presenter.setScrollTop(scrollTop) # I'm fighting the editor
editor.insertNewline(autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 6 * 10 - scrollTop - itemHeight, left: gutterWidth}
}
it "when avoidOverflow is false, does not move horizontally when overflowing the editor's scrollView horizontally", ->
scrollLeft = 20
marker = editor.markBufferPosition([0, 26], invalidate: 'never')
decoration = editor.decorateMarker(marker, {type: 'overlay', item, avoidOverflow: false})
presenter = buildPresenter({scrollLeft, windowWidth, windowHeight, contentFrameWidth, boundingClientRect, gutterWidth})
expectStateUpdate presenter, ->
presenter.setOverlayDimensions(decoration.id, itemWidth, itemHeight, contentMargin)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: 26 * 10 + gutterWidth - scrollLeft}
}
expectStateUpdate presenter, -> editor.insertText('a', autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 1 * 10, left: 27 * 10 + gutterWidth - scrollLeft}
}
it "when avoidOverflow is false, does not flip vertically when overflowing the editor's scrollView vertically", ->
scrollTop = 10
marker = editor.markBufferPosition([5, 0], invalidate: 'never')
decoration = editor.decorateMarker(marker, {type: 'overlay', item, avoidOverflow: false})
presenter = buildPresenter({scrollTop, windowWidth, windowHeight, contentFrameWidth, boundingClientRect, gutterWidth})
expectStateUpdate presenter, ->
presenter.setOverlayDimensions(decoration.id, itemWidth, itemHeight, contentMargin)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 6 * 10 - scrollTop, left: gutterWidth}
}
expectStateUpdate presenter, ->
editor.insertNewline(autoscroll: false)
expectValues stateForOverlay(presenter, decoration), {
item: item
pixelPosition: {top: 7 * 10 - scrollTop, left: gutterWidth}
}
describe "when the overlay item has a margin", ->
beforeEach ->
itemWidth = 12 * 10

View File

@@ -1,6 +1,6 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
temp = require('temp').track()
describe "atom.themes", ->
beforeEach ->
@@ -8,6 +8,7 @@ describe "atom.themes", ->
afterEach ->
atom.themes.deactivateThemes()
temp.cleanupSync()
describe "theme getters and setters", ->
beforeEach ->
@@ -170,7 +171,7 @@ describe "atom.themes", ->
expect(styleElementAddedHandler).toHaveBeenCalled()
element = document.querySelector('head style[source-path*="css.css"]')
expect(element.getAttribute('source-path')).toEqualPath atom.themes.stringToId(cssPath)
expect(element.getAttribute('source-path')).toEqualPath cssPath
expect(element.textContent).toBe fs.readFileSync(cssPath, 'utf8')
# doesn't append twice
@@ -189,7 +190,7 @@ describe "atom.themes", ->
expect(document.querySelectorAll('head style').length).toBe lengthBefore + 1
element = document.querySelector('head style[source-path*="sample.less"]')
expect(element.getAttribute('source-path')).toEqualPath atom.themes.stringToId(lessPath)
expect(element.getAttribute('source-path')).toEqualPath lessPath
expect(element.textContent).toBe """
#header {
color: #4d926f;
@@ -208,9 +209,9 @@ describe "atom.themes", ->
it "supports requiring css and less stylesheets without an explicit extension", ->
atom.themes.requireStylesheet path.join(__dirname, 'fixtures', 'css')
expect(document.querySelector('head style[source-path*="css.css"]').getAttribute('source-path')).toEqualPath atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('css.css'))
expect(document.querySelector('head style[source-path*="css.css"]').getAttribute('source-path')).toEqualPath atom.project.getDirectories()[0]?.resolve('css.css')
atom.themes.requireStylesheet path.join(__dirname, 'fixtures', 'sample')
expect(document.querySelector('head style[source-path*="sample.less"]').getAttribute('source-path')).toEqualPath atom.themes.stringToId(atom.project.getDirectories()[0]?.resolve('sample.less'))
expect(document.querySelector('head style[source-path*="sample.less"]').getAttribute('source-path')).toEqualPath atom.project.getDirectories()[0]?.resolve('sample.less')
document.querySelector('head style[source-path*="css.css"]').remove()
document.querySelector('head style[source-path*="sample.less"]').remove()

View File

@@ -1,28 +1,38 @@
/** @babel */
/* eslint-env jasmine */
import {it, fit, ffit, fffit, beforeEach, afterEach} from './async-spec-helpers'
import path from 'path'
import temp from 'temp'
import child_process from 'child_process'
import childProcess from 'child_process'
import {updateProcessEnv, shouldGetEnvFromShell} from '../src/update-process-env'
import dedent from 'dedent'
import {EventEmitter} from 'events'
import mockSpawn from 'mock-spawn'
const temp = require('temp').track()
describe('updateProcessEnv(launchEnv)', function () {
let originalProcessEnv, originalProcessPlatform
let originalProcessEnv, originalProcessPlatform, originalSpawn, spawn
beforeEach(function () {
originalSpawn = childProcess.spawn
spawn = mockSpawn()
childProcess.spawn = spawn
originalProcessEnv = process.env
originalProcessPlatform = process.platform
process.env = {}
})
afterEach(function () {
if (originalSpawn) {
childProcess.spawn = originalSpawn
}
process.env = originalProcessEnv
process.platform = originalProcessPlatform
temp.cleanupSync()
})
describe('when the launch environment appears to come from a shell', function () {
it('updates process.env to match the launch environment', function () {
it('updates process.env to match the launch environment', async function () {
process.env = {
WILL_BE_DELETED: 'hi',
NODE_ENV: 'the-node-env',
@@ -32,7 +42,7 @@ describe('updateProcessEnv(launchEnv)', function () {
const initialProcessEnv = process.env
updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', TERM: 'xterm-something', KEY1: 'value1', KEY2: 'value2'})
await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', TERM: 'xterm-something', KEY1: 'value1', KEY2: 'value2'})
expect(process.env).toEqual({
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
PWD: '/the/dir',
@@ -50,7 +60,7 @@ describe('updateProcessEnv(launchEnv)', function () {
expect(process.env).toBe(initialProcessEnv)
})
it('allows ATOM_HOME to be overwritten only if the new value is a valid path', function () {
it('allows ATOM_HOME to be overwritten only if the new value is a valid path', async function () {
let newAtomHomePath = temp.mkdirSync('atom-home')
process.env = {
@@ -60,7 +70,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
}
updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir'})
await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir'})
expect(process.env).toEqual({
PWD: '/the/dir',
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
@@ -69,7 +79,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
})
updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', ATOM_HOME: path.join(newAtomHomePath, 'non-existent')})
await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', ATOM_HOME: path.join(newAtomHomePath, 'non-existent')})
expect(process.env).toEqual({
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
PWD: '/the/dir',
@@ -78,7 +88,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
})
updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', ATOM_HOME: newAtomHomePath})
await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', ATOM_HOME: newAtomHomePath})
expect(process.env).toEqual({
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
PWD: '/the/dir',
@@ -88,7 +98,7 @@ describe('updateProcessEnv(launchEnv)', function () {
})
})
it('allows ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT to be preserved if set', function () {
it('allows ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT to be preserved if set', async function () {
process.env = {
WILL_BE_DELETED: 'hi',
NODE_ENV: 'the-node-env',
@@ -96,7 +106,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
}
updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', NODE_ENV: 'the-node-env', NODE_PATH: '/the/node/path', ATOM_HOME: '/the/atom/home'})
await updateProcessEnv({ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true', PWD: '/the/dir', NODE_ENV: 'the-node-env', NODE_PATH: '/the/node/path', ATOM_HOME: '/the/atom/home'})
expect(process.env).toEqual({
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
PWD: '/the/dir',
@@ -105,7 +115,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
})
updateProcessEnv({PWD: '/the/dir', NODE_ENV: 'the-node-env', NODE_PATH: '/the/node/path', ATOM_HOME: '/the/atom/home'})
await updateProcessEnv({PWD: '/the/dir', NODE_ENV: 'the-node-env', NODE_PATH: '/the/node/path', ATOM_HOME: '/the/atom/home'})
expect(process.env).toEqual({
ATOM_DISABLE_SHELLING_OUT_FOR_ENVIRONMENT: 'true',
PWD: '/the/dir',
@@ -115,7 +125,7 @@ describe('updateProcessEnv(launchEnv)', function () {
})
})
it('allows an existing env variable to be updated', function () {
it('allows an existing env variable to be updated', async function () {
process.env = {
WILL_BE_UPDATED: 'old-value',
NODE_ENV: 'the-node-env',
@@ -123,7 +133,7 @@ describe('updateProcessEnv(launchEnv)', function () {
ATOM_HOME: '/the/atom/home'
}
updateProcessEnv(process.env)
await updateProcessEnv(process.env)
expect(process.env).toEqual(process.env)
let updatedEnv = {
@@ -135,27 +145,27 @@ describe('updateProcessEnv(launchEnv)', function () {
PWD: '/the/dir'
}
updateProcessEnv(updatedEnv)
await updateProcessEnv(updatedEnv)
expect(process.env).toEqual(updatedEnv)
})
})
describe('when the launch environment does not come from a shell', function () {
describe('on osx', function () {
it('updates process.env to match the environment in the user\'s login shell', function () {
describe('on macOS', function () {
it('updates process.env to match the environment in the user\'s login shell', async function () {
if (process.platform === 'win32') return // TestsThatFailOnWin32
process.platform = 'darwin'
process.env.SHELL = '/my/custom/bash'
spyOn(child_process, 'spawnSync').andReturn({
stdout: dedent`
FOO=BAR=BAZ=QUUX
TERM=xterm-something
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path
`
})
updateProcessEnv(process.env)
expect(child_process.spawnSync.mostRecentCall.args[0]).toBe('/my/custom/bash')
spawn.setDefault(spawn.simple(0, dedent`
FOO=BAR=BAZ=QUUX
TERM=xterm-something
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path
`))
await updateProcessEnv(process.env)
expect(spawn.calls.length).toBe(1)
expect(spawn.calls[0].command).toBe('/my/custom/bash')
expect(spawn.calls[0].args).toEqual(['-ilc', 'command env'])
expect(process.env).toEqual({
FOO: 'BAR=BAZ=QUUX',
TERM: 'xterm-something',
@@ -163,25 +173,25 @@ describe('updateProcessEnv(launchEnv)', function () {
})
// Doesn't error
updateProcessEnv(null)
await updateProcessEnv(null)
})
})
describe('on linux', function () {
it('updates process.env to match the environment in the user\'s login shell', function () {
it('updates process.env to match the environment in the user\'s login shell', async function () {
if (process.platform === 'win32') return // TestsThatFailOnWin32
process.platform = 'linux'
process.env.SHELL = '/my/custom/bash'
spyOn(child_process, 'spawnSync').andReturn({
stdout: dedent`
FOO=BAR=BAZ=QUUX
TERM=xterm-something
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path
`
})
updateProcessEnv(process.env)
expect(child_process.spawnSync.mostRecentCall.args[0]).toBe('/my/custom/bash')
spawn.setDefault(spawn.simple(0, dedent`
FOO=BAR=BAZ=QUUX
TERM=xterm-something
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/crazy/path
`))
await updateProcessEnv(process.env)
expect(spawn.calls.length).toBe(1)
expect(spawn.calls[0].command).toBe('/my/custom/bash')
expect(spawn.calls[0].args).toEqual(['-ilc', 'command env'])
expect(process.env).toEqual({
FOO: 'BAR=BAZ=QUUX',
TERM: 'xterm-something',
@@ -189,24 +199,26 @@ describe('updateProcessEnv(launchEnv)', function () {
})
// Doesn't error
updateProcessEnv(null)
await updateProcessEnv(null)
})
})
describe('on windows', function () {
it('does not update process.env', function () {
it('does not update process.env', async function () {
process.platform = 'win32'
spyOn(child_process, 'spawnSync')
spyOn(childProcess, 'spawn')
process.env = {FOO: 'bar'}
updateProcessEnv(process.env)
expect(child_process.spawnSync).not.toHaveBeenCalled()
await updateProcessEnv(process.env)
expect(childProcess.spawn).not.toHaveBeenCalled()
expect(process.env).toEqual({FOO: 'bar'})
})
})
describe('shouldGetEnvFromShell()', function () {
it('indicates when the environment should be fetched from the shell', function () {
if (process.platform === 'win32') return // TestsThatFailOnWin32
process.platform = 'darwin'
expect(shouldGetEnvFromShell({SHELL: '/bin/sh'})).toBe(true)
expect(shouldGetEnvFromShell({SHELL: '/usr/local/bin/sh'})).toBe(true)

View File

@@ -23,6 +23,7 @@ describe "WindowEventHandler", ->
describe "when the window is loaded", ->
it "doesn't have .is-blurred on the body tag", ->
return if process.platform is 'win32' #Win32TestFailures - can not steal focus
expect(document.body.className).not.toMatch("is-blurred")
describe "when the window is blurred", ->

View File

@@ -4,6 +4,9 @@ temp = require('temp').track()
{Disposable} = require 'event-kit'
describe "WorkspaceElement", ->
afterEach ->
temp.cleanupSync()
describe "when the workspace element is focused", ->
it "transfers focus to the active pane", ->
workspaceElement = atom.views.getView(atom.workspace)

View File

@@ -1,5 +1,5 @@
path = require 'path'
temp = require 'temp'
temp = require('temp').track()
TextEditor = require '../src/text-editor'
Workspace = require '../src/workspace'
Project = require '../src/project'
@@ -19,6 +19,9 @@ describe "Workspace", ->
atom.project.setPaths([atom.project.getDirectories()[0]?.resolve('dir')])
waits(1)
afterEach ->
temp.cleanupSync()
describe "serialization", ->
simulateReload = ->
workspaceState = atom.workspace.serialize()
@@ -489,6 +492,7 @@ describe "Workspace", ->
expect(item).toEqual {bar: "bar://baz"}
it "adds the file to the application's recent documents list", ->
return unless process.platform is 'darwin' # Feature only supported on macOS
spyOn(atom.applicationDelegate, 'addRecentDocument')
waitsForPromise ->
@@ -1139,6 +1143,7 @@ describe "Workspace", ->
range: [[2, 6], [2, 11]]
it "works on evil filenames", ->
atom.config.set('core.excludeVcsIgnoredPaths', false)
platform.generateEvilFiles()
atom.project.setPaths([path.join(__dirname, 'fixtures', 'evil-files')])
paths = []
@@ -1224,7 +1229,7 @@ describe "Workspace", ->
expect(matches.length).toBe 1
it "includes files and folders that begin with a '.'", ->
projectPath = temp.mkdirSync()
projectPath = temp.mkdirSync('atom-spec-workspace')
filePath = path.join(projectPath, '.text')
fs.writeFileSync(filePath, 'match this')
atom.project.setPaths([projectPath])

View File

@@ -13,6 +13,7 @@ StateStore = require './state-store'
StorageFolder = require './storage-folder'
{getWindowLoadSettings} = require './window-load-settings-helpers'
registerDefaultCommands = require './register-default-commands'
{updateProcessEnv} = require './update-process-env'
DeserializerManager = require './deserializer-manager'
ViewRegistry = require './view-registry'
@@ -239,16 +240,6 @@ class AtomEnvironment extends Model
new ReopenProjectMenuManager({@menu, @commands, @history, @config, open: (paths) => @open(pathsToOpen: paths)})
checkPortableHomeWritable = =>
responseChannel = "check-portable-home-writable-response"
ipcRenderer.on responseChannel, (event, response) ->
ipcRenderer.removeAllListeners(responseChannel)
@notifications.addWarning("#{response.message.replace(/([\\\.+\\-_#!])/g, '\\$1')}") if not response.writable
@disposables.add new Disposable -> ipcRenderer.removeAllListeners(responseChannel)
ipcRenderer.send('check-portable-home-writable', responseChannel)
checkPortableHomeWritable()
attachSaveStateListeners: ->
saveState = _.debounce((=>
window.requestIdleCallback => @saveState({isUnloading: false}) unless @unloaded
@@ -675,7 +666,11 @@ class AtomEnvironment extends Model
# Call this method when establishing a real application window.
startEditorWindow: ->
@unloaded = false
@loadState().then (state) =>
updateProcessEnvPromise = updateProcessEnv(@getLoadSettings().env)
updateProcessEnvPromise.then =>
@packages.triggerActivationHook('core:loaded-shell-environment')
loadStatePromise = @loadState().then (state) =>
@windowDimensions = state?.windowDimensions
@displayWindow().then =>
@commandInstaller.installAtomCommand false, (error) ->
@@ -716,6 +711,8 @@ class AtomEnvironment extends Model
@openInitialEmptyEditorIfNecessary()
Promise.all([loadStatePromise, updateProcessEnvPromise])
serialize: (options) ->
version: @constructor.version
project: @project.serialize(options)

62
src/atom-paths.js Normal file
View File

@@ -0,0 +1,62 @@
/** @babel */
const fs = require('fs-plus')
const path = require('path')
const hasWriteAccess = (dir) => {
const testFilePath = path.join(dir, 'write.test')
try {
fs.writeFileSync(testFilePath, new Date().toISOString(), { flag: 'w+' })
fs.unlinkSync(testFilePath)
return true
} catch (err) {
return false
}
}
const getAppDirectory = () => {
switch (process.platform) {
case 'darwin':
return path.join(process.execPath.substring(0, process.execPath.indexOf('.app')), '..')
case 'linux':
case 'win32':
return path.join(process.execPath, '..')
}
}
module.exports = {
setAtomHome: (homePath) => {
// When a read-writeable .atom folder exists above app use that
const portableHomePath = path.join(getAppDirectory(), '.atom')
if (fs.existsSync(portableHomePath)) {
if (hasWriteAccess(portableHomePath)) {
process.env.ATOM_HOME = portableHomePath
} else {
// A path exists so it was intended to be used but we didn't have rights, so warn.
console.log(`Insufficient permission to portable Atom home "${portableHomePath}".`)
}
}
// Check ATOM_HOME environment variable next
if (process.env.ATOM_HOME !== undefined) {
return
}
// Fall back to default .atom folder in users home folder
process.env.ATOM_HOME = path.join(homePath, '.atom')
},
setUserData: (app) => {
const electronUserDataPath = path.join(process.env.ATOM_HOME, 'electronUserData')
if (fs.existsSync(electronUserDataPath)) {
if (hasWriteAccess(electronUserDataPath)) {
app.setPath('userData', electronUserDataPath)
} else {
// A path exists so it was intended to be used but we didn't have rights, so warn.
console.log(`Insufficient permission to Electron user data "${electronUserDataPath}".`)
}
}
},
getAppDirectory: getAppDirectory
}

View File

@@ -50,33 +50,8 @@ export default class BufferedProcess {
this.emitter = new Emitter()
this.command = command
// Related to joyent/node#2318
if (process.platform === 'win32' && !options.shell) {
let cmdArgs = []
// Quote all arguments and escapes inner quotes
if (args) {
cmdArgs = args.filter((arg) => arg != null)
.map((arg) => {
if (this.isExplorerCommand(command) && /^\/[a-zA-Z]+,.*$/.test(arg)) {
// Don't wrap /root,C:\folder style arguments to explorer calls in
// quotes since they will not be interpreted correctly if they are
return arg
} else {
return `\"${arg.toString().replace(/"/g, '\\"')}\"`
}
})
}
if (/\s/.test(command)) {
cmdArgs.unshift(`\"${command}\"`)
} else {
cmdArgs.unshift(command)
}
cmdArgs = ['/s', '/d', '/c', `\"${cmdArgs.join(' ')}\"`]
const cmdOptions = _.clone(options)
cmdOptions.windowsVerbatimArguments = true
this.spawn(this.getCmdPath(), cmdArgs, cmdOptions)
if (process.platform === 'win32' && options.shell === undefined) {
this.spawnWithEscapedWindowsArgs(command, args, options)
} else {
this.spawn(command, args, options)
}
@@ -85,6 +60,33 @@ export default class BufferedProcess {
this.handleEvents(stdout, stderr, exit)
}
// Windows has a bunch of special rules that node still doesn't take care of for you
spawnWithEscapedWindowsArgs (command, args, options) {
let cmdArgs = []
// Quote all arguments and escapes inner quotes
if (args) {
cmdArgs = args.filter((arg) => arg != null)
.map((arg) => {
if (this.isExplorerCommand(command) && /^\/[a-zA-Z]+,.*$/.test(arg)) {
// Don't wrap /root,C:\folder style arguments to explorer calls in
// quotes since they will not be interpreted correctly if they are
return arg
} else {
// Escape double quotes by putting a backslash in front of them
return `\"${arg.toString().replace(/"/g, '\\"')}\"`
}
})
}
// The command itself is quoted if it contains spaces, &, ^ or | chars
cmdArgs.unshift(/\s|&|\^|\|/.test(command) ? `\"${command}\"` : command)
const cmdOptions = _.clone(options)
cmdOptions.windowsVerbatimArguments = true
this.spawn(this.getCmdPath(), ['/s', '/d', '/c', `\"${cmdArgs.join(' ')}\"`], cmdOptions)
}
/*
Section: Event Subscription
*/

View File

@@ -12,7 +12,7 @@ const configSchema = {
properties: {
ignoredNames: {
type: 'array',
default: ['.git', '.hg', '.svn', '.DS_Store', '._*', 'Thumbs.db'],
default: ['.git', '.hg', '.svn', '.DS_Store', '._*', 'Thumbs.db', 'desktop.ini'],
items: {
type: 'string'
},
@@ -85,6 +85,8 @@ const configSchema = {
default: 'utf8',
enum: [
'cp437',
'cp850',
'cp866',
'eucjp',
'euckr',
'gbk',
@@ -117,12 +119,16 @@ const configSchema = {
'windows1255',
'windows1256',
'windows1257',
'windows1258',
'windows866'
'windows1258'
]
},
openEmptyEditorOnStart: {
description: 'Automatically open an empty editor on startup.',
description: 'When checked opens an untitled editor when loading a blank environment (such as with _File > New Window_ or when "Restore Previous Windows On Start" is unchecked); otherwise no editor is opened when loading a blank environment. This setting has no effect when restoring a previous state.',
type: 'boolean',
default: true
},
restorePreviousWindowsOnStart: {
description: 'When checked restores the last state of all Atom windows when started from the icon or `atom` by itself from the command line; otherwise a blank environment is loaded.',
type: 'boolean',
default: true
},

View File

@@ -238,6 +238,7 @@ class GitRepository
# Public: Returns the git configuration value specified by the key.
#
# * `key` The {String} key for the configuration to lookup.
# * `path` An optional {String} path in the repository to get this information
# for, only needed if the repository has submodules.
getConfigValue: (key, path) -> @getRepo(path).getConfigValue(key)

View File

@@ -103,6 +103,7 @@ class GutterContainerComponent
@domNode.appendChild(gutterComponent.getDomNode())
else
@domNode.insertBefore(gutterComponent.getDomNode(), @domNode.children[indexInOldGutters])
indexInOldGutters += 1
# Remove any gutters that were not present in the new gutters state.
for gutterComponentDescription in @gutterComponents

View File

@@ -47,6 +47,8 @@ export class HistoryManager {
}
addProject (paths, lastOpened) {
if (paths.length === 0) return
let project = this.getProject(paths)
if (!project) {
project = new HistoryProject(paths)
@@ -60,9 +62,8 @@ export class HistoryManager {
}
getProject (paths) {
const pathsString = paths.toString()
for (var i = 0; i < this.projects.length; i++) {
if (this.projects[i].paths.toString() === pathsString) {
if (arrayEquivalent(paths, this.projects[i].paths)) {
return this.projects[i]
}
}
@@ -98,6 +99,14 @@ export class HistoryManager {
}
}
function arrayEquivalent (a, b) {
if (a.length !== b.length) return false
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) return false
}
return true
}
export class HistoryProject {
constructor (paths, lastOpened) {
this.paths = paths

View File

@@ -8,8 +8,6 @@ module.exports = ({blobStore}) ->
{resourcePath, devMode, env} = getWindowLoadSettings()
require './electron-shims'
updateProcessEnv(env)
# Add application-specific exports to module search path.
exportsPath = path.join(resourcePath, 'exports')
require('module').globalPaths.push(exportsPath)

View File

@@ -1,15 +1,6 @@
module.exports =
class InputComponent
constructor: ->
@domNode = document.createElement('input')
@domNode.classList.add('hidden-input')
@domNode.setAttribute('tabindex', -1)
@domNode.setAttribute('data-react-skip-selection-restoration', true)
@domNode.style['-webkit-transform'] = 'translateZ(0)'
@domNode.addEventListener 'paste', (event) -> event.preventDefault()
getDomNode: ->
@domNode
constructor: (@domNode) ->
updateSync: (state) ->
@oldState ?= {}

View File

@@ -34,7 +34,7 @@ class AtomApplication
unless options.socketPath?
if process.platform is 'win32'
userNameSafe = new Buffer(process.env.USERNAME).toString('base64')
options.socketPath = "\\\\.\\pipe\\atom-#{options.version}-#{userNameSafe}-sock"
options.socketPath = "\\\\.\\pipe\\atom-#{options.version}-#{userNameSafe}-#{process.arch}-sock"
else
options.socketPath = path.join(os.tmpdir(), "atom-#{options.version}-#{process.env.USER}.sock")
@@ -63,7 +63,7 @@ class AtomApplication
exit: (status) -> app.exit(status)
constructor: (options) ->
{@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, @logFile, @setPortable, @userDataDir} = options
{@resourcePath, @devResourcePath, @version, @devMode, @safeMode, @socketPath, @logFile, @userDataDir} = options
@socketPath = null if options.test or options.benchmark or options.benchmarkTest
@pidsToOpenWindows = {}
@windows = []
@@ -509,7 +509,7 @@ class AtomApplication
openPaths: ({initialPaths, pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window, clearWindowState, addToLastWindow, env}={}) ->
if not pathsToOpen? or pathsToOpen.length is 0
return
env = process.env unless env?
devMode = Boolean(devMode)
safeMode = Boolean(safeMode)
clearWindowState = Boolean(clearWindowState)
@@ -796,7 +796,6 @@ class AtomApplication
restart: ->
args = []
args.push("--safe") if @safeMode
args.push("--portable") if @setPortable
args.push("--log-file=#{@logFile}") if @logFile?
args.push("--socket-path=#{@socketPath}") if @socketPath?
args.push("--user-data-dir=#{@userDataDir}") if @userDataDir?

View File

@@ -1,58 +0,0 @@
const fs = require('fs-plus')
const path = require('path')
const {ipcMain} = require('electron')
module.exports = class AtomPortable {
static getPortableAtomHomePath () {
const execDirectoryPath = path.dirname(process.execPath)
return path.join(execDirectoryPath, '..', '.atom')
}
static setPortable (existingAtomHome) {
fs.copySync(existingAtomHome, this.getPortableAtomHomePath())
}
static isPortableInstall (platform, environmentAtomHome, defaultHome) {
if (!['linux', 'win32'].includes(platform)) {
return false
}
if (environmentAtomHome) {
return false
}
if (!fs.existsSync(this.getPortableAtomHomePath())) {
return false
}
// Currently checking only that the directory exists and is writable,
// probably want to do some integrity checks on contents in future.
return this.isPortableAtomHomePathWritable(defaultHome)
}
static isPortableAtomHomePathWritable (defaultHome) {
let writable = false
let message = ''
try {
const writePermissionTestFile = path.join(this.getPortableAtomHomePath(), 'write.test')
if (!fs.existsSync(writePermissionTestFile)) {
fs.writeFileSync(writePermissionTestFile, 'test')
}
fs.removeSync(writePermissionTestFile)
writable = true
} catch (error) {
message = `Failed to use portable Atom home directory (${this.getPortableAtomHomePath()}). Using the default instead (${defaultHome}). ${error.message}.`
}
ipcMain.on('check-portable-home-writable', function (event) {
event.sender.send('check-portable-home-writable-response', {
writable: writable,
message: message
})
})
return writable
}
}

View File

@@ -17,13 +17,15 @@ class AutoUpdateManager
constructor: (@version, @testMode, resourcePath, @config) ->
@state = IdleState
@iconPath = path.resolve(__dirname, '..', '..', 'resources', 'atom.png')
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
process.nextTick => @setupAutoUpdater()
setupAutoUpdater: ->
if process.platform is 'win32'
archSuffix = if process.arch is 'ia32' then '' else '-' + process.arch
@feedUrl = "https://atom.io/api/updates#{archSuffix}"
autoUpdater = require './auto-updater-win32'
else
@feedUrl = "https://atom.io/api/updates?version=#{@version}"
{autoUpdater} = require 'electron'
autoUpdater.on 'error', (event, message) =>

View File

@@ -41,10 +41,6 @@ module.exports = function parseCommandLine (processArgs) {
'safe',
'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.'
)
options.boolean('portable').describe(
'portable',
'Set portable mode. Copies the ~/.atom folder to be a sibling of the installed Atom location if a .atom folder is not already there.'
)
options.boolean('benchmark').describe('benchmark', 'Open a new window that runs the specified benchmarks.')
options.boolean('benchmark-test').describe('benchmark--test', 'Run a faster version of the benchmarks in headless mode.')
options.alias('t', 'test').boolean('t').describe('t', 'Run the specified specs and exit with error code on failures.')
@@ -104,7 +100,6 @@ module.exports = function parseCommandLine (processArgs) {
const profileStartup = args['profile-startup']
const clearWindowState = args['clear-window-state']
const urlsToOpen = []
const setPortable = args.portable
let devMode = args['dev']
let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
let resourcePath = null
@@ -152,7 +147,6 @@ module.exports = function parseCommandLine (processArgs) {
userDataDir,
profileStartup,
timeout,
setPortable,
clearWindowState,
addToLastWindow,
mainProcess,

View File

@@ -1,10 +1,10 @@
const {app} = require('electron')
const fs = require('fs-plus')
const nslog = require('nslog')
const path = require('path')
const temp = require('temp')
const parseCommandLine = require('./parse-command-line')
const startCrashReporter = require('../crash-reporter-start')
const atomPaths = require('../atom-paths')
module.exports = function start (resourcePath, startTime) {
global.shellStartTime = startTime
@@ -23,7 +23,8 @@ module.exports = function start (resourcePath, startTime) {
console.log = nslog
const args = parseCommandLine(process.argv.slice(1))
setupAtomHome(args)
atomPaths.setAtomHome(app.getPath('home'))
atomPaths.setUserData()
setupCompileCache()
if (handleStartupEventWithSquirrel()) {
@@ -39,7 +40,7 @@ module.exports = function start (resourcePath, startTime) {
}
// NB: This prevents Win10 from showing dupe items in the taskbar
app.setAppUserModelId('com.squirrel.atom.atom')
app.setAppUserModelId('com.squirrel.atom.' + process.arch)
function addPathToOpen (event, pathToOpen) {
event.preventDefault()
@@ -79,36 +80,6 @@ function handleStartupEventWithSquirrel () {
return SquirrelUpdate.handleStartupEvent(app, squirrelCommand)
}
function setupAtomHome ({setPortable}) {
if (process.env.ATOM_HOME) {
return
}
let atomHome = path.join(app.getPath('home'), '.atom')
const AtomPortable = require('./atom-portable')
if (setPortable && !AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)) {
try {
AtomPortable.setPortable(atomHome)
} catch (error) {
console.log(`Failed copying portable directory '${atomHome}' to '${AtomPortable.getPortableAtomHomePath()}'`)
console.log(`${error.message} ${error.stack}`)
}
}
if (AtomPortable.isPortableInstall(process.platform, process.env.ATOM_HOME, atomHome)) {
atomHome = AtomPortable.getPortableAtomHomePath()
}
try {
atomHome = fs.realpathSync(atomHome)
} catch (e) {
// Don't throw an error if atomHome doesn't exist.
}
process.env.ATOM_HOME = atomHome
}
function setupCompileCache () {
const CompileCache = require('../compile-cache')
CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME)

View File

@@ -39,6 +39,7 @@ class PackageManager
@activationHookEmitter = new Emitter
@packageDirPaths = []
@deferredActivationHooks = []
@triggeredActivationHooks = new Set()
if configDirPath? and not safeMode
if @devMode
@packageDirPaths.push(path.join(configDirPath, "dev", "packages"))
@@ -67,6 +68,7 @@ class PackageManager
@deactivatePackages()
@loadedPackages = {}
@packageStates = {}
@triggeredActivationHooks.clear()
###
Section: Event Subscription
@@ -460,12 +462,17 @@ class PackageManager
Promise.resolve(pack)
else if pack = @loadPackage(name)
@activatingPackages[pack.name] = pack
pack.activate().then =>
activationPromise = pack.activate().then =>
if @activatingPackages[pack.name]?
delete @activatingPackages[pack.name]
@activePackages[pack.name] = pack
@emitter.emit 'did-activate-package', pack
pack
unless @deferredActivationHooks?
@triggeredActivationHooks.forEach((hook) => @activationHookEmitter.emit(hook))
activationPromise
else
Promise.reject(new Error("Failed to load package '#{name}'"))
@@ -476,6 +483,7 @@ class PackageManager
triggerActivationHook: (hook) ->
return new Error("Cannot trigger an empty activation hook") unless hook? and _.isString(hook) and hook.length > 0
@triggeredActivationHooks.add(hook)
if @deferredActivationHooks?
@deferredActivationHooks.push hook
else

View File

@@ -96,7 +96,7 @@ class PackageTranspilationRegistry {
}
lastPath = thisPath
thisPath = path.resolve(thisPath, '..')
thisPath = path.join(thisPath, '..')
}
this.specByFilePath[filePath] = null

View File

@@ -24,6 +24,7 @@ class Package
mainModulePath: null
resolvedMainModulePath: false
mainModule: null
mainInitialized: false
mainActivated: false
###
@@ -114,8 +115,24 @@ class Package
@menus = []
@grammars = []
@settings = []
@mainInitialized = false
@mainActivated = false
initializeIfNeeded: ->
return if @mainInitialized
@measure 'initializeTime', =>
try
# The main module's `initialize()` method is guaranteed to be called
# before its `activate()`. This gives you a chance to handle the
# serialized package state before the package's derserializers and view
# providers are used.
@requireMainModule() unless @mainModule?
@mainModule.initialize?(@packageManager.getPackageState(@name) ? {})
@mainInitialized = true
catch error
@handleError("Failed to initialize the #{@name} package", error)
return
activate: ->
@grammarsPromise ?= @loadGrammars()
@activationPromise ?=
@@ -140,10 +157,13 @@ class Package
@registerViewProviders()
@activateStylesheets()
if @mainModule? and not @mainActivated
@initializeIfNeeded()
@mainModule.activateConfig?()
@mainModule.activate?(@packageManager.getPackageState(@name) ? {})
@mainActivated = true
@activateServices()
@activationCommandSubscriptions?.dispose()
@activationHookSubscriptions?.dispose()
catch error
@handleError("Failed to activate the #{@name} package", error)
@@ -301,6 +321,7 @@ class Package
deserialize: (state, atomEnvironment) =>
@registerViewProviders()
@requireMainModule()
@initializeIfNeeded()
@mainModule[methodName](state, atomEnvironment)
return
@@ -318,6 +339,7 @@ class Package
@requireMainModule()
@metadata.viewProviders.forEach (methodName) =>
@viewRegistry.addViewProvider (model) =>
@initializeIfNeeded()
@mainModule[methodName](model)
@registeredViewProviders = true
@@ -420,6 +442,7 @@ class Package
@mainModule?.deactivate?()
@mainModule?.deactivateConfig?()
@mainActivated = false
@mainInitialized = false
catch e
console.error "Error deactivating package '#{@name}'", e.stack
@emitter.emit 'did-deactivate'

View File

@@ -234,6 +234,39 @@ class Pane extends Model
onDidChangeActiveItem: (callback) ->
@emitter.on 'did-change-active-item', callback
# Public: Invoke the given callback when {::activateNextRecentlyUsedItem}
# has been called, either initiating or continuing a forward MRU traversal of
# pane items.
#
# * `callback` {Function} to be called with when the active item changes.
# * `nextRecentlyUsedItem` The next MRU item, now being set active
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onChooseNextMRUItem: (callback) ->
@emitter.on 'choose-next-mru-item', callback
# Public: Invoke the given callback when {::activatePreviousRecentlyUsedItem}
# has been called, either initiating or continuing a reverse MRU traversal of
# pane items.
#
# * `callback` {Function} to be called with when the active item changes.
# * `previousRecentlyUsedItem` The previous MRU item, now being set active
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onChooseLastMRUItem: (callback) ->
@emitter.on 'choose-last-mru-item', callback
# Public: Invoke the given callback when {::moveActiveItemToTopOfStack}
# has been called, terminating an MRU traversal of pane items and moving the
# current active item to the top of the stack. Typically bound to a modifier
# (e.g. CTRL) key up event.
#
# * `callback` {Function} to be called with when the MRU traversal is done.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDoneChoosingMRUItem: (callback) ->
@emitter.on 'done-choosing-mru-item', callback
# Public: Invoke the given callback with the current and future values of
# {::getActiveItem}.
#
@@ -334,6 +367,7 @@ class Pane extends Model
@itemStackIndex = @itemStack.length if @itemStackIndex is 0
@itemStackIndex = @itemStackIndex - 1
nextRecentlyUsedItem = @itemStack[@itemStackIndex]
@emitter.emit 'choose-next-mru-item', nextRecentlyUsedItem
@setActiveItem(nextRecentlyUsedItem, modifyStack: false)
# Makes the previous item in the itemStack active.
@@ -343,12 +377,15 @@ class Pane extends Model
@itemStackIndex = -1
@itemStackIndex = @itemStackIndex + 1
previousRecentlyUsedItem = @itemStack[@itemStackIndex]
@emitter.emit 'choose-last-mru-item', previousRecentlyUsedItem
@setActiveItem(previousRecentlyUsedItem, modifyStack: false)
# Moves the active item to the end of the itemStack once the ctrl key is lifted
moveActiveItemToTopOfStack: ->
delete @itemStackIndex
@addItemToStack(@activeItem)
@emitter.emit 'done-choosing-mru-item'
# Public: Makes the next item active.
activateNextItem: ->

View File

@@ -1,59 +1,71 @@
/** @babel */
import { SelectListView } from 'atom-space-pen-views'
import SelectListView from 'atom-select-list'
export default class ReopenProjectListView extends SelectListView {
initialize (callback) {
export default class ReopenProjectListView {
constructor (callback) {
this.callback = callback
super.initialize()
this.addClass('reopen-project')
this.list.addClass('mark-active')
this.selectListView = new SelectListView({
emptyMessage: 'No projects in history.',
itemsClassList: ['mark-active'],
items: [],
filterKeyForItem: (project) => project.name,
elementForItem: (project) => {
let element = document.createElement('li')
if (project.name === this.currentProjectName) {
element.classList.add('active')
}
element.textContent = project.name
return element
},
didConfirmSelection: (project) => {
this.cancel()
this.callback(project.value)
},
didCancelSelection: () => {
this.cancel()
}
})
this.selectListView.element.classList.add('reopen-project')
}
getFilterKey () {
return 'name'
get element () {
return this.selectListView.element
}
destroy () {
dispose () {
this.cancel()
return this.selectListView.destroy()
}
viewForItem (project) {
let element = document.createElement('li')
if (project.name === this.currentProjectName) {
element.classList.add('active')
}
element.textContent = project.name
return element
}
cancelled () {
cancel () {
if (this.panel != null) {
this.panel.destroy()
}
this.panel = null
this.currentProjectName = null
}
confirmed (project) {
this.cancel()
this.callback(project.value)
if (this.previouslyFocusedElement) {
this.previouslyFocusedElement.focus()
this.previouslyFocusedElement = null
}
}
attach () {
this.storeFocusedElement()
this.previouslyFocusedElement = document.activeElement
if (this.panel == null) {
this.panel = atom.workspace.addModalPanel({item: this})
}
this.focusFilterEditor()
this.selectListView.focus()
this.selectListView.reset()
}
toggle () {
async toggle () {
if (this.panel != null) {
this.cancel()
} else {
this.currentProjectName = atom.project != null ? this.makeName(atom.project.getPaths()) : null
this.setItems(atom.history.getProjects().map(p => ({ name: this.makeName(p.paths), value: p.paths })))
const projects = atom.history.getProjects().map(p => ({ name: this.makeName(p.paths), value: p.paths }))
await this.selectListView.update({items: projects})
this.attach()
}
}

View File

@@ -46,6 +46,32 @@ export default class ReopenProjectMenuManager {
this.projects = this.historyManager.getProjects().slice(0, this.config.get('core.reopenProjectMenuCount'))
const newMenu = ReopenProjectMenuManager.createProjectsMenu(this.projects)
this.lastProjectMenu = this.menuManager.add([newMenu])
this.updateWindowsJumpList()
}
updateWindowsJumpList () {
if (process.platform !== 'win32') return
if (this.app === undefined) {
this.app = require('remote').app
}
this.app.setJumpList([
{
type: 'custom',
name: 'Recent Projects',
items: this.projects.map(project => ({
type: 'task',
title: project.paths.map(ReopenProjectMenuManager.betterBaseName).join(', '),
description: project.paths.map(path => `${ReopenProjectMenuManager.betterBaseName(path)} (${path})`).join(' '),
program: process.execPath,
args: project.paths.map(path => `"${path}"`).join(' ') }))
},
{ type: 'recent' },
{ items: [
{type: 'task', title: 'New Window', program: process.execPath, args: '--new-window', description: 'Opens a new Atom window'}
]}
])
}
dispose () {

View File

@@ -366,7 +366,7 @@ class Selection extends Model
insertText: (text, options={}) ->
oldBufferRange = @getBufferRange()
wasReversed = @isReversed()
@clear()
@clear(options)
autoIndentFirstLine = false
precedingText = @editor.getTextInRange([[oldBufferRange.start.row, 0], oldBufferRange.start])
@@ -403,7 +403,7 @@ class Selection extends Model
else if options.autoDecreaseIndent and NonWhitespaceRegExp.test(text)
@editor.autoDecreaseIndentForBufferRow(newBufferRange.start.row)
@autoscroll() if @isLastSelection()
@autoscroll() if options.autoscroll ? @isLastSelection()
newBufferRange

View File

@@ -42,7 +42,7 @@ class TextEditorComponent
@assert domNode?, "TextEditorComponent::domNode was set to null."
@domNodeValue = domNode
constructor: ({@editor, @hostElement, tileSize, @views, @themes, @styles, @assert}) ->
constructor: ({@editor, @hostElement, tileSize, @views, @themes, @styles, @assert, hiddenInputElement}) ->
@tileSize = tileSize if tileSize?
@disposables = new CompositeDisposable
@@ -70,8 +70,12 @@ class TextEditorComponent
@scrollViewNode.classList.add('scroll-view')
@domNode.appendChild(@scrollViewNode)
@hiddenInputComponent = new InputComponent
@scrollViewNode.appendChild(@hiddenInputComponent.getDomNode())
@hiddenInputComponent = new InputComponent(hiddenInputElement)
@scrollViewNode.appendChild(hiddenInputElement)
# Add a getModel method to the hidden input component to make it easy to
# access the editor in response to DOM events or when using
# document.activeElement.
hiddenInputElement.getModel = => @editor
@linesComponent = new LinesComponent({@presenter, @domElementPool, @assert, @grammars, @views})
@scrollViewNode.appendChild(@linesComponent.getDomNode())
@@ -342,7 +346,6 @@ class TextEditorComponent
focused: ->
if @mounted
@presenter.setFocused(true)
@hiddenInputComponent.getDomNode().focus()
blurred: ->
if @mounted
@@ -416,7 +419,6 @@ class TextEditorComponent
onScrollViewScroll: =>
if @mounted
console.warn "TextEditorScrollView scrolled when it shouldn't have."
@scrollViewNode.scrollTop = 0
@scrollViewNode.scrollLeft = 0
@@ -905,7 +907,7 @@ class TextEditorComponent
screenRowForNode: (node) ->
while node?
if screenRow = node.dataset.screenRow
if screenRow = node.dataset?.screenRow
return parseInt(screenRow)
node = node.parentElement
null

View File

@@ -25,8 +25,17 @@ class TextEditorElement extends HTMLElement
@emitter = new Emitter
@subscriptions = new CompositeDisposable
@hiddenInputElement = document.createElement('input')
@hiddenInputElement.classList.add('hidden-input')
@hiddenInputElement.setAttribute('tabindex', -1)
@hiddenInputElement.setAttribute('data-react-skip-selection-restoration', true)
@hiddenInputElement.style['-webkit-transform'] = 'translateZ(0)'
@hiddenInputElement.addEventListener 'paste', (event) -> event.preventDefault()
@addEventListener 'focus', @focused.bind(this)
@addEventListener 'blur', @blurred.bind(this)
@hiddenInputElement.addEventListener 'focus', @focused.bind(this)
@hiddenInputElement.addEventListener 'blur', @inputNodeBlurred.bind(this)
@classList.add('editor')
@setAttribute('tabindex', -1)
@@ -117,12 +126,10 @@ class TextEditorElement extends HTMLElement
themes: @themes
styles: @styles
workspace: @workspace
assert: @assert
assert: @assert,
hiddenInputElement: @hiddenInputElement
)
@rootElement.appendChild(@component.getDomNode())
inputNode = @component.hiddenInputComponent.getDomNode()
inputNode.addEventListener 'focus', @focused.bind(this)
inputNode.addEventListener 'blur', @inputNodeBlurred.bind(this)
unmountComponent: ->
if @component?
@@ -132,16 +139,17 @@ class TextEditorElement extends HTMLElement
focused: (event) ->
@component?.focused()
@hiddenInputElement.focus()
blurred: (event) ->
if event.relatedTarget is @component?.hiddenInputComponent.getDomNode()
if event.relatedTarget is @hiddenInputElement
event.stopImmediatePropagation()
return
@component?.blurred()
inputNodeBlurred: (event) ->
if event.relatedTarget isnt this
@dispatchEvent(new FocusEvent('blur', bubbles: false))
@dispatchEvent(new FocusEvent('blur', relatedTarget: event.relatedTarget, bubbles: false))
addGrammarScopeAttribute: ->
@dataset.grammar = @model.getGrammar()?.scopeName?.replace(/\./g, ' ')

View File

@@ -306,9 +306,6 @@ class TextEditorPresenter
getEndTileRow: ->
@tileForRow(@endRow ? 0)
isValidScreenRow: (screenRow) ->
screenRow >= 0 and screenRow < @model.getApproximateScreenLineCount()
getScreenRowsToRender: ->
startRow = @getStartTileRow()
endRow = @getEndTileRow() + @tileSize
@@ -320,7 +317,7 @@ class TextEditorPresenter
if @screenRowsToMeasure?
screenRows.push(@screenRowsToMeasure...)
screenRows = screenRows.filter @isValidScreenRow.bind(this)
screenRows = screenRows.filter (row) -> row >= 0
screenRows.sort (a, b) -> a - b
_.uniq(screenRows, true)
@@ -395,19 +392,17 @@ class TextEditorPresenter
visibleTiles[tileStartRow] = true
zIndex++
if @mouseWheelScreenRow? and 0 <= @mouseWheelScreenRow < @model.getApproximateScreenLineCount()
mouseWheelTile = @tileForRow(@mouseWheelScreenRow)
unless visibleTiles[mouseWheelTile]?
@lineNumberGutter.tiles[mouseWheelTile].display = "none"
@state.content.tiles[mouseWheelTile].display = "none"
visibleTiles[mouseWheelTile] = true
mouseWheelTileId = @tileForRow(@mouseWheelScreenRow) if @mouseWheelScreenRow?
for id, tile of @state.content.tiles
continue if visibleTiles.hasOwnProperty(id)
delete @state.content.tiles[id]
delete @lineNumberGutter.tiles[id]
if Number(id) is mouseWheelTileId
@state.content.tiles[id].display = "none"
@lineNumberGutter.tiles[id].display = "none"
else
delete @state.content.tiles[id]
delete @lineNumberGutter.tiles[id]
updateLinesState: (tileState, screenRows) ->
tileState.lines ?= {}
@@ -456,7 +451,7 @@ class TextEditorPresenter
for decoration in @model.getOverlayDecorations()
continue unless decoration.getMarker().isValid()
{item, position, class: klass} = decoration.getProperties()
{item, position, class: klass, avoidOverflow} = decoration.getProperties()
if position is 'tail'
screenPosition = decoration.getMarker().getTailScreenPosition()
else
@@ -471,15 +466,16 @@ class TextEditorPresenter
if overlayDimensions = @overlayDimensions[decoration.id]
{itemWidth, itemHeight, contentMargin} = overlayDimensions
rightDiff = left + itemWidth + contentMargin - @windowWidth
left -= rightDiff if rightDiff > 0
if avoidOverflow isnt false
rightDiff = left + itemWidth + contentMargin - @windowWidth
left -= rightDiff if rightDiff > 0
leftDiff = left + contentMargin
left -= leftDiff if leftDiff < 0
leftDiff = left + contentMargin
left -= leftDiff if leftDiff < 0
if top + itemHeight > @windowHeight and
top - (itemHeight + @lineHeight) >= 0
top -= itemHeight + @lineHeight
if top + itemHeight > @windowHeight and
top - (itemHeight + @lineHeight) >= 0
top -= itemHeight + @lineHeight
pixelPosition.top = top
pixelPosition.left = left
@@ -1006,8 +1002,7 @@ class TextEditorPresenter
@lineHeight? and @baseCharacterWidth?
pixelPositionForScreenPosition: (screenPosition) ->
position =
@linesYardstick.pixelPositionForScreenPosition(screenPosition)
position = @linesYardstick.pixelPositionForScreenPosition(screenPosition)
position.top -= @getScrollTop()
position.left -= @getScrollLeft()
@@ -1230,13 +1225,14 @@ class TextEditorPresenter
screenRange.end.column = 0
repositionRegionWithinTile: (region, tileStartRow) ->
region.top += @scrollTop - @lineTopIndex.pixelPositionBeforeBlocksForRow(tileStartRow)
region.left += @scrollLeft
region.top += @scrollTop - @lineTopIndex.pixelPositionBeforeBlocksForRow(tileStartRow)
buildHighlightRegions: (screenRange) ->
lineHeightInPixels = @lineHeight
startPixelPosition = @pixelPositionForScreenPosition(screenRange.start)
endPixelPosition = @pixelPositionForScreenPosition(screenRange.end)
startPixelPosition.left += @scrollLeft
endPixelPosition.left += @scrollLeft
spannedRows = screenRange.end.row - screenRange.start.row + 1
regions = []

View File

@@ -222,6 +222,7 @@ class TextEditor extends Model
@backgroundWorkHandle = null
update: (params) ->
currentSoftWrapColumn = @getSoftWrapColumn()
displayLayerParams = {}
for param in Object.keys(params)
@@ -272,12 +273,16 @@ class TextEditor extends Model
when 'softWrapAtPreferredLineLength'
if value isnt @softWrapAtPreferredLineLength
@softWrapAtPreferredLineLength = value
displayLayerParams.softWrapColumn = @getSoftWrapColumn() if @isSoftWrapped()
softWrapColumn = @getSoftWrapColumn()
if softWrapColumn isnt currentSoftWrapColumn
displayLayerParams.softWrapColumn = softWrapColumn
when 'preferredLineLength'
if value isnt @preferredLineLength
@preferredLineLength = value
displayLayerParams.softWrapColumn = @getSoftWrapColumn() if @isSoftWrapped()
softWrapColumn = @getSoftWrapColumn()
if softWrapColumn isnt currentSoftWrapColumn
displayLayerParams.softWrapColumn = softWrapColumn
when 'mini'
if value isnt @mini
@@ -322,12 +327,16 @@ class TextEditor extends Model
when 'editorWidthInChars'
if value > 0 and value isnt @editorWidthInChars
@editorWidthInChars = value
displayLayerParams.softWrapColumn = @getSoftWrapColumn() if @isSoftWrapped()
softWrapColumn = @getSoftWrapColumn()
if softWrapColumn isnt currentSoftWrapColumn
displayLayerParams.softWrapColumn = softWrapColumn
when 'width'
if value isnt @width
@width = value
displayLayerParams.softWrapColumn = @getSoftWrapColumn() if @isSoftWrapped()
softWrapColumn = @getSoftWrapColumn()
if softWrapColumn isnt currentSoftWrapColumn
displayLayerParams.softWrapColumn = softWrapColumn
when 'scrollPastEnd'
if value isnt @scrollPastEnd
@@ -1076,8 +1085,8 @@ class TextEditor extends Model
)
# Essential: For each selection, replace the selected text with a newline.
insertNewline: ->
@insertText('\n')
insertNewline: (options) ->
@insertText('\n', options)
# Essential: For each selection, if the selection is empty, delete the character
# following the cursor. Otherwise delete the selected text.
@@ -1740,10 +1749,14 @@ class TextEditor extends Model
# * `onlyNonEmpty` (optional) If `true`, the decoration will only be applied
# if the associated `DisplayMarker` is non-empty. Only applicable to the
# `gutter`, `line`, and `line-number` types.
# * `position` (optional) Only applicable to decorations of type `overlay` and `block`,
# controls where the view is positioned relative to the `TextEditorMarker`.
# * `position` (optional) Only applicable to decorations of type `overlay` and `block`.
# Controls where the view is positioned relative to the `TextEditorMarker`.
# Values can be `'head'` (the default) or `'tail'` for overlay decorations, and
# `'before'` (the default) or `'after'` for block decorations.
# * `avoidOverflow` (optional) Only applicable to decorations of type
# `overlay`. Determines whether the decoration adjusts its horizontal or
# vertical position to remain fully visible when it would otherwise
# overflow the editor. Defaults to `true`.
#
# Returns a {Decoration} object
decorateMarker: (marker, decorationParams) ->

View File

@@ -178,7 +178,8 @@ class ThemeManager
@requireStylesheet(nativeStylesheetPath)
stylesheetElementForId: (id) ->
document.head.querySelector("atom-styles style[source-path=\"#{id}\"]")
escapedId = id.replace(/\\/g, '\\\\')
document.head.querySelector("atom-styles style[source-path=\"#{escapedId}\"]")
resolveStylesheet: (stylesheetPath) ->
if path.extname(stylesheetPath).length > 0
@@ -231,9 +232,6 @@ class ThemeManager
applyStylesheet: (path, text) ->
@styleSheetDisposablesBySourcePath[path] = @styleManager.addStyleSheet(text, sourcePath: path)
stringToId: (string) ->
string.replace(/\\/g, '/')
activateThemes: ->
new Promise (resolve) =>
# @config.observe runs the callback once, then on subsequent changes.

View File

@@ -1,7 +1,7 @@
/** @babel */
import fs from 'fs'
import {spawnSync} from 'child_process'
import childProcess from 'child_process'
const ENVIRONMENT_VARIABLES_TO_PRESERVE = new Set([
'NODE_ENV',
@@ -15,12 +15,14 @@ const PLATFORMS_KNOWN_TO_WORK = new Set([
'linux'
])
function updateProcessEnv (launchEnv) {
async function updateProcessEnv (launchEnv) {
let envToAssign
if (launchEnv && shouldGetEnvFromShell(launchEnv)) {
envToAssign = getEnvFromShell(launchEnv)
} else if (launchEnv && launchEnv.PWD) {
envToAssign = launchEnv
if (launchEnv) {
if (shouldGetEnvFromShell(launchEnv)) {
envToAssign = await getEnvFromShell(launchEnv)
} else if (launchEnv.PWD) {
envToAssign = launchEnv
}
}
if (envToAssign) {
@@ -58,24 +60,64 @@ function shouldGetEnvFromShell (env) {
return true
}
function getEnvFromShell (env) {
if (!shouldGetEnvFromShell(env)) {
return
}
let {stdout} = spawnSync(env.SHELL, ['-ilc', 'command env'], {encoding: 'utf8'})
if (stdout) {
let result = {}
for (let line of stdout.split('\n')) {
if (line.includes('=')) {
let components = line.split('=')
let key = components.shift()
let value = components.join('=')
result[key] = value
async function getEnvFromShell (env) {
let {stdout, error} = await new Promise((resolve) => {
let child
let error
let stdout = ''
let done = false
const cleanup = () => {
if (!done && child) {
child.kill()
done = true
}
}
return result
process.once('exit', cleanup)
setTimeout(() => {
cleanup()
}, 5000)
child = childProcess.spawn(env.SHELL, ['-ilc', 'command env'], {encoding: 'utf8', detached: true, stdio: ['ignore', 'pipe', process.stderr]})
const buffers = []
child.on('error', (e) => {
done = true
error = e
})
child.stdout.on('data', (data) => {
buffers.push(data)
})
child.on('close', (code, signal) => {
done = true
process.removeListener('exit', cleanup)
if (buffers.length) {
stdout = Buffer.concat(buffers).toString('utf8')
}
resolve({stdout, error})
})
})
if (error) {
if (error.handle) {
error.handle()
}
console.log('warning: ' + env.SHELL + ' -ilc "command env" failed with signal (' + error.signal + ')')
console.log(error)
}
if (!stdout || stdout.trim() === '') {
return null
}
let result = {}
for (let line of stdout.split('\n')) {
if (line.includes('=')) {
let components = line.split('=')
let key = components.shift()
let value = components.join('=')
result[key] = value
}
}
return result
}
export default { updateProcessEnv, shouldGetEnvFromShell }

View File

@@ -441,7 +441,7 @@ class Workspace extends Model
# Avoid adding URLs as recent documents to work-around this Spotlight crash:
# https://github.com/atom/atom/issues/10071
if uri? and not url.parse(uri).protocol?
if uri? and (not url.parse(uri).protocol? or process.platform is 'win32')
@applicationDelegate.addRecentDocument(uri)
pane = @paneContainer.paneForURI(uri) if searchAllPanes

View File

@@ -116,14 +116,12 @@
})
}
var currentWindow = require('electron').remote.getCurrentWindow()
if (currentWindow.devToolsWebContents) {
const webContents = require('electron').remote.getCurrentWindow().webContents
if (webContents.devToolsWebContents) {
profile()
} else {
currentWindow.openDevTools()
currentWindow.once('devtools-opened', function () {
setTimeout(profile, 1000)
})
webContents.once('devtools-opened', () => { setTimeout(profile, 1000) })
webContents.openDevTools()
}
}