Merge branch 'master' into sm-hidden-inset

# Conflicts:
#	src/main-process/atom-application.coffee
This commit is contained in:
simurai
2016-10-15 19:45:50 +09:00
142 changed files with 1538 additions and 978 deletions

View File

@@ -1 +1 @@
2.7.6
2.7.12

View File

@@ -3,7 +3,7 @@
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
The following is a set of guidelines for contributing to Atom and its packages, which are hosted in the [Atom Organization](https://github.com/atom) on GitHub.
These are just guidelines, not rules, use your best judgment and feel free to propose changes to this document in a pull request.
These are just guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
#### Table Of Contents
@@ -71,12 +71,12 @@ Here's a list of the big ones:
There are many more, but this list should be a good starting point.
For more information on how to work with Atom's official packages, see [Contributing to Atom Packages](https://github.com/atom/atom/blob/master/docs/contributing-to-packages.md).
Also, because Atom is so extensible, it's possible that a feature you've become accustomed to in Atom or an issue you're encountering aren't coming from a bundled package at all, but rather a [community package](https://atom.io/packages) you've installed.
Also, because Atom is so extensible, it's possible that a feature you've become accustomed to in Atom or an issue you're encountering isn't coming from a bundled package at all, but rather a [community package](https://atom.io/packages) you've installed.
Each community package has its own repository too, and you should be able to find it in Settings > Packages for the packages you installed and contribute there.
### Design Decisions
When we make a significant decision in how we maintain the project and what we can or cannot support, we will be documenting them in the [atom/design-decisions repository](https://github.com/atom/design-decisions). If you have a question around how we do things, check to see if it is documented there. If it is *not* documented there, please open a new topic on [Discuss, the official Atom message board](https://discuss.atom.io) and ask your question.
When we make a significant decision in how we maintain the project and what we can or cannot support, we will document it in the [atom/design-decisions repository](https://github.com/atom/design-decisions). If you have a question around how we do things, check to see if it is documented there. If it is *not* documented there, please open a new topic on [Discuss, the official Atom message board](https://discuss.atom.io) and ask your question.
## How Can I Contribute?
@@ -232,9 +232,7 @@ If you want to read about using Atom or developing packages in Atom, the [Atom F
### Pull Requests
* Include screenshots and animated GIFs in your pull request whenever possible.
* Follow the [CoffeeScript](#coffeescript-styleguide),
[JavaScript](https://github.com/styleguide/javascript),
and [CSS](https://github.com/styleguide/css) styleguides.
* Follow the [JavaScript](#javascript-styleguide) and [CoffeeScript](#coffeescript-styleguide) styleguides.
* Include thoughtfully-worded, well-structured
[Jasmine](http://jasmine.github.io/) specs in the `./spec` folder. Run them using `apm test`. See the [Specs Styleguide](#specs-styleguide) below.
* Document new code based on the

View File

@@ -1,4 +1,4 @@
Copyright (c) 2016 GitHub Inc.
Copyright (c) 2014 GitHub Inc.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -45,7 +45,7 @@ the latest version of Atom.
### Debian Linux (Ubuntu)
Currently only a 64-bit version is available.
Atom is only available for 64-bit Linux systems.
1. Download `atom-amd64.deb` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
2. Run `sudo dpkg --install atom-amd64.deb` on the downloaded package.
@@ -56,7 +56,7 @@ repeat these steps to upgrade to future releases.
### Red Hat Linux (Fedora 21 and under, CentOS, Red Hat)
Currently only a 64-bit version is available.
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 yum localinstall atom.x86_64.rpm` on the downloaded package.
@@ -67,7 +67,7 @@ repeat these steps to upgrade to future releases.
### Fedora 22+
Currently only a 64-bit version is available.
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.
@@ -83,8 +83,7 @@ An archive is available for people who don't want to install `atom` as root.
This version enables you to install multiple Atom versions in parallel. It has been built on Ubuntu 64-bit,
but should be compatible with other Linux distributions.
1. Install dependencies (on Ubuntu): `sudo apt install git gconf2 gconf-service libgtk2.0-0 libudev1 libgcrypt20
libnotify4 libxtst6 libnss3 python gvfs-bin xdg-utils libcap2`
1. Install dependencies (on Ubuntu): `sudo apt install git gconf2 gconf-service libgtk2.0-0 libudev1 libgcrypt20 libnotify4 libxtst6 libnss3 python gvfs-bin xdg-utils libcap2`
2. Download `atom-amd64.tar.gz` from the [Atom releases page](https://github.com/atom/atom/releases/latest).
3. Run `tar xf atom-amd64.tar.gz` in the directory where you want to extract the Atom folder.
4. Launch Atom using the installed `atom` command from the newly extracted directory.

View File

@@ -28,7 +28,7 @@ while getopts ":wtfvh-:" opt; do
REDIRECT_STDERR=1
EXPECT_OUTPUT=1
;;
foreground|test)
foreground|benchmark|benchmark-test|test)
EXPECT_OUTPUT=1
;;
esac

View File

@@ -0,0 +1,73 @@
/** @babel */
import Chart from 'chart.js'
import glob from 'glob'
import fs from 'fs-plus'
import path from 'path'
export default async function ({test, benchmarkPaths}) {
document.body.style.backgroundColor = '#ffffff'
document.body.style.overflow = 'auto'
let paths = []
for (const benchmarkPath of benchmarkPaths) {
if (fs.isDirectorySync(benchmarkPath)) {
paths = paths.concat(glob.sync(path.join(benchmarkPath, '**', '*.bench.js')))
} else {
paths.push(benchmarkPath)
}
}
while (paths.length > 0) {
const benchmark = require(paths.shift())({test})
let results
if (benchmark instanceof Promise) {
results = await benchmark
} else {
results = benchmark
}
const dataByBenchmarkName = {}
for (const {name, duration, x} of results) {
dataByBenchmarkName[name] = dataByBenchmarkName[name] || {points: []}
dataByBenchmarkName[name].points.push({x, y: duration})
}
const benchmarkContainer = document.createElement('div')
document.body.appendChild(benchmarkContainer)
for (const key in dataByBenchmarkName) {
const data = dataByBenchmarkName[key]
if (data.points.length > 1) {
const canvas = document.createElement('canvas')
benchmarkContainer.appendChild(canvas)
const chart = new Chart(canvas, {
type: 'line',
data: {
datasets: [{label: key, fill: false, data: data.points}]
},
options: {
showLines: false,
scales: {xAxes: [{type: 'linear', position: 'bottom'}]}
}
})
const textualOutput = `${key}:\n\n` + data.points.map((p) => `${p.x}\t${p.y}`).join('\n')
console.log(textualOutput)
} else {
const title = document.createElement('h2')
title.textContent = key
benchmarkContainer.appendChild(title)
const duration = document.createElement('p')
duration.textContent = `${data.points[0].y}ms`
benchmarkContainer.appendChild(duration)
const textualOutput = `${key}: ${data.points[0].y}`
console.log(textualOutput)
}
global.atom.reset()
}
}
return 0
}

View File

@@ -0,0 +1,90 @@
/** @babel */
import {TextEditor, TextBuffer} from 'atom'
const MIN_SIZE_IN_KB = 0 * 1024
const MAX_SIZE_IN_KB = 10 * 1024
const SIZE_STEP_IN_KB = 1024
const LINE_TEXT = 'Lorem ipsum dolor sit amet\n'
const TEXT = LINE_TEXT.repeat(Math.ceil(MAX_SIZE_IN_KB * 1024 / LINE_TEXT.length))
export default async function ({test}) {
const data = []
const workspaceElement = atom.views.getView(atom.workspace)
document.body.appendChild(workspaceElement)
atom.packages.loadPackages()
await atom.packages.activate()
for (let pane of atom.workspace.getPanes()) {
pane.destroy()
}
for (let sizeInKB = MIN_SIZE_IN_KB; sizeInKB < MAX_SIZE_IN_KB; sizeInKB += SIZE_STEP_IN_KB) {
const text = TEXT.slice(0, sizeInKB * 1024)
console.log(text.length / 1024)
let t0 = window.performance.now()
const buffer = new TextBuffer(text)
const editor = new TextEditor({buffer, largeFileMode: true})
atom.workspace.getActivePane().activateItem(editor)
let t1 = window.performance.now()
data.push({
name: 'Opening a large file',
x: sizeInKB,
duration: t1 - t0
})
const tickDurations = []
for (let i = 0; i < 20; i++) {
await timeout(50)
t0 = window.performance.now()
await timeout(0)
t1 = window.performance.now()
tickDurations[i] = t1 - t0
}
data.push({
name: 'Max time event loop was blocked after opening a large file',
x: sizeInKB,
duration: Math.max(...tickDurations)
})
t0 = window.performance.now()
editor.setCursorScreenPosition(editor.element.screenPositionForPixelPosition({
top: 100,
left: 30
}))
t1 = window.performance.now()
data.push({
name: 'Clicking the editor after opening a large file',
x: sizeInKB,
duration: t1 - t0
})
t0 = window.performance.now()
editor.element.setScrollTop(editor.element.getScrollTop() + 100)
t1 = window.performance.now()
data.push({
name: 'Scrolling down after opening a large file',
x: sizeInKB,
duration: t1 - t0
})
editor.destroy()
buffer.destroy()
await timeout(10000)
}
workspaceElement.remove()
return data
}
function timeout (duration) {
return new Promise((resolve) => setTimeout(resolve, duration))
}

View File

@@ -7,9 +7,6 @@ machine:
xcode:
version: 7.3
post:
- osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver
general:
artifacts:
- out/atom-mac.zip
@@ -36,6 +33,7 @@ dependencies:
test:
override:
- script/lint
- osascript -e 'tell application "System Events" to keystroke "x"' # clear screen saver
- caffeinate -s script/test # Run with caffeinate to prevent screen saver
experimental:

View File

@@ -37,7 +37,7 @@
| 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.png?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) |
| 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) |
@@ -62,7 +62,7 @@
| Library | macOS | Windows | Dependencies |
|---------|------|---------|--------------|
| Clear Cut | [![macOS Build Status](https://travis-ci.org/atom/clear-cut.png?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) |
| 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) |
@@ -107,6 +107,6 @@
| 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.png?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.png?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) |
| 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) |

View File

@@ -19,7 +19,7 @@
## Instructions
You can run these commands using Command Prompt, PowerShell or Git Shell via [GitHub Desktop](https://desktop.github.com/). These instructions will assume the use of Command Prompt.
You can run these commands using Command Prompt, PowerShell, Git Shell, or any other terminal. These instructions will assume the use of Command Prompt.
```
cd C:\
@@ -36,28 +36,18 @@ To also install the newly built application, use `script\build --create-windows-
* `--create-windows-installer`: creates an `.msi`, an `.exe` and a `.nupkg` installer in the `out/` directory.
* `--install`: installs the application in `%LOCALAPPDATA%\Atom\app-dev\`.
## Do I have to use GitHub Desktop?
No, you can use your existing Git! GitHub Desktop's Git Shell is just easier to set up.
If you _prefer_ using your existing Git installation, make sure git's cmd directory is in your PATH env variable (e.g. `C:\Program Files (x86)\Git\cmd`) before you open your PowerShell or Command Prompt.
It is also recommended you open your Command Prompt or PowerShell as Administrator.
If none of this works, do install Github Desktop and use its Git Shell as it makes life easier.
## Troubleshooting
### Common Errors
* `node is not recognized`
* If you just installed Node.js, you'll need to restart your PowerShell/Command Prompt/Git Shell 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`
* Ensure you have Visual C++ support installed. Go into Add/Remove Programs, select Visual Studio and press Modify and then check the Visual C++ box.
* 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.
* `script\build` stop 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. e.g. use `c:\atom` and not `c:\my stuff\atom`
* 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.
@@ -77,7 +67,7 @@ If none of this works, do install Github Desktop and use its Git Shell as it mak
* 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 you are running and then `script\clean` followed by `script\build` (re-open your command prompt or Powershell window if you set it 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.

View File

@@ -3,8 +3,6 @@
import TextBuffer, {Point, Range} from 'text-buffer'
import {File, Directory} from 'pathwatcher'
import {Emitter, Disposable, CompositeDisposable} from 'event-kit'
import Grim from 'grim'
import dedent from 'dedent'
import BufferedNodeProcess from '../src/buffered-node-process'
import BufferedProcess from '../src/buffered-process'
import GitRepository from '../src/git-repository'
@@ -39,25 +37,7 @@ if (process.platform === 'win32') {
// only be exported when not running as a child node process
if (process.type === 'renderer') {
atomExport.Task = require('../src/task')
const TextEditor = (params) => {
return atom.workspace.buildTextEditor(params)
}
TextEditor.prototype = require('../src/text-editor').prototype
Object.defineProperty(atomExport, 'TextEditor', {
enumerable: true,
get () {
Grim.deprecate(dedent`
The \`TextEditor\` constructor is no longer public.
To construct a text editor, use \`atom.workspace.buildTextEditor()\`.
To check if an object is a text editor, use \`atom.workspace.isTextEditor(object)\`.
`)
return TextEditor
}
})
atomExport.TextEditor = require('../src/text-editor')
}
export default atomExport

View File

@@ -133,6 +133,20 @@
'cmd-ctrl-left': 'editor:move-selection-left'
'cmd-ctrl-right': 'editor:move-selection-right'
# Emacs
'alt-f': 'editor:move-to-end-of-word'
'alt-ctrl-f': 'editor:move-to-next-subword-boundary'
'alt-F': 'editor:select-to-end-of-word'
'alt-ctrl-F': 'editor:select-to-next-subword-boundary'
'alt-b': 'editor:move-to-beginning-of-word'
'alt-ctrl-b': 'editor:move-to-previous-subword-boundary'
'alt-B': 'editor:select-to-beginning-of-word'
'alt-ctrl-B': 'editor:select-to-previous-subword-boundary'
'alt-h': 'editor:delete-to-beginning-of-word'
'alt-ctrl-h': 'editor:delete-to-beginning-of-subword'
'alt-d': 'editor:delete-to-end-of-word'
'alt-ctrl-d': 'editor:delete-to-end-of-subword'
# Sublime Parity
'cmd-a': 'core:select-all'
'cmd-alt-p': 'editor:log-cursor-scope'

View File

@@ -1,13 +0,0 @@
'atom-text-editor':
'alt-f': 'editor:move-to-end-of-word'
'alt-ctrl-f': 'editor:move-to-next-subword-boundary'
'alt-F': 'editor:select-to-end-of-word'
'alt-ctrl-F': 'editor:select-to-next-subword-boundary'
'alt-b': 'editor:move-to-beginning-of-word'
'alt-ctrl-b': 'editor:move-to-previous-subword-boundary'
'alt-B': 'editor:select-to-beginning-of-word'
'alt-ctrl-B': 'editor:select-to-previous-subword-boundary'
'alt-h': 'editor:delete-to-beginning-of-word'
'alt-ctrl-h': 'editor:delete-to-beginning-of-subword'
'alt-d': 'editor:delete-to-end-of-word'
'alt-ctrl-d': 'editor:delete-to-end-of-subword'

View File

@@ -13,7 +13,7 @@
'left': 'core:move-left'
'right': 'core:move-right'
'ctrl-alt-r': 'window:reload'
'ctrl-alt-i': 'window:toggle-dev-tools'
'ctrl-shift-i': 'window:toggle-dev-tools'
'ctrl-alt-p': 'window:run-package-specs'
'ctrl-shift-o': 'application:open-folder'
'ctrl-alt-o': 'application:add-project-folder'

View File

@@ -147,6 +147,7 @@
{ label: 'Open In Dev Mode…', command: 'application:open-dev' }
{ label: 'Reload Window', command: 'window:reload' }
{ label: 'Run Package Specs', command: 'window:run-package-specs' }
{ label: 'Run Benchmarks', command: 'window:run-benchmarks' }
{ label: 'Toggle Developer Tools', command: 'window:toggle-dev-tools' }
]
}

View File

@@ -1,7 +1,7 @@
{
"name": "atom",
"productName": "Atom",
"version": "1.12.0-dev",
"version": "1.13.0-dev",
"description": "A hackable text editor for the 21st Century.",
"main": "./src/main-process/main.js",
"repository": {
@@ -15,23 +15,25 @@
"electronVersion": "1.3.6",
"dependencies": {
"async": "0.2.6",
"atom-keymap": "6.3.5",
"atom-keymap": "7.0.5",
"atom-ui": "0.4.1",
"babel-core": "5.8.38",
"cached-run-in-this-context": "0.4.1",
"chai": "3.5.0",
"chart.js": "^2.3.0",
"clear-cut": "^2.0.1",
"coffee-script": "1.8.0",
"coffee-script": "1.11.1",
"color": "^0.7.3",
"dedent": "^0.6.0",
"devtron": "1.1.0",
"devtron": "1.3.0",
"event-kit": "^2.1.0",
"find-parent-dir": "^0.3.0",
"first-mate": "6.0.0",
"fs-plus": "2.9.1",
"first-mate": "6.1.0",
"fs-plus": "2.9.2",
"fstream": "0.1.24",
"fuzzaldrin": "^2.1",
"git-utils": "^4.1.2",
"glob": "^7.1.1",
"grim": "1.5.0",
"jasmine-json": "~0.0",
"jasmine-tagged": "^1.1.4",
@@ -52,13 +54,13 @@
"scandal": "^2.2.1",
"scoped-property-store": "^0.17.0",
"scrollbar-style": "^3.2",
"season": "^5.3",
"season": "^5.4.1",
"semver": "^4.3.3",
"service-hub": "^0.7.0",
"service-hub": "^0.7.2",
"sinon": "1.17.4",
"source-map-support": "^0.3.2",
"temp": "0.8.1",
"text-buffer": "9.2.12",
"text-buffer": "9.4.0",
"typescript-simple": "1.0.0",
"underscore-plus": "^1.6.6",
"winreg": "^1.2.1",
@@ -71,89 +73,89 @@
"atom-light-ui": "0.45.0",
"base16-tomorrow-dark-theme": "1.3.0",
"base16-tomorrow-light-theme": "1.3.0",
"one-dark-ui": "1.6.1",
"one-light-ui": "1.6.1",
"one-dark-syntax": "1.4.0",
"one-light-syntax": "1.4.0",
"solarized-dark-syntax": "1.0.3",
"solarized-light-syntax": "1.0.3",
"one-dark-ui": "1.6.2",
"one-light-ui": "1.6.2",
"one-dark-syntax": "1.5.0",
"one-light-syntax": "1.5.0",
"solarized-dark-syntax": "1.0.5",
"solarized-light-syntax": "1.0.5",
"about": "1.7.0",
"archive-view": "0.61.1",
"archive-view": "0.62.0",
"autocomplete-atom-api": "0.10.0",
"autocomplete-css": "0.11.2",
"autocomplete-css": "0.13.1",
"autocomplete-html": "0.7.2",
"autocomplete-plus": "2.31.3",
"autocomplete-plus": "2.32.0",
"autocomplete-snippets": "1.11.0",
"autoflow": "0.27.0",
"autosave": "0.23.1",
"background-tips": "0.26.1",
"bookmarks": "0.42.0",
"bracket-matcher": "0.82.2",
"command-palette": "0.38.0",
"command-palette": "0.39.0",
"deprecation-cop": "0.54.1",
"dev-live-reload": "0.47.0",
"encoding-selector": "0.22.0",
"exception-reporting": "0.40.0",
"find-and-replace": "0.201.1",
"find-and-replace": "0.202.1",
"fuzzy-finder": "1.4.0",
"git-diff": "1.1.0",
"go-to-line": "0.31.0",
"grammar-selector": "0.48.2",
"image-view": "0.59.0",
"image-view": "0.60.0",
"incompatible-packages": "0.26.1",
"keybinding-resolver": "0.35.0",
"line-ending-selector": "0.5.0",
"link": "0.31.2",
"markdown-preview": "0.158.7",
"markdown-preview": "0.158.8",
"metrics": "1.0.0",
"notifications": "0.65.1",
"open-on-github": "1.2.1",
"package-generator": "1.0.1",
"settings-view": "0.243.0",
"settings-view": "0.243.1",
"snippets": "1.0.3",
"spell-check": "0.68.2",
"status-bar": "1.4.1",
"spell-check": "0.68.4",
"status-bar": "1.6.0",
"styleguide": "0.47.2",
"symbols-view": "0.113.1",
"tabs": "0.101.1",
"tabs": "0.103.0",
"timecop": "0.33.2",
"tree-view": "0.209.3",
"tree-view": "0.210.0",
"update-package-dependencies": "0.10.0",
"welcome": "0.35.1",
"whitespace": "0.33.0",
"whitespace": "0.35.0",
"wrap-guide": "0.38.2",
"language-c": "0.53.1",
"language-clojure": "0.21.0",
"language-coffee-script": "0.47.2",
"language-c": "0.54.0",
"language-clojure": "0.22.1",
"language-coffee-script": "0.48.0",
"language-csharp": "0.12.1",
"language-css": "0.39.0",
"language-css": "0.40.1",
"language-gfm": "0.88.0",
"language-git": "0.15.0",
"language-go": "0.42.1",
"language-html": "0.45.1",
"language-hyperlink": "0.16.0",
"language-go": "0.43.0",
"language-html": "0.46.1",
"language-hyperlink": "0.16.1",
"language-java": "0.24.0",
"language-javascript": "0.120.0",
"language-json": "0.18.2",
"language-less": "0.29.5",
"language-javascript": "0.122.0",
"language-json": "0.18.3",
"language-less": "0.29.6",
"language-make": "0.22.2",
"language-mustache": "0.13.0",
"language-objective-c": "0.15.1",
"language-perl": "0.36.0",
"language-php": "0.37.2",
"language-perl": "0.37.0",
"language-php": "0.37.3",
"language-property-list": "0.8.0",
"language-python": "0.45.0",
"language-ruby": "0.70.1",
"language-python": "0.45.1",
"language-ruby": "0.70.2",
"language-ruby-on-rails": "0.25.1",
"language-sass": "0.56.0",
"language-shellscript": "0.22.5",
"language-sass": "0.57.0",
"language-shellscript": "0.23.0",
"language-source": "0.9.0",
"language-sql": "0.24.0",
"language-sql": "0.25.0",
"language-text": "0.7.1",
"language-todo": "0.29.0",
"language-toml": "0.18.0",
"language-xml": "0.34.10",
"language-yaml": "0.27.0"
"language-todo": "0.29.1",
"language-toml": "0.18.1",
"language-xml": "0.34.12",
"language-yaml": "0.27.1"
},
"private": true,
"scripts": {
@@ -161,8 +163,6 @@
"test": "node script/test"
},
"standard": {
"ignore": [],
"parser": "babel-eslint",
"globals": [
"atom",
"afterEach",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 629 KiB

After

Width:  |  Height:  |  Size: 355 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 907 B

After

Width:  |  Height:  |  Size: 838 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 119 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 601 KiB

After

Width:  |  Height:  |  Size: 325 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 905 B

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 184 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 KiB

After

Width:  |  Height:  |  Size: 357 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

After

Width:  |  Height:  |  Size: 851 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -5,14 +5,16 @@ SET WAIT=
SET PSARGS=%*
FOR %%a IN (%*) DO (
IF /I "%%a"=="-f" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--foreground" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-h" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--help" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-t" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--test" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-v" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--version" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-f" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--foreground" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-h" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--help" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-t" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--test" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--benchmark" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--benchmark-test" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-v" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="--version" SET EXPECT_OUTPUT=YES
IF /I "%%a"=="-w" (
SET EXPECT_OUTPUT=YES
SET WAIT=YES

View File

@@ -10,7 +10,8 @@ require('./bootstrap')
require('coffee-script/register')
require('colors')
const argv = require('yargs')
const yargs = require('yargs')
const argv = yargs
.usage('Usage: $0 [options]')
.help('help')
.describe('code-sign', 'Code-sign executables (macOS and Windows only)')
@@ -19,6 +20,7 @@ const argv = require('yargs')
.describe('create-rpm-package', 'Create .rpm package (Linux only)')
.describe('compress-artifacts', 'Compress Atom binaries (and symbols on macOS)')
.describe('install', 'Install Atom')
.wrap(yargs.terminalWidth())
.argv
const cleanOutputDirectory = require('./lib/clean-output-directory')

View File

@@ -12,6 +12,7 @@ const includePathInPackagedApp = require('./include-path-in-packaged-app')
module.exports = function () {
console.log(`Copying assets to ${CONFIG.intermediateAppPath}`);
let srcPaths = [
path.join(CONFIG.repositoryRootPath, 'benchmarks', 'benchmark-runner.js'),
path.join(CONFIG.repositoryRootPath, 'dot-atom'),
path.join(CONFIG.repositoryRootPath, 'exports'),
path.join(CONFIG.repositoryRootPath, 'node_modules'),

View File

@@ -6,6 +6,7 @@ const fs = require('fs-extra')
const glob = require('glob')
const os = require('os')
const path = require('path')
const spawnSync = require('./spawn-sync')
const CONFIG = require('../config')
@@ -21,7 +22,8 @@ module.exports = function (packagedAppPath, codeSign) {
}
const certPath = path.join(os.tmpdir(), 'win.p12')
if (codeSign && process.env.WIN_P12KEY_URL) {
const signing = codeSign && process.env.WIN_P12KEY_URL
if (signing) {
downloadFileFromGithub(process.env.WIN_P12KEY_URL, certPath)
options.certificateFile = certPath
options.certificatePassword = process.env.WIN_P12KEY_PASSWORD
@@ -42,9 +44,30 @@ module.exports = function (packagedAppPath, codeSign) {
}
}
}
// Squirrel signs its own copy of the executables but we need them for the portable ZIP
const extractSignedExes = function() {
if (signing) {
for (let nupkgPath of glob.sync(`${CONFIG.buildOutputPath}/*-full.nupkg`)) {
if (nupkgPath.includes(CONFIG.appMetadata.version)) {
console.log(`Extracting signed executables from ${nupkgPath} for use in portable zip`)
var atomOutPath = path.join(path.dirname(packagedAppPath), 'Atom')
spawnSync('7z.exe', ['e', nupkgPath, 'lib\\net45\\*.exe', '-aoa'], {cwd: atomOutPath})
spawnSync(process.env.COMSPEC, ['/c', `move /y ${path.join(atomOutPath, 'squirrel.exe')} ${path.join(atomOutPath, 'update.exe')}`])
return
}
}
}
}
console.log(`Creating Windows Installer for ${packagedAppPath}`)
return electronInstaller.createWindowsInstaller(options).then(cleanUp, function (error) {
console.log(`Windows installer creation failed:\n${error}`)
cleanUp()
})
return electronInstaller.createWindowsInstaller(options)
.then(extractSignedExes, function (error) {
console.log(`Extracting signed executables failed:\n${error}`)
cleanUp()
})
.then(cleanUp, function (error) {
console.log(`Windows installer creation failed:\n${error}`)
cleanUp()
})
}

View File

@@ -25,6 +25,7 @@ module.exports = function () {
function getPathsToTranspile () {
let paths = []
paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'benchmarks', '**', '*.js')))
paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'exports', '**', '*.js')))
paths = paths.concat(glob.sync(path.join(CONFIG.intermediateAppPath, 'src', '**', '*.js')))
for (let packageName of Object.keys(CONFIG.appMetadata.packageDependencies)) {

View File

@@ -4,7 +4,6 @@
"dependencies": {
"async": "2.0.1",
"babel-core": "5.8.38",
"babel-eslint": "6.1.2",
"coffeelint": "1.15.7",
"colors": "1.1.2",
"csslint": "1.0.2",
@@ -24,7 +23,7 @@
"runas": "3.1.1",
"season": "5.3.0",
"semver": "5.3.0",
"standard": "6.0.0",
"standard": "8.4.0",
"sync-request": "3.0.1",
"tello": "1.0.5",
"webdriverio": "2.4.5",

View File

@@ -83,9 +83,19 @@ for (let packageName in CONFIG.appMetadata.packageDependencies) {
})
}
function runBenchmarkTests (callback) {
const benchmarksPath = path.join(CONFIG.repositoryRootPath, 'benchmarks')
const testArguments = ['--benchmark-test', benchmarksPath]
console.log('Executing benchmark tests'.bold.green)
const cp = childProcess.spawn(executablePath, testArguments, {stdio: 'inherit'})
cp.on('error', error => { callback(error) })
cp.on('close', exitCode => { callback(null, exitCode) })
}
let testSuitesToRun
if (process.platform === 'darwin') {
testSuitesToRun = [runCoreMainProcessTests, runCoreRenderProcessTests].concat(packageTestSuites)
testSuitesToRun = [runCoreMainProcessTests, runCoreRenderProcessTests, runBenchmarkTests].concat(packageTestSuites)
} else {
testSuitesToRun = [runCoreMainProcessTests]
}

View File

@@ -29,23 +29,20 @@ export function afterEach (fn) {
}
})
export function conditionPromise (condition) {
const timeoutError = new Error("Timed out waiting on condition")
Error.captureStackTrace(timeoutError, conditionPromise)
export async function conditionPromise (condition) {
const startTime = Date.now()
return new Promise(function (resolve, reject) {
const interval = global.setInterval(function () {
if (condition()) {
global.clearInterval(interval)
global.clearTimeout(timeout)
resolve()
}
}, 100)
const timeout = global.setTimeout(function () {
global.clearInterval(interval)
reject(timeoutError)
}, 5000)
})
while (true) {
await timeoutPromise(100)
if (await condition()) {
return
}
if (Date.now() - startTime > 5000) {
throw new Error("Timed out waiting on condition")
}
}
}
export function timeoutPromise (timeout) {

View File

@@ -1,8 +1,6 @@
_ = require 'underscore-plus'
path = require 'path'
temp = require 'temp'
Package = require '../src/package'
ThemeManager = require '../src/theme-manager'
AtomEnvironment = require '../src/atom-environment'
StorageFolder = require '../src/storage-folder'
@@ -392,8 +390,9 @@ describe "AtomEnvironment", ->
describe "when the opened path is a uri", ->
it "adds it to the project's paths as is", ->
pathToOpen = 'remote://server:7644/some/dir/path'
spyOn(atom.project, 'addPath')
atom.openLocations([{pathToOpen}])
expect(atom.project.getPaths()[0]).toBe pathToOpen
expect(atom.project.addPath).toHaveBeenCalledWith(pathToOpen)
describe "::updateAvailable(info) (called via IPC from browser process)", ->
subscription = null

View File

@@ -1,6 +1,5 @@
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
AtomPortable = require '../src/main-process/atom-portable'
portableModeCommonPlatformBehavior = (platform) ->

View File

@@ -3,6 +3,7 @@ _ = require 'underscore-plus'
grim = require 'grim'
marked = require 'marked'
listen = require '../src/delegated-listener'
ipcHelpers = require '../src/ipc-helpers'
formatStackTrace = (spec, message='', stackTrace) ->
return stackTrace unless stackTrace
@@ -173,7 +174,7 @@ class AtomReporter
listen document, 'click', '.stack-trace', (event) ->
event.currentTarget.classList.toggle('expanded')
@reloadButton.addEventListener('click', -> require('electron').ipcRenderer.send('call-window-method', 'reload'))
@reloadButton.addEventListener('click', -> ipcHelpers.call('window-method', 'reload'))
updateSpecCounts: ->
if @skippedCount

View File

@@ -17,7 +17,7 @@ describe 'CompileCache', ->
CompileCache.resetCacheStats()
spyOn(Babel, 'transform').andReturn {code: 'the-babel-code'}
spyOn(CoffeeScript, 'compile').andReturn {js: 'the-coffee-code', v3SourceMap: "{}"}
spyOn(CoffeeScript, 'compile').andReturn 'the-coffee-code'
spyOn(TypeScriptSimple::, 'compile').andReturn 'the-typescript-code'
afterEach ->

View File

@@ -1,5 +1,4 @@
DecorationManager = require '../src/decoration-manager'
_ = require 'underscore-plus'
describe "DecorationManager", ->
[decorationManager, buffer, defaultMarkerLayer] = []

View File

@@ -0,0 +1,47 @@
'use strict'
class FakeRemoteDirectory {
constructor (uri) {
this.uri = uri
}
relativize (uri) {
return uri
}
getPath () {
return this.uri
}
isRoot () {
return true
}
getSubdirectory () {
return {
existsSync () {
return false
}
}
}
existsSync () {
return true
}
contains () {
return false
}
}
exports.provideDirectoryProvider = function () {
return {
name: 'directory provider from package-with-directory-provider',
directoryForURISync (uri) {
if (uri.startsWith('remote://')) {
return new FakeRemoteDirectory(uri)
}
}
}
}

View File

@@ -0,0 +1,12 @@
{
"name": "package-with-directory-provider",
"providedServices": {
"atom.directory-provider": {
"description": "Provides custom Directory instances",
"versions": {
"0.1.1": "provideDirectoryProvider"
}
}
}
}

View File

@@ -2,7 +2,6 @@ temp = require 'temp'
GitRepository = require '../src/git-repository'
fs = require 'fs-plus'
path = require 'path'
Task = require '../src/task'
Project = require '../src/project'
copyRepository = ->
@@ -195,7 +194,7 @@ describe "GitRepository", ->
expect(repo.isStatusModified(repo.getDirectoryStatus(directoryPath))).toBe true
describe ".refreshStatus()", ->
[newPath, modifiedPath, cleanPath, originalModifiedPathText, workingDirectory] = []
[newPath, modifiedPath, cleanPath, workingDirectory] = []
beforeEach ->
workingDirectory = copyRepository()

View File

@@ -1,5 +1,4 @@
Grim = require 'grim'
_ = require 'underscore-plus'
fs = require 'fs-plus'
path = require 'path'
{ipcRenderer} = require 'electron'

View File

@@ -1,6 +1,5 @@
LinesYardstick = require '../src/lines-yardstick'
LineTopIndex = require 'line-top-index'
{toArray} = require 'underscore-plus'
{Point} = require 'text-buffer'
describe "LinesYardstick", ->
@@ -15,8 +14,6 @@ describe "LinesYardstick", ->
runs ->
createdLineNodes = []
availableScreenRows = {}
screenRowsToMeasure = []
buildLineNode = (screenRow) ->
startIndex = 0
@@ -43,11 +40,13 @@ describe "LinesYardstick", ->
mockLineNodesProvider =
lineNodesById: {}
lineIdForScreenRow: (screenRow) ->
editor.screenLineForScreenRow(screenRow).id
editor.screenLineForScreenRow(screenRow)?.id
lineNodeForScreenRow: (screenRow) ->
@lineNodesById[@lineIdForScreenRow(screenRow)] ?= buildLineNode(screenRow)
if id = @lineIdForScreenRow(screenRow)
@lineNodesById[id] ?= buildLineNode(screenRow)
textNodesForScreenRow: (screenRow) ->
lineNode = @lineNodeForScreenRow(screenRow)

View File

@@ -188,6 +188,8 @@ describe('AtomApplication', function () {
reusedWindow = atomApplication.launch(parseCommandLine([dirBPath, '-a']))
assert.equal(reusedWindow, window1)
assert.deepEqual(atomApplication.windows, [window1])
await conditionPromise(async () => (await getTreeViewRootDirectories(reusedWindow)).length === 3)
assert.deepEqual(await getTreeViewRootDirectories(window1), [dirAPath, dirCPath, dirBPath])
})
@@ -246,7 +248,7 @@ describe('AtomApplication', function () {
const reusedWindow = atomApplication.launch(parseCommandLine([tempDirPath]))
assert.equal(reusedWindow, window1)
assert.deepEqual(await getTreeViewRootDirectories(window1), [tempDirPath])
await conditionPromise(async () => (await getTreeViewRootDirectories(reusedWindow)).length > 0)
})
it('opens a new window with a single untitled buffer when launched with no path, even if windows already exist', async function () {
@@ -303,33 +305,33 @@ describe('AtomApplication', function () {
assert.deepEqual(await getTreeViewRootDirectories(window), [path.dirname(newFilePath)])
})
it('opens an empty text editor and loads its parent directory in the tree-view when launched with a new file path in a remote directory', async function () {
// Disable the tree-view because it will try to enumerate the contents of
// the remote directory and, since it doesn't exist, throw an error.
const configPath = path.join(process.env.ATOM_HOME, 'config.cson')
const config = season.readFileSync(configPath)
if (!config['*'].core) config['*'].core = {}
config['*'].core.disabledPackages = ['tree-view']
season.writeFileSync(configPath, config)
it('adds a remote directory to the project when launched with a remote directory', async 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'))
const atomApplication = buildAtomApplication()
const newRemoteFilePath = 'remote://server:3437/some/directory/path'
const window = atomApplication.launch(parseCommandLine([newRemoteFilePath]))
atomApplication.config.set('core.disabledPackages', ['fuzzy-finder'])
const remotePath = 'remote://server:3437/some/directory/path'
let window = atomApplication.launch(parseCommandLine([remotePath]))
await focusWindow(window)
const {projectPaths, editorTitle, editorText} = await evalInWebContents(window.browserWindow.webContents, function (sendBackToMainProcess) {
atom.workspace.observeActivePaneItem(function (editor) {
if (editor) {
sendBackToMainProcess({
projectPaths: atom.project.getPaths(),
editorTitle: editor.getTitle(),
editorText: editor.getText()
})
}
await conditionPromise(async () => (await getProjectDirectories()).length > 0)
let directories = await getProjectDirectories()
assert.deepEqual(directories, [{type: 'FakeRemoteDirectory', path: remotePath}])
await window.reload()
await focusWindow(window)
directories = await getProjectDirectories()
assert.deepEqual(directories, [{type: 'FakeRemoteDirectory', path: remotePath}])
function getProjectDirectories () {
return evalInWebContents(window.browserWindow.webContents, function (sendBackToMainProcess) {
sendBackToMainProcess(atom.project.getDirectories().map(d => ({ type: d.constructor.name, path: d.getPath() })))
})
})
assert.deepEqual(projectPaths, [newRemoteFilePath])
assert.equal(editorTitle, path.basename(newRemoteFilePath))
assert.equal(editorText, '')
}
})
it('reopens any previously opened windows when launched with no path', async function () {
@@ -342,6 +344,9 @@ describe('AtomApplication', function () {
const app1Window2 = atomApplication1.launch(parseCommandLine([tempDirPath2]))
await app1Window2.loadedPromise
await app1Window1.saveState()
await app1Window2.saveState()
const atomApplication2 = buildAtomApplication()
const [app2Window1, app2Window2] = atomApplication2.launch(parseCommandLine([]))
await app2Window1.loadedPromise

View File

@@ -31,6 +31,19 @@ describe "PackageManager", ->
it "returns the value of the core.apmPath config setting", ->
expect(atom.packages.getApmPath()).toBe "/path/to/apm"
describe "::loadPackages()", ->
beforeEach ->
spyOn(atom.packages, 'loadPackage')
afterEach ->
atom.packages.deactivatePackages()
atom.packages.unloadPackages()
it "sets hasLoadedInitialPackages", ->
expect(atom.packages.hasLoadedInitialPackages()).toBe false
atom.packages.loadPackages()
expect(atom.packages.hasLoadedInitialPackages()).toBe true
describe "::loadPackage(name)", ->
beforeEach ->
atom.config.set("core.disabledPackages", [])
@@ -120,6 +133,16 @@ describe "PackageManager", ->
state: state2
}
it "early-activates any atom.directory-provider or atom.repository-provider services that the package provide", ->
jasmine.useRealClock()
providers = []
atom.packages.serviceHub.consume 'atom.directory-provider', '^0.1.0', (provider) ->
providers.push(provider)
atom.packages.loadPackage('package-with-directory-provider')
expect(providers.map((p) -> p.name)).toEqual(['directory provider from package-with-directory-provider'])
describe "when there are view providers specified in the package's package.json", ->
model1 = {worksWithViewProvider1: true}
model2 = {worksWithViewProvider2: true}
@@ -492,6 +515,7 @@ describe "PackageManager", ->
runs ->
expect(pack.mainModule.someNumber).not.toBe 77
pack.mainModule.someNumber = 77
atom.packages.serializePackage("package-with-serialization")
atom.packages.deactivatePackage("package-with-serialization")
spyOn(pack.mainModule, 'activate').andCallThrough()
waitsForPromise ->
@@ -889,6 +913,22 @@ describe "PackageManager", ->
expect(atom.packages.packageStates['package-with-serialization']).toEqual someNumber: 1
expect(console.error).toHaveBeenCalled()
describe "::deactivatePackages()", ->
it "deactivates all packages but does not serialize them", ->
[pack1, pack2] = []
waitsForPromise ->
atom.packages.activatePackage("package-with-deactivate").then (p) -> pack1 = p
atom.packages.activatePackage("package-with-serialization").then (p) -> pack2 = p
runs ->
spyOn(pack1.mainModule, 'deactivate')
spyOn(pack2.mainModule, 'serialize')
atom.packages.deactivatePackages()
expect(pack1.mainModule.deactivate).toHaveBeenCalled()
expect(pack2.mainModule.serialize).not.toHaveBeenCalled()
describe "::deactivatePackage(id)", ->
afterEach ->
atom.packages.unloadPackages()
@@ -995,6 +1035,12 @@ describe "PackageManager", ->
jasmine.restoreDeprecationsSnapshot()
it "sets hasActivatedInitialPackages", ->
spyOn(atom.packages, 'activatePackages')
expect(atom.packages.hasActivatedInitialPackages()).toBe false
waitsForPromise -> atom.packages.activate()
runs -> expect(atom.packages.hasActivatedInitialPackages()).toBe true
it "activates all the packages, and none of the themes", ->
packageActivator = spyOn(atom.packages, 'activatePackages')
themeActivator = spyOn(atom.themes, 'activatePackages')

View File

@@ -197,7 +197,7 @@ describe "Package", ->
expect(spy).toHaveBeenCalled()
describe ".loadMetadata()", ->
[packagePath, pack, metadata] = []
[packagePath, metadata] = []
beforeEach ->
packagePath = atom.project.getDirectories()[0]?.resolve('packages/package-with-different-directory-name')

View File

@@ -2,7 +2,6 @@
{Emitter} = require 'event-kit'
Grim = require 'grim'
Pane = require '../src/pane'
PaneAxis = require '../src/pane-axis'
PaneContainer = require '../src/pane-container'
describe "Pane", ->

View File

@@ -1,7 +1,5 @@
Panel = require '../src/panel'
PanelElement = require '../src/panel-element'
PanelContainer = require '../src/panel-container'
PanelContainerElement = require '../src/panel-container-element'
describe "PanelContainerElement", ->
[jasmineContent, element, container] = []

View File

@@ -1,10 +1,7 @@
temp = require 'temp'
fstream = require 'fstream'
Project = require '../src/project'
_ = require 'underscore-plus'
fs = require 'fs-plus'
path = require 'path'
BufferedProcess = require '../src/buffered-process'
{Directory} = require 'pathwatcher'
GitRepository = require '../src/git-repository'
@@ -25,7 +22,6 @@ describe "Project", ->
deserializedProject = new Project({notificationManager: atom.notifications, packageManager: atom.packages, confirm: atom.confirm})
state = atom.project.serialize()
state.paths.push('/directory/that/does/not/exist')
state.paths.push(path.join(__dirname, 'fixtures', 'sample.js'))
deserializedProject.deserialize(state, atom.deserializers)
expect(deserializedProject.getPaths()).toEqual(atom.project.getPaths())
@@ -231,31 +227,22 @@ describe "Project", ->
expect(directories[1].getPath()).toBe remotePath
expect(directories[1] instanceof DummyDirectory).toBe true
# It does not add new remote paths if their directories do not exist
# and they are contained by existing remote paths.
childRemotePath = remotePath + "/subdirectory/that/does-not-exist"
atom.project.addPath(childRemotePath)
# It does not add new remote paths that do not exist
nonExistentRemotePath = "ssh://another-directory:8080/does-not-exist"
atom.project.addPath(nonExistentRemotePath)
expect(atom.project.getDirectories().length).toBe 2
# It does add new remote paths if their directories exist.
childRemotePath = remotePath + "/subdirectory/that/does-exist"
atom.project.addPath(childRemotePath)
# It adds new remote paths if their directories exist.
newRemotePath = "ssh://another-directory:8080/does-exist"
atom.project.addPath(newRemotePath)
directories = atom.project.getDirectories()
expect(directories[2].getPath()).toBe childRemotePath
expect(directories[2].getPath()).toBe newRemotePath
expect(directories[2] instanceof DummyDirectory).toBe true
# It does add new remote paths to be added if they are not contained by
# previous remote paths.
otherRemotePath = "ssh://other-foreign-directory:8080/"
atom.project.addPath(otherRemotePath)
directories = atom.project.getDirectories()
expect(directories[3].getPath()).toBe otherRemotePath
expect(directories[3] instanceof DummyDirectory).toBe true
it "stops using the provider when the service is removed", ->
serviceDisposable.dispose()
atom.project.setPaths(["ssh://foreign-directory:8080/does-exist"])
expect(atom.project.getDirectories()[0] instanceof Directory).toBe true
expect(atom.project.getDirectories().length).toBe(0)
describe ".open(path)", ->
[absolutePath, newBufferHandler] = []
@@ -429,13 +416,6 @@ describe "Project", ->
expect(atom.project.getPaths()[0]).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
expect(atom.project.getDirectories()[0].path).toEqual path.dirname(require.resolve('./fixtures/dir/a'))
it "only normalizes the directory path if it isn't on the local filesystem", ->
nonLocalFsDirectory = "custom_proto://abc/def"
atom.project.setPaths([nonLocalFsDirectory])
directories = atom.project.getDirectories()
expect(directories.length).toBe 1
expect(directories[0].getPath()).toBe path.normalize(nonLocalFsDirectory)
describe ".addPath(path)", ->
it "calls callbacks registered with ::onDidChangePaths", ->
onDidChangePathsSpy = jasmine.createSpy('onDidChangePaths spy')
@@ -470,6 +450,11 @@ describe "Project", ->
expect(atom.project.getPaths()).toEqual([oldPath, newPath])
expect(onDidChangePathsSpy).toHaveBeenCalled()
it "doesn't add non-existent directories", ->
previousPaths = atom.project.getPaths()
atom.project.addPath('/this-definitely/does-not-exist')
expect(atom.project.getPaths()).toEqual(previousPaths)
describe ".removePath(path)", ->
onDidChangePathsSpy = null

View File

@@ -5,7 +5,7 @@ describe "Selection", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
editor = atom.workspace.buildTextEditor(buffer: buffer, tabLength: 2)
editor = new TextEditor({buffer: buffer, tabLength: 2})
selection = editor.getLastSelection()
afterEach ->

View File

@@ -49,7 +49,7 @@ if process.env.CI
else
jasmine.getEnv().defaultTimeoutInterval = 5000
{resourcePath, testPaths} = atom.getLoadSettings()
{testPaths} = atom.getLoadSettings()
if specPackagePath = FindParentDir.sync(testPaths[0], 'package.json')
packageMetadata = require(path.join(specPackagePath, 'package.json'))
@@ -61,8 +61,6 @@ else
specProjectPath = path.join(__dirname, 'fixtures')
beforeEach ->
documentTitle = null
atom.project.setPaths([specProjectPath])
window.resetTimeouts()

View File

@@ -4,7 +4,6 @@ path = require 'path'
temp = require 'temp'
SquirrelUpdate = require '../src/main-process/squirrel-update'
Spawner = require '../src/main-process/spawner'
WinPowerShell = require '../src/main-process/win-powershell'
WinShell = require '../src/main-process/win-shell'
# Run passed callback as Spawner.spawn() would do

View File

@@ -8,7 +8,6 @@ describe "Task", ->
task = Task.once require.resolve('./fixtures/task-spec-handler'), (result) ->
handlerResult = result
processClosed = false
processErrored = false
childProcess = task.childProcess
spyOn(childProcess, 'kill').andCallThrough()

View File

@@ -2,6 +2,7 @@
import {it, fit, ffit, fffit, beforeEach, afterEach, conditionPromise} from './async-spec-helpers'
import Grim from 'grim'
import TextEditor from '../src/text-editor'
import TextEditorElement from '../src/text-editor-element'
import _, {extend, flatten, last, toArray} from 'underscore-plus'
@@ -4419,7 +4420,7 @@ describe('TextEditorComponent', function () {
describe('when autoHeight is not assigned on the editor', function () {
it('implicitly assigns autoHeight to true and emits a deprecation warning if the editor has its height assigned via an inline style', function () {
editor = atom.workspace.buildTextEditor()
editor = new TextEditor()
element = editor.getElement()
element.setUpdatedSynchronously(false)
element.style.height = '200px'
@@ -4434,7 +4435,7 @@ describe('TextEditorComponent', function () {
})
it('implicitly assigns autoHeight to true and emits a deprecation warning if the editor has its height assigned via position absolute with an assigned top and bottom', function () {
editor = atom.workspace.buildTextEditor()
editor = new TextEditor()
element = editor.getElement()
element.setUpdatedSynchronously(false)
parentElement = document.createElement('div')

View File

@@ -1,5 +1,5 @@
TextEditorElement = require '../src/text-editor-element'
TextEditor = require '../src/text-editor'
TextEditorElement = require '../src/text-editor-element'
{Disposable} = require 'event-kit'
# The rest of text-editor-component-spec will be moved to this file when React
@@ -34,7 +34,7 @@ describe "TextEditorElement", ->
describe "when the model is assigned", ->
it "adds the 'mini' attribute if .isMini() returns true on the model", ->
element = new TextEditorElement
model = atom.workspace.buildTextEditor(mini: true)
model = new TextEditor({mini: true})
element.setModel(model)
expect(element.hasAttribute('mini')).toBe true
@@ -53,7 +53,7 @@ describe "TextEditorElement", ->
describe "when the editor is detached from the DOM and then reattached", ->
it "does not render duplicate line numbers", ->
editor = atom.workspace.buildTextEditor()
editor = new TextEditor
editor.setText('1\n2\n3')
element = atom.views.getView(editor)
@@ -66,7 +66,7 @@ describe "TextEditorElement", ->
expect(element.shadowRoot.querySelectorAll('.line-number').length).toBe initialCount
it "does not render duplicate decorations in custom gutters", ->
editor = atom.workspace.buildTextEditor()
editor = new TextEditor
editor.setText('1\n2\n3')
editor.addGutter({name: 'test-gutter'})
marker = editor.markBufferRange([[0, 0], [2, 0]])
@@ -201,7 +201,7 @@ describe "TextEditorElement", ->
describe "::getMaxScrollTop", ->
it "returns the maximum scroll top that can be applied to the element", ->
editor = atom.workspace.buildTextEditor()
editor = new TextEditor
editor.setText('1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16')
element = atom.views.getView(editor)
element.style.lineHeight = "10px"

View File

@@ -19,7 +19,7 @@ describe "TextEditorPresenter", ->
spyOn(window, "clearInterval").andCallFake window.fakeClearInterval
buffer = new TextBuffer(filePath: require.resolve('./fixtures/sample.js'))
editor = atom.workspace.buildTextEditor({buffer})
editor = new TextEditor({buffer})
waitsForPromise -> buffer.load()
afterEach ->
@@ -475,6 +475,7 @@ describe "TextEditorPresenter", ->
waitsForPromise -> atom.packages.activatePackage('language-javascript')
runs ->
editor.setGrammar(atom.grammars.grammarForScopeName('source.js'))
maxLineLength = editor.getMaxScreenLineLength()
presenter = buildPresenter(contentFrameWidth: 50, baseCharacterWidth: 10)
@@ -759,6 +760,7 @@ describe "TextEditorPresenter", ->
waitsForPromise -> atom.packages.activatePackage('language-javascript')
runs ->
editor.setGrammar(atom.grammars.grammarForScopeName('source.js'))
editor.setCursorBufferPosition([3, 6])
presenter = buildPresenter()
expect(getState(presenter).hiddenInput.width).toBe 10
@@ -918,6 +920,7 @@ describe "TextEditorPresenter", ->
waitsForPromise -> atom.packages.activatePackage('language-javascript')
runs ->
editor.setGrammar(atom.grammars.grammarForScopeName('source.js'))
maxLineLength = editor.getMaxScreenLineLength()
presenter = buildPresenter(contentFrameWidth: 50, baseCharacterWidth: 10)
@@ -1265,6 +1268,8 @@ describe "TextEditorPresenter", ->
expectValues lineStateForScreenRow(presenter, 3), {screenRow: 3, tagCodes: editor.screenLineForScreenRow(3).tagCodes}
it "includes the .endOfLineInvisibles if the editor.showInvisibles config option is true", ->
editor.update({showInvisibles: false, invisibles: {eol: 'X'}})
editor.setText("hello\nworld\r\n")
presenter = buildPresenter(explicitHeight: 25, scrollTop: 0, lineHeight: 10)
expect(tagsForCodes(presenter, lineStateForScreenRow(presenter, 0).tagCodes).openTags).not.toContain('invisible-character eol')
@@ -1731,6 +1736,7 @@ describe "TextEditorPresenter", ->
atom.packages.activatePackage('language-javascript')
runs ->
editor.setGrammar(atom.grammars.grammarForScopeName('source.js'))
editor.setCursorBufferPosition([1, 4])
presenter = buildPresenter(explicitHeight: 20)
@@ -1848,7 +1854,7 @@ describe "TextEditorPresenter", ->
describe ".highlights", ->
expectUndefinedStateForHighlight = (presenter, decoration) ->
for tileId, tileState of getState(presenter).content.tiles
for tileId of getState(presenter).content.tiles
state = stateForHighlightInTile(presenter, decoration, tileId)
expect(state).toBeUndefined()
@@ -1860,7 +1866,7 @@ describe "TextEditorPresenter", ->
stateForHighlightInTile(presenter, selection.decoration, tile)
expectUndefinedStateForSelection = (presenter, selectionIndex) ->
for tileId, tileState of getState(presenter).content.tiles
for tileId of getState(presenter).content.tiles
state = stateForSelectionInTile(presenter, selectionIndex, tileId)
expect(state).toBeUndefined()
@@ -2076,6 +2082,7 @@ describe "TextEditorPresenter", ->
atom.packages.activatePackage('language-javascript')
runs ->
editor.setGrammar(atom.grammars.grammarForScopeName('source.js'))
editor.setSelectedBufferRanges([
[[2, 4], [2, 6]],
])
@@ -3667,7 +3674,7 @@ describe "TextEditorPresenter", ->
performSetup = ->
buffer = new TextBuffer
editor = atom.workspace.buildTextEditor({buffer})
editor = new TextEditor({buffer})
editor.setEditorWidthInChars(80)
presenterParams =
model: editor

View File

@@ -15,15 +15,11 @@ describe('TextEditorRegistry', function () {
registry = new TextEditorRegistry({
assert: atom.assert,
config: atom.config,
clipboard: atom.clipboard,
grammarRegistry: atom.grammars,
packageManager: {deferredActivationHooks: null}
})
editor = new TextEditor({
config: atom.config,
clipboard: atom.clipboard,
})
editor = new TextEditor()
})
afterEach(function () {
@@ -125,6 +121,25 @@ describe('TextEditorRegistry', function () {
expect(editor.getGrammar().name).toBe('Null Grammar')
expect(retainedEditorCount(registry)).toBe(0)
})
describe('when called twice with a given editor', function () {
it('does nothing the second time', async function () {
await atom.packages.activatePackage('language-javascript')
const disposable1 = registry.maintainGrammar(editor)
const disposable2 = registry.maintainGrammar(editor)
editor.getBuffer().setPath('test.js')
expect(editor.getGrammar().name).toBe('JavaScript')
disposable2.dispose()
editor.getBuffer().setPath('test.txt')
expect(editor.getGrammar().name).toBe('Null Grammar')
disposable1.dispose()
editor.getBuffer().setPath('test.js')
expect(editor.getGrammar().name).toBe('Null Grammar')
})
})
})
describe('.setGrammarOverride', function () {
@@ -175,10 +190,7 @@ describe('TextEditorRegistry', function () {
it('does not update the editor when config settings change for unrelated scope selectors', async function () {
await atom.packages.activatePackage('language-javascript')
const editor2 = new TextEditor({
config: atom.config,
clipboard: atom.clipboard,
})
const editor2 = new TextEditor()
editor2.setGrammar(atom.grammars.selectGrammar('test.js'))
@@ -186,13 +198,13 @@ describe('TextEditorRegistry', function () {
registry.maintainConfig(editor2)
await initialPackageActivation
expect(editor.getRootScopeDescriptor().getScopesArray()).toEqual(['text.plain'])
expect(editor.getRootScopeDescriptor().getScopesArray()).toEqual(['text.plain.null-grammar'])
expect(editor2.getRootScopeDescriptor().getScopesArray()).toEqual(['source.js'])
expect(editor.getEncoding()).toBe('utf8')
expect(editor2.getEncoding()).toBe('utf8')
atom.config.set('core.fileEncoding', 'utf16le', {scopeSelector: '.text.plain'})
atom.config.set('core.fileEncoding', 'utf16le', {scopeSelector: '.text.plain.null-grammar'})
atom.config.set('core.fileEncoding', 'utf16be', {scopeSelector: '.source.js'})
expect(editor.getEncoding()).toBe('utf16le')
@@ -205,7 +217,6 @@ describe('TextEditorRegistry', function () {
registry = new TextEditorRegistry({
assert: atom.assert,
config: atom.config,
clipboard: atom.clipboard,
grammarRegistry: atom.grammars,
packageManager: {
deferredActivationHooks: [],
@@ -625,14 +636,32 @@ describe('TextEditorRegistry', function () {
expect(delegate.getNonWordCharacters(['e.f', 'g.h'])).toBe('(){}[]')
expect(delegate.getNonWordCharacters(['i.j'])).toBe('()')
})
describe('when called twice with a given editor', function () {
it('does nothing the second time', async function () {
editor.update({scrollSensitivity: 50})
const disposable1 = registry.maintainConfig(editor)
const disposable2 = registry.maintainConfig(editor)
await initialPackageActivation
atom.config.set('editor.scrollSensitivity', 60)
expect(editor.getScrollSensitivity()).toBe(60)
disposable2.dispose()
atom.config.set('editor.scrollSensitivity', 70)
expect(editor.getScrollSensitivity()).toBe(70)
disposable1.dispose()
atom.config.set('editor.scrollSensitivity', 80)
expect(editor.getScrollSensitivity()).toBe(70)
})
})
})
describe('serialization', function () {
it('persists editors\' grammar overrides', async function () {
const editor2 = new TextEditor({
config: atom.config,
clipboard: atom.clipboard,
})
const editor2 = new TextEditor()
await atom.packages.activatePackage('language-c')
await atom.packages.activatePackage('language-html')
@@ -651,7 +680,6 @@ describe('TextEditorRegistry', function () {
const registryCopy = new TextEditorRegistry({
assert: atom.assert,
config: atom.config,
clipboard: atom.clipboard,
grammarRegistry: atom.grammars,
packageManager: {deferredActivationHooks: null}
})

View File

@@ -1,6 +1,4 @@
fs = require 'fs-plus'
path = require 'path'
temp = require 'temp'
clipboard = require '../src/safe-clipboard'
TextEditor = require '../src/text-editor'
TextBuffer = require 'text-buffer'
@@ -56,7 +54,6 @@ describe "TextEditor", ->
# reusing the same buffer instance
editor2 = TextEditor.deserialize(editor.serialize(), {
assert: atom.assert,
clipboard: atom.clipboard,
textEditors: atom.textEditors,
project: {
bufferForIdSync: (id) -> TextBuffer.deserialize(editor.buffer.serialize())
@@ -4751,7 +4748,7 @@ describe "TextEditor", ->
it "deletes the entire file from the bottom up", ->
count = buffer.getLineCount()
expect(count).toBeGreaterThan(0)
for line in [0...count]
for [0...count]
editor.getLastCursor().moveToBottom()
editor.deleteLine()
expect(buffer.getLineCount()).toBe(1)
@@ -4760,7 +4757,7 @@ describe "TextEditor", ->
it "deletes the entire file from the top down", ->
count = buffer.getLineCount()
expect(count).toBeGreaterThan(0)
for line in [0...count]
for [0...count]
editor.getLastCursor().moveToTop()
editor.deleteLine()
expect(buffer.getLineCount()).toBe(1)
@@ -4878,6 +4875,11 @@ describe "TextEditor", ->
editor.setTabLength(6)
expect(changeHandler).not.toHaveBeenCalled()
it 'does not change its tab length when the given tab length is null', ->
editor.setTabLength(4)
editor.setTabLength(null)
expect(editor.getTabLength()).toBe(4)
describe ".indentLevelForLine(line)", ->
it "returns the indent level when the line has only leading whitespace", ->
expect(editor.indentLevelForLine(" hello")).toBe(2)
@@ -5522,7 +5524,7 @@ describe "TextEditor", ->
describe "auto height", ->
it "returns true by default but can be customized", ->
editor = atom.workspace.buildTextEditor()
editor = new TextEditor
expect(editor.getAutoHeight()).toBe(true)
editor.update({autoHeight: false})
expect(editor.getAutoHeight()).toBe(false)
@@ -5540,10 +5542,10 @@ describe "TextEditor", ->
describe '.get/setPlaceholderText()', ->
it 'can be created with placeholderText', ->
newEditor = atom.workspace.buildTextEditor(
newEditor = new TextEditor({
mini: true
placeholderText: 'yep'
)
})
expect(newEditor.getPlaceholderText()).toBe 'yep'
it 'models placeholderText and emits an event when changed', ->
@@ -5828,11 +5830,7 @@ describe "TextEditor", ->
atom.packages.activatePackage('language-coffee-script')
it "sets the grammar", ->
editor = new TextEditor({
grammar: atom.grammars.grammarForScopeName('source.coffee')
clipboard: atom.clipboard
})
editor = new TextEditor({grammar: atom.grammars.grammarForScopeName('source.coffee')})
expect(editor.getGrammar().name).toBe 'CoffeeScript'
describe "softWrapAtPreferredLineLength", ->

View File

@@ -2,12 +2,7 @@ path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
Package = require '../src/package'
describe "atom.themes", ->
resourcePath = atom.getLoadSettings().resourcePath
configDirPath = atom.getConfigDirPath()
beforeEach ->
spyOn(console, 'warn')

View File

@@ -60,7 +60,7 @@ class TimeReporter extends jasmine.Reporter
time: duration
fullName: spec.getFullName()
if timedSuites[@suite]
if window.timedSuites[@suite]
window.timedSuites[@suite] += duration
else
window.timedSuites[@suite] = duration

View File

@@ -29,7 +29,7 @@ describe "TokenIterator", ->
})
tokenizedBuffer.setGrammar(grammar)
tokenIterator = tokenizedBuffer.tokenizedLineForRow(1).getTokenIterator()
tokenIterator = tokenizedBuffer.tokenizedLines[1].getTokenIterator()
tokenIterator.next()
expect(tokenIterator.getBufferStart()).toBe 0

View File

@@ -1,3 +1,4 @@
NullGrammar = require '../src/null-grammar'
TokenizedBuffer = require '../src/tokenized-buffer'
{Point} = TextBuffer = require 'text-buffer'
_ = require 'underscore-plus'
@@ -32,15 +33,8 @@ describe "TokenizedBuffer", ->
atom.packages.activatePackage('language-coffee-script')
it "deserializes it searching among the buffers in the current project", ->
tokenizedBufferA = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBufferB = TokenizedBuffer.deserialize(
JSON.parse(JSON.stringify(tokenizedBufferA.serialize())),
atom
)
tokenizedBufferA = new TokenizedBuffer({buffer, tabLength: 2})
tokenizedBufferB = TokenizedBuffer.deserialize(JSON.parse(JSON.stringify(tokenizedBufferA.serialize())), atom)
expect(tokenizedBufferB.buffer).toBe(tokenizedBufferA.buffer)
describe "when the underlying buffer has no path", ->
@@ -48,25 +42,14 @@ describe "TokenizedBuffer", ->
buffer = atom.project.bufferForPathSync(null)
it "deserializes it searching among the buffers in the current project", ->
tokenizedBufferA = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBufferB = TokenizedBuffer.deserialize(
JSON.parse(JSON.stringify(tokenizedBufferA.serialize())),
atom
)
tokenizedBufferA = new TokenizedBuffer({buffer, tabLength: 2})
tokenizedBufferB = TokenizedBuffer.deserialize(JSON.parse(JSON.stringify(tokenizedBufferA.serialize())), atom)
expect(tokenizedBufferB.buffer).toBe(tokenizedBufferA.buffer)
describe "when the buffer is destroyed", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
startTokenizing(tokenizedBuffer)
it "stops tokenization", ->
@@ -78,11 +61,7 @@ describe "TokenizedBuffer", ->
describe "when the buffer contains soft-tabs", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
startTokenizing(tokenizedBuffer)
afterEach ->
@@ -90,32 +69,29 @@ describe "TokenizedBuffer", ->
buffer.release()
describe "on construction", ->
it "initially creates un-tokenized screen lines, then tokenizes lines chunk at a time in the background", ->
line0 = tokenizedBuffer.tokenizedLineForRow(0)
expect(line0.tokens).toEqual([value: line0.text, scopes: ['source.js']])
it "tokenizes lines chunk at a time in the background", ->
line0 = tokenizedBuffer.tokenizedLines[0]
expect(line0).toBeUndefined()
line11 = tokenizedBuffer.tokenizedLineForRow(11)
expect(line11.tokens).toEqual([value: " return sort(Array.apply(this, arguments));", scopes: ['source.js']])
# background tokenization has not begun
expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack).toBeUndefined()
line11 = tokenizedBuffer.tokenizedLines[11]
expect(line11).toBeUndefined()
# tokenize chunk 1
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(4).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeFalsy()
expect(tokenizedBuffer.tokenizedLines[0].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[4].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[5]).toBeUndefined()
# tokenize chunk 2
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(9).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(10).ruleStack?).toBeFalsy()
expect(tokenizedBuffer.tokenizedLines[5].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[9].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[10]).toBeUndefined()
# tokenize last chunk
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(10).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(12).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[10].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[12].ruleStack?).toBeTruthy()
describe "when the buffer is partially tokenized", ->
beforeEach ->
@@ -152,8 +128,8 @@ describe "TokenizedBuffer", ->
it "does not attempt to tokenize the lines in the change, and preserves the existing invalid row", ->
expect(tokenizedBuffer.firstInvalidRow()).toBe 5
buffer.setTextInRange([[6, 0], [7, 0]], "\n\n\n")
expect(tokenizedBuffer.tokenizedLineForRow(6).ruleStack?).toBeFalsy()
expect(tokenizedBuffer.tokenizedLineForRow(7).ruleStack?).toBeFalsy()
expect(tokenizedBuffer.tokenizedLines[6]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLines[7]).toBeUndefined()
expect(tokenizedBuffer.firstInvalidRow()).toBe 5
describe "when the buffer is fully tokenized", ->
@@ -165,101 +141,101 @@ describe "TokenizedBuffer", ->
it "updates tokens to reflect the change", ->
buffer.setTextInRange([[0, 0], [2, 0]], "foo()\n7\n")
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.function-call.js', 'meta.arguments.js', 'punctuation.definition.arguments.begin.bracket.round.js'])
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.decimal.js'])
expect(tokenizedBuffer.tokenizedLines[0].tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.function-call.js', 'meta.arguments.js', 'punctuation.definition.arguments.begin.bracket.round.js'])
expect(tokenizedBuffer.tokenizedLines[1].tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.decimal.js'])
# line 2 is unchanged
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
expect(tokenizedBuffer.tokenizedLines[2].tokens[1]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
describe "when the change invalidates the tokenization of subsequent lines", ->
it "schedules the invalidated lines to be tokenized in the background", ->
buffer.insert([5, 30], '/* */')
buffer.insert([2, 0], '/*')
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js']
expect(tokenizedBuffer.tokenizedLines[3].tokens[0].scopes).toEqual ['source.js']
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[3].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[4].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[5].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
it "resumes highlighting with the state of the previous line", ->
buffer.insert([0, 0], '/*')
buffer.insert([5, 0], '*/')
buffer.insert([1, 0], 'var ')
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[1].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
describe "when lines are both updated and removed", ->
it "updates tokens to reflect the change", ->
buffer.setTextInRange([[1, 0], [3, 0]], "foo()")
# previous line 0 remains
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.type.var.js'])
expect(tokenizedBuffer.tokenizedLines[0].tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.type.var.js'])
# previous line 3 should be combined with input to form line 1
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[6]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
expect(tokenizedBuffer.tokenizedLines[1].tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLines[1].tokens[6]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
# lines below deleted regions should be shifted upward
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[1]).toEqual(value: 'while', scopes: ['source.js', 'keyword.control.js'])
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[1]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[1]).toEqual(value: '<', scopes: ['source.js', 'keyword.operator.comparison.js'])
expect(tokenizedBuffer.tokenizedLines[2].tokens[1]).toEqual(value: 'while', scopes: ['source.js', 'keyword.control.js'])
expect(tokenizedBuffer.tokenizedLines[3].tokens[1]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
expect(tokenizedBuffer.tokenizedLines[4].tokens[1]).toEqual(value: '<', scopes: ['source.js', 'keyword.operator.comparison.js'])
describe "when the change invalidates the tokenization of subsequent lines", ->
it "schedules the invalidated lines to be tokenized in the background", ->
buffer.insert([5, 30], '/* */')
buffer.setTextInRange([[2, 0], [3, 0]], '/*')
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js']
expect(tokenizedBuffer.tokenizedLines[2].tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
expect(tokenizedBuffer.tokenizedLines[3].tokens[0].scopes).toEqual ['source.js']
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[3].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[4].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
describe "when lines are both updated and inserted", ->
it "updates tokens to reflect the change", ->
buffer.setTextInRange([[1, 0], [2, 0]], "foo()\nbar()\nbaz()\nquux()")
# previous line 0 remains
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.type.var.js'])
expect(tokenizedBuffer.tokenizedLines[0].tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.type.var.js'])
# 3 new lines inserted
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0]).toEqual(value: 'bar', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0]).toEqual(value: 'baz', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLines[1].tokens[0]).toEqual(value: 'foo', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLines[2].tokens[0]).toEqual(value: 'bar', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLines[3].tokens[0]).toEqual(value: 'baz', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
# previous line 2 is joined with quux() on line 4
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0]).toEqual(value: 'quux', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[4]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
expect(tokenizedBuffer.tokenizedLines[4].tokens[0]).toEqual(value: 'quux', scopes: ['source.js', 'meta.function-call.js', 'entity.name.function.js'])
expect(tokenizedBuffer.tokenizedLines[4].tokens[4]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
# previous line 3 is pushed down to become line 5
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[3]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
expect(tokenizedBuffer.tokenizedLines[5].tokens[3]).toEqual(value: '=', scopes: ['source.js', 'keyword.operator.assignment.js'])
describe "when the change invalidates the tokenization of subsequent lines", ->
it "schedules the invalidated lines to be tokenized in the background", ->
buffer.insert([5, 30], '/* */')
buffer.insert([2, 0], '/*\nabcde\nabcder')
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js']
expect(tokenizedBuffer.tokenizedLines[2].tokens[0].scopes).toEqual ['source.js', 'comment.block.js', 'punctuation.definition.comment.js']
expect(tokenizedBuffer.tokenizedLines[3].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[4].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[5].tokens[0].scopes).toEqual ['source.js']
advanceClock() # tokenize invalidated lines in background
expect(tokenizedBuffer.tokenizedLineForRow(5).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(6).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(7).tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLineForRow(8).tokens[0].scopes).not.toBe ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[5].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[6].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[7].tokens[0].scopes).toEqual ['source.js', 'comment.block.js']
expect(tokenizedBuffer.tokenizedLines[8].tokens[0].scopes).not.toBe ['source.js', 'comment.block.js']
describe "when there is an insertion that is larger than the chunk size", ->
it "tokenizes the initial chunk synchronously, then tokenizes the remaining lines in the background", ->
commentBlock = _.multiplyString("// a comment\n", tokenizedBuffer.chunkSize + 2)
buffer.insert([0, 0], commentBlock)
expect(tokenizedBuffer.tokenizedLineForRow(0).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(4).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeFalsy()
expect(tokenizedBuffer.tokenizedLines[0].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[4].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[5]).toBeUndefined()
advanceClock()
expect(tokenizedBuffer.tokenizedLineForRow(5).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLineForRow(6).ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[5].ruleStack?).toBeTruthy()
expect(tokenizedBuffer.tokenizedLines[6].ruleStack?).toBeTruthy()
it "does not break out soft tabs across a scope boundary", ->
waitsForPromise ->
@@ -284,11 +260,7 @@ describe "TokenizedBuffer", ->
runs ->
buffer = atom.project.bufferForPathSync('sample-with-tabs.coffee')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.coffee'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.coffee'), tabLength: 2})
startTokenizing(tokenizedBuffer)
afterEach ->
@@ -352,7 +324,6 @@ describe "TokenizedBuffer", ->
expect(tokenizedHandler.callCount).toBe(1)
it "retokenizes the buffer", ->
waitsForPromise ->
atom.packages.activatePackage('language-ruby-on-rails')
@@ -362,14 +333,10 @@ describe "TokenizedBuffer", ->
runs ->
buffer = atom.project.bufferForPathSync()
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.selectGrammar('test.erb'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.selectGrammar('test.erb'), tabLength: 2})
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.tokenizedLineForRow(0)
{tokens} = tokenizedBuffer.tokenizedLines[0]
expect(tokens[0]).toEqual value: "<div class='name'>", scopes: ["text.html.ruby"]
waitsForPromise ->
@@ -377,7 +344,7 @@ describe "TokenizedBuffer", ->
runs ->
fullyTokenize(tokenizedBuffer)
{tokens} = tokenizedBuffer.tokenizedLineForRow(0)
{tokens} = tokenizedBuffer.tokenizedLines[0]
expect(tokens[0]).toEqual value: '<', scopes: ["text.html.ruby", "meta.tag.block.any.html", "punctuation.definition.tag.begin.html"]
describe ".tokenForPosition(position)", ->
@@ -387,11 +354,7 @@ describe "TokenizedBuffer", ->
it "returns the correct token (regression)", ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
fullyTokenize(tokenizedBuffer)
expect(tokenizedBuffer.tokenForPosition([1, 0]).scopes).toEqual ["source.js"]
expect(tokenizedBuffer.tokenForPosition([1, 1]).scopes).toEqual ["source.js"]
@@ -400,16 +363,12 @@ describe "TokenizedBuffer", ->
describe ".bufferRangeForScopeAtPosition(selector, position)", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
fullyTokenize(tokenizedBuffer)
describe "when the selector does not match the token at the position", ->
it "returns a falsy value", ->
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.bogus', [0, 1])).toBeFalsy()
expect(tokenizedBuffer.bufferRangeForScopeAtPosition('.bogus', [0, 1])).toBeUndefined()
describe "when the selector matches a single token at the position", ->
it "returns the range covered by the token", ->
@@ -423,11 +382,7 @@ describe "TokenizedBuffer", ->
describe ".indentLevelForRow(row)", ->
beforeEach ->
buffer = atom.project.bufferForPathSync('sample.js')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
fullyTokenize(tokenizedBuffer)
describe "when the line is non-empty", ->
@@ -469,7 +424,7 @@ describe "TokenizedBuffer", ->
buffer.insert([12, 0], ' ')
expect(tokenizedBuffer.indentLevelForRow(13)).toBe 2
expect(tokenizedBuffer.tokenizedLineForRow(14)).not.toBeDefined()
expect(tokenizedBuffer.tokenizedLines[14]).not.toBeDefined()
it "updates the indentLevel of empty lines surrounding a change that inserts lines", ->
buffer.insert([7, 0], '\n\n')
@@ -499,18 +454,11 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.indentLevelForRow(10)).toBe 2 # }
describe "::isFoldableAtRow(row)", ->
changes = null
beforeEach ->
changes = []
buffer = atom.project.bufferForPathSync('sample.js')
buffer.insert [10, 0], " // multi-line\n // comment\n // block\n"
buffer.insert [0, 0], "// multi-line\n// comment\n// block\n"
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.grammarForScopeName('source.js'))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName('source.js'), tabLength: 2})
fullyTokenize(tokenizedBuffer)
it "includes the first line of multi-line comments", ->
@@ -573,40 +521,69 @@ describe "TokenizedBuffer", ->
expect(tokenizedBuffer.isFoldableAtRow(7)).toBe false
expect(tokenizedBuffer.isFoldableAtRow(8)).toBe false
describe "::tokenizedLineForRow(row)", ->
it "returns the tokenized line for a row, or a placeholder line if it hasn't been tokenized yet", ->
buffer = atom.project.bufferForPathSync('sample.js')
grammar = atom.grammars.grammarForScopeName('source.js')
tokenizedBuffer = new TokenizedBuffer({buffer, grammar, tabLength: 2})
line0 = buffer.lineForRow(0)
jsScopeStartId = grammar.startIdForScope(grammar.scopeName)
jsScopeEndId = grammar.endIdForScope(grammar.scopeName)
startTokenizing(tokenizedBuffer)
expect(tokenizedBuffer.tokenizedLines[0]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe(line0)
expect(tokenizedBuffer.tokenizedLineForRow(0).tags).toEqual([jsScopeStartId, line0.length, jsScopeEndId])
advanceClock(1)
expect(tokenizedBuffer.tokenizedLines[0]).not.toBeUndefined()
expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe(line0)
expect(tokenizedBuffer.tokenizedLineForRow(0).tags).not.toEqual([jsScopeStartId, line0.length, jsScopeEndId])
nullScopeStartId = NullGrammar.startIdForScope(NullGrammar.scopeName)
nullScopeEndId = NullGrammar.endIdForScope(NullGrammar.scopeName)
tokenizedBuffer.setGrammar(NullGrammar)
startTokenizing(tokenizedBuffer)
expect(tokenizedBuffer.tokenizedLines[0]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe(line0)
expect(tokenizedBuffer.tokenizedLineForRow(0).tags).toEqual([nullScopeStartId, line0.length, nullScopeEndId])
advanceClock(1)
expect(tokenizedBuffer.tokenizedLineForRow(0).text).toBe(line0)
expect(tokenizedBuffer.tokenizedLineForRow(0).tags).toEqual([nullScopeStartId, line0.length, nullScopeEndId])
it "returns undefined if the requested row is outside the buffer range", ->
buffer = atom.project.bufferForPathSync('sample.js')
grammar = atom.grammars.grammarForScopeName('source.js')
tokenizedBuffer = new TokenizedBuffer({buffer, grammar, tabLength: 2})
fullyTokenize(tokenizedBuffer)
expect(tokenizedBuffer.tokenizedLineForRow(999)).toBeUndefined()
describe "when the buffer is configured with the null grammar", ->
it "uses the placeholder tokens and does not actually tokenize using the grammar", ->
spyOn(atom.grammars.nullGrammar, 'tokenizeLine').andCallThrough()
it "does not actually tokenize using the grammar", ->
spyOn(NullGrammar, 'tokenizeLine').andCallThrough()
buffer = atom.project.bufferForPathSync('sample.will-use-the-null-grammar')
buffer.setText('a\nb\nc')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer = new TokenizedBuffer({buffer, tabLength: 2})
tokenizeCallback = jasmine.createSpy('onDidTokenize')
tokenizedBuffer.onDidTokenize(tokenizeCallback)
expect(tokenizedBuffer.tokenizedLines[0]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLines[1]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLines[2]).toBeUndefined()
expect(tokenizeCallback.callCount).toBe(0)
expect(NullGrammar.tokenizeLine).not.toHaveBeenCalled()
fullyTokenize(tokenizedBuffer)
expect(tokenizeCallback.callCount).toBe 1
expect(atom.grammars.nullGrammar.tokenizeLine.callCount).toBe 0
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens.length).toBe 1
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0].value).toBe 'a'
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens.length).toBe 1
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0].value).toBe 'b'
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens.length).toBe 1
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0].value).toBe 'c'
expect(tokenizedBuffer.tokenizedLines[0]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLines[1]).toBeUndefined()
expect(tokenizedBuffer.tokenizedLines[2]).toBeUndefined()
expect(tokenizeCallback.callCount).toBe(0)
expect(NullGrammar.tokenizeLine).not.toHaveBeenCalled()
describe "text decoration layer API", ->
describe "iterator", ->
it "iterates over the syntactic scope boundaries", ->
buffer = new TextBuffer(text: "var foo = 1 /*\nhello*/var bar = 2\n")
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.selectGrammar(".js"))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName("source.js"), tabLength: 2})
fullyTokenize(tokenizedBuffer)
iterator = tokenizedBuffer.buildIterator()
@@ -658,11 +635,7 @@ describe "TokenizedBuffer", ->
runs ->
buffer = new TextBuffer(text: "# hello\n# world")
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(atom.grammars.selectGrammar(".coffee"))
tokenizedBuffer = new TokenizedBuffer({buffer, grammar: atom.grammars.grammarForScopeName("source.coffee"), tabLength: 2})
fullyTokenize(tokenizedBuffer)
iterator = tokenizedBuffer.buildIterator()
@@ -691,11 +664,7 @@ describe "TokenizedBuffer", ->
})
buffer = new TextBuffer(text: 'start x\nend x\nx')
tokenizedBuffer = new TokenizedBuffer({
buffer, grammarRegistry: atom.grammars, packageManager: atom.packages,
assert: atom.assert, tabLength: 2,
})
tokenizedBuffer.setGrammar(grammar)
tokenizedBuffer = new TokenizedBuffer({buffer, grammar, tabLength: 2})
fullyTokenize(tokenizedBuffer)
iterator = tokenizedBuffer.buildIterator()

View File

@@ -8,7 +8,7 @@ describe "TooltipManager", ->
ctrlY = _.humanizeKeystroke("ctrl-y")
beforeEach ->
manager = new TooltipManager(keymapManager: atom.keymaps)
manager = new TooltipManager(keymapManager: atom.keymaps, viewRegistry: atom.views)
element = document.createElement('div')
element.classList.add('foo')
jasmine.attachToDOM(element)
@@ -16,23 +16,62 @@ describe "TooltipManager", ->
hover = (element, fn) ->
element.dispatchEvent(new CustomEvent('mouseenter', bubbles: false))
element.dispatchEvent(new CustomEvent('mouseover', bubbles: true))
advanceClock(manager.defaults.delay.show)
advanceClock(manager.hoverDefaults.delay.show)
fn()
element.dispatchEvent(new CustomEvent('mouseleave', bubbles: false))
element.dispatchEvent(new CustomEvent('mouseout', bubbles: true))
advanceClock(manager.defaults.delay.hide)
advanceClock(manager.hoverDefaults.delay.hide)
describe "::add(target, options)", ->
it "creates a tooltip based on the given options when hovering over the target element", ->
manager.add element, title: "Title"
hover element, ->
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
describe "when the trigger is 'hover' (the default)", ->
it "creates a tooltip when hovering over the target element", ->
manager.add element, title: "Title"
hover element, ->
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
it "creates a tooltip immediately if the trigger type is manual", ->
disposable = manager.add element, title: "Title", trigger: "manual"
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
disposable.dispose()
expect(document.body.querySelector(".tooltip")).toBeNull()
describe "when the trigger is 'manual'", ->
it "creates a tooltip immediately and only hides it on dispose", ->
disposable = manager.add element, title: "Title", trigger: "manual"
expect(document.body.querySelector(".tooltip")).toHaveText("Title")
disposable.dispose()
expect(document.body.querySelector(".tooltip")).toBeNull()
describe "when the trigger is 'click'", ->
it "shows and hides the tooltip when the target element is clicked", ->
disposable = manager.add element, title: "Title", trigger: "click"
expect(document.body.querySelector(".tooltip")).toBeNull()
element.click()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
element.click()
expect(document.body.querySelector(".tooltip")).toBeNull()
# Hide the tooltip when clicking anywhere but inside the tooltip element
element.click()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
document.body.querySelector(".tooltip").click()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
document.body.querySelector(".tooltip").firstChild.click()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
document.body.click()
expect(document.body.querySelector(".tooltip")).toBeNull()
# Tooltip can show again after hiding due to clicking outside of the tooltip
element.click()
expect(document.body.querySelector(".tooltip")).not.toBeNull()
element.click()
expect(document.body.querySelector(".tooltip")).toBeNull()
it "allows a custom item to be specified for the content of the tooltip", ->
tooltipElement = document.createElement('div')
manager.add element, item: {element: tooltipElement}
hover element, ->
expect(tooltipElement.closest(".tooltip")).not.toBeNull()
it "allows a custom class to be specified for the tooltip", ->
tooltipElement = document.createElement('div')
manager.add element, title: 'Title', class: 'custom-tooltip-class'
hover element, ->
expect(document.body.querySelector(".tooltip").classList.contains('custom-tooltip-class')).toBe(true)
it "allows jQuery elements to be passed as the target", ->
element2 = document.createElement('div')
@@ -52,20 +91,6 @@ describe "TooltipManager", ->
hover element, -> expect(document.body.querySelector(".tooltip")).toBeNull()
hover element2, -> expect(document.body.querySelector(".tooltip")).toBeNull()
describe "when a selector is specified", ->
it "creates a tooltip when hovering over a descendant of the target that matches the selector", ->
child = document.createElement('div')
child.classList.add('bar')
grandchild = document.createElement('div')
element.appendChild(child)
child.appendChild(grandchild)
manager.add element, selector: '.bar', title: 'Bar'
hover grandchild, ->
expect(document.body.querySelector('.tooltip')).toHaveText('Bar')
expect(document.body.querySelector('.tooltip')).toBeNull()
describe "when a keyBindingCommand is specified", ->
describe "when a title is specified", ->
it "appends the key binding corresponding to the command to the title", ->

View File

@@ -1,13 +1,10 @@
KeymapManager = require 'atom-keymap'
path = require 'path'
fs = require 'fs-plus'
temp = require 'temp'
TextEditor = require '../src/text-editor'
WindowEventHandler = require '../src/window-event-handler'
{ipcRenderer} = require 'electron'
describe "WindowEventHandler", ->
[projectPath, windowEventHandler] = []
[windowEventHandler] = []
beforeEach ->
atom.uninstallWindowEventHandler()
@@ -19,7 +16,6 @@ describe "WindowEventHandler", ->
loadSettings
atom.project.destroy()
windowEventHandler = new WindowEventHandler({atomEnvironment: atom, applicationDelegate: atom.applicationDelegate, window, document})
projectPath = atom.project.getPaths()[0]
afterEach ->
windowEventHandler.unsubscribe()
@@ -53,6 +49,7 @@ describe "WindowEventHandler", ->
describe "beforeunload event", ->
beforeEach ->
jasmine.unspy(TextEditor.prototype, "shouldPromptToSave")
spyOn(atom, 'destroy')
spyOn(ipcRenderer, 'send')
describe "when pane items are modified", ->
@@ -66,12 +63,14 @@ describe "WindowEventHandler", ->
window.dispatchEvent(new CustomEvent('beforeunload'))
expect(atom.workspace.confirmClose).toHaveBeenCalled()
expect(ipcRenderer.send).not.toHaveBeenCalledWith('did-cancel-window-unload')
expect(atom.destroy).toHaveBeenCalled()
it "cancels the unload if the user selects cancel", ->
spyOn(atom.workspace, 'confirmClose').andReturn(false)
window.dispatchEvent(new CustomEvent('beforeunload'))
expect(atom.workspace.confirmClose).toHaveBeenCalled()
expect(ipcRenderer.send).toHaveBeenCalledWith('did-cancel-window-unload')
expect(atom.destroy).not.toHaveBeenCalled()
describe "when a link is clicked", ->
it "opens the http/https links in an external application", ->

View File

@@ -1,6 +1,7 @@
{ipcRenderer} = require 'electron'
path = require 'path'
temp = require('temp').track()
{Disposable} = require 'event-kit'
describe "WorkspaceElement", ->
describe "when the workspace element is focused", ->
@@ -17,9 +18,11 @@ describe "WorkspaceElement", ->
it "has a class based on the style of the scrollbar", ->
observeCallback = null
scrollbarStyle = require 'scrollbar-style'
spyOn(scrollbarStyle, 'observePreferredScrollbarStyle').andCallFake (cb) -> observeCallback = cb
workspaceElement = atom.views.getView(atom.workspace)
spyOn(scrollbarStyle, 'observePreferredScrollbarStyle').andCallFake (cb) ->
observeCallback = cb
new Disposable(->)
workspaceElement = atom.views.getView(atom.workspace)
observeCallback('legacy')
expect(workspaceElement.className).toMatch 'scrollbars-visible-always'

View File

@@ -1,8 +1,8 @@
path = require 'path'
temp = require 'temp'
TextEditor = require '../src/text-editor'
Workspace = require '../src/workspace'
Project = require '../src/project'
Pane = require '../src/pane'
platform = require './spec-helper-platform'
_ = require 'underscore-plus'
fstream = require 'fstream'
@@ -30,7 +30,7 @@ describe "Workspace", ->
atom.workspace = new Workspace({
config: atom.config, project: atom.project, packageManager: atom.packages,
grammarRegistry: atom.grammars, deserializerManager: atom.deserializers,
notificationManager: atom.notifications, clipboard: atom.clipboard,
notificationManager: atom.notifications,
applicationDelegate: atom.applicationDelegate,
viewRegistry: atom.views, assert: atom.assert.bind(atom),
textEditorRegistry: atom.textEditors
@@ -81,7 +81,7 @@ describe "Workspace", ->
expect(untitledEditor.getText()).toBe("An untitled editor.")
expect(atom.workspace.getActiveTextEditor().getPath()).toBe editor3.getPath()
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{path.basename(editor3.getLongTitle())}\ \u2014\ #{pathEscaped}///
describe "where there are no open panes or editors", ->
@@ -796,7 +796,7 @@ describe "Workspace", ->
describe "::isTextEditor(obj)", ->
it "returns true when the passed object is an instance of `TextEditor`", ->
expect(workspace.isTextEditor(atom.workspace.buildTextEditor())).toBe(true)
expect(workspace.isTextEditor(new TextEditor)).toBe(true)
expect(workspace.isTextEditor({getText: -> null})).toBe(false)
expect(workspace.isTextEditor(null)).toBe(false)
expect(workspace.isTextEditor(undefined)).toBe(false)
@@ -872,7 +872,7 @@ describe "Workspace", ->
workspace2 = new Workspace({
config: atom.config, project: atom.project, packageManager: atom.packages,
notificationManager: atom.notifications, deserializerManager: atom.deserializers,
clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars,
viewRegistry: atom.views, grammarRegistry: atom.grammars,
applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom),
textEditorRegistry: atom.textEditors
})
@@ -894,28 +894,28 @@ describe "Workspace", ->
describe "when there is an active pane item", ->
it "sets the title to the pane item's title plus the project path", ->
item = atom.workspace.getActivePaneItem()
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{pathEscaped}///
describe "when the title of the active pane item changes", ->
it "updates the window title based on the item's new title", ->
editor = atom.workspace.getActivePaneItem()
editor.buffer.setPath(path.join(temp.dir, 'hi'))
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{editor.getTitle()}\ \u2014\ #{pathEscaped}///
describe "when the active pane's item changes", ->
it "updates the title to the new item's title plus the project path", ->
atom.workspace.getActivePane().activateNextItem()
item = atom.workspace.getActivePaneItem()
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{item.getTitle()}\ \u2014\ #{pathEscaped}///
describe "when the last pane item is removed", ->
it "updates the title to contain the project's path", ->
atom.workspace.getActivePane().destroy()
expect(atom.workspace.getActivePaneItem()).toBeUndefined()
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{pathEscaped}///
describe "when an inactive pane's item changes", ->
@@ -935,13 +935,13 @@ describe "Workspace", ->
workspace2 = new Workspace({
config: atom.config, project: atom.project, packageManager: atom.packages,
notificationManager: atom.notifications, deserializerManager: atom.deserializers,
clipboard: atom.clipboard, viewRegistry: atom.views, grammarRegistry: atom.grammars,
viewRegistry: atom.views, grammarRegistry: atom.grammars,
applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom),
textEditorRegistry: atom.textEditors
})
workspace2.deserialize(atom.workspace.serialize(), atom.deserializers)
item = workspace2.getActivePaneItem()
pathEscaped = escapeStringRegex(atom.project.getPaths()[0])
pathEscaped = fs.tildify(escapeStringRegex(atom.project.getPaths()[0]))
expect(document.title).toMatch ///^#{item.getLongTitle()}\ \u2014\ #{pathEscaped}///
workspace2.destroy()
@@ -1241,7 +1241,6 @@ describe "Workspace", ->
expect(matches.length).toBe 1
it "excludes values in core.ignoredNames", ->
projectPath = path.join(__dirname, 'fixtures', 'git', 'working-dir')
ignoredNames = atom.config.get("core.ignoredNames")
ignoredNames.push("a")
atom.config.set("core.ignoredNames", ignoredNames)
@@ -1729,7 +1728,7 @@ describe "Workspace", ->
describe "when there's no repository for the editor's file", ->
it "doesn't do anything", ->
editor = atom.workspace.buildTextEditor()
editor = new TextEditor
editor.setText("stuff")
atom.workspace.checkoutHeadRevision(editor)

View File

@@ -1,5 +1,5 @@
_ = require 'underscore-plus'
{screen, ipcRenderer, remote, shell, systemPreferences, webFrame} = require 'electron'
{screen, ipcRenderer, remote, shell, webFrame} = require 'electron'
ipcHelpers = require './ipc-helpers'
{Disposable} = require 'event-kit'
{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers'
@@ -20,7 +20,7 @@ class ApplicationDelegate
remote.getCurrentWindow()
closeWindow: ->
ipcRenderer.send("call-window-method", "close")
ipcHelpers.call('window-method', 'close')
getTemporaryWindowState: ->
ipcHelpers.call('get-temporary-window-state').then (stateJSON) -> JSON.parse(stateJSON)
@@ -55,72 +55,55 @@ class ApplicationDelegate
ipcHelpers.call('hide-window')
reloadWindow: ->
ipcRenderer.send("call-window-method", "reload")
ipcHelpers.call('window-method', 'reload')
restartApplication: ->
ipcRenderer.send("restart-application")
minimizeWindow: ->
ipcRenderer.send("call-window-method", "minimize")
ipcHelpers.call('window-method', 'minimize')
isWindowMaximized: ->
remote.getCurrentWindow().isMaximized()
maximizeWindow: ->
ipcRenderer.send("call-window-method", "maximize")
ipcHelpers.call('window-method', 'maximize')
unmaximizeWindow: ->
ipcRenderer.send("call-window-method", "unmaximize")
ipcHelpers.call('window-method', 'unmaximize')
isWindowFullScreen: ->
remote.getCurrentWindow().isFullScreen()
setWindowFullScreen: (fullScreen=false) ->
ipcRenderer.send("call-window-method", "setFullScreen", fullScreen)
ipcHelpers.call('window-method', 'setFullScreen', fullScreen)
openWindowDevTools: ->
new Promise (resolve) ->
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
process.nextTick ->
if remote.getCurrentWindow().isDevToolsOpened()
resolve()
else
remote.getCurrentWindow().once("devtools-opened", -> resolve())
ipcRenderer.send("call-window-method", "openDevTools")
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'openDevTools'))
closeWindowDevTools: ->
new Promise (resolve) ->
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
process.nextTick ->
unless remote.getCurrentWindow().isDevToolsOpened()
resolve()
else
remote.getCurrentWindow().once("devtools-closed", -> resolve())
ipcRenderer.send("call-window-method", "closeDevTools")
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'closeDevTools'))
toggleWindowDevTools: ->
new Promise (resolve) =>
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
process.nextTick =>
if remote.getCurrentWindow().isDevToolsOpened()
@closeWindowDevTools().then(resolve)
else
@openWindowDevTools().then(resolve)
# Defer DevTools interaction to the next tick, because using them during
# event handling causes some wrong input events to be triggered on
# `TextEditorComponent` (Ref.: https://github.com/atom/atom/issues/9697).
new Promise(process.nextTick).then(-> ipcHelpers.call('window-method', 'toggleDevTools'))
executeJavaScriptInWindowDevTools: (code) ->
ipcRenderer.send("execute-javascript-in-dev-tools", code)
setWindowDocumentEdited: (edited) ->
ipcRenderer.send("call-window-method", "setDocumentEdited", edited)
ipcHelpers.call('window-method', 'setDocumentEdited', edited)
setRepresentedFilename: (filename) ->
ipcRenderer.send("call-window-method", "setRepresentedFilename", filename)
ipcHelpers.call('window-method', 'setRepresentedFilename', filename)
addRecentDocument: (filename) ->
ipcRenderer.send("add-recent-document", filename)
@@ -131,7 +114,7 @@ class ApplicationDelegate
setWindowLoadSettings(loadSettings)
setAutoHideWindowMenuBar: (autoHide) ->
ipcRenderer.send("call-window-method", "setAutoHideMenuBar", autoHide)
ipcHelpers.call('window-method', 'setAutoHideMenuBar', autoHide)
setWindowMenuBarVisibility: (visible) ->
remote.getCurrentWindow().setMenuBarVisibility(visible)

View File

@@ -9,10 +9,9 @@ fs = require 'fs-plus'
{mapSourcePosition} = require 'source-map-support'
Model = require './model'
WindowEventHandler = require './window-event-handler'
StylesElement = require './styles-element'
StateStore = require './state-store'
StorageFolder = require './storage-folder'
{getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers'
{getWindowLoadSettings} = require './window-load-settings-helpers'
registerDefaultCommands = require './register-default-commands'
DeserializerManager = require './deserializer-manager'
@@ -29,7 +28,6 @@ ThemeManager = require './theme-manager'
MenuManager = require './menu-manager'
ContextMenuManager = require './context-menu-manager'
CommandInstaller = require './command-installer'
Clipboard = require './clipboard'
Project = require './project'
TitleBar = require './title-bar'
Workspace = require './workspace'
@@ -51,7 +49,6 @@ PanelElement = require './panel-element'
PaneContainerElement = require './pane-container-element'
PaneAxisElement = require './pane-axis-element'
PaneElement = require './pane-element'
TextEditorElement = require './text-editor-element'
{createGutterView} = require './gutter-component-helpers'
# Essential: Atom global for dealing with packages, themes, menus, and the window.
@@ -129,7 +126,7 @@ class AtomEnvironment extends Model
# Call .loadOrCreate instead
constructor: (params={}) ->
{@blobStore, @applicationDelegate, @window, @document, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params
{@blobStore, @applicationDelegate, @window, @document, @clipboard, @configDirPath, @enablePersistence, onlyLoadBaseStyleSheets} = params
@unloaded = false
@loadTime = null
@@ -156,7 +153,7 @@ class AtomEnvironment extends Model
@keymaps = new KeymapManager({@configDirPath, resourcePath, notificationManager: @notifications})
@tooltips = new TooltipManager(keymapManager: @keymaps)
@tooltips = new TooltipManager(keymapManager: @keymaps, viewRegistry: @views)
@commands = new CommandRegistry
@commands.attach(@window)
@@ -184,20 +181,18 @@ class AtomEnvironment extends Model
@packages.setContextMenuManager(@contextMenu)
@packages.setThemeManager(@themes)
@clipboard = new Clipboard()
@project = new Project({notificationManager: @notifications, packageManager: @packages, @config, @applicationDelegate})
@commandInstaller = new CommandInstaller(@getVersion(), @applicationDelegate)
@textEditors = new TextEditorRegistry({
@config, grammarRegistry: @grammars, assert: @assert.bind(this), @clipboard,
@config, grammarRegistry: @grammars, assert: @assert.bind(this),
packageManager: @packages
})
@workspace = new Workspace({
@config, @project, packageManager: @packages, grammarRegistry: @grammars, deserializerManager: @deserializers,
notificationManager: @notifications, @applicationDelegate, @clipboard, viewRegistry: @views, assert: @assert.bind(this),
notificationManager: @notifications, @applicationDelegate, viewRegistry: @views, assert: @assert.bind(this),
textEditorRegistry: @textEditors,
})
@@ -850,7 +845,7 @@ class AtomEnvironment extends Model
@project.addPath(selectedPath) for selectedPath in selectedPaths
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
callback(@showSaveDialogSync())
showSaveDialogSync: (options={}) ->
@applicationDelegate.showSaveDialog(options)

View File

@@ -24,7 +24,7 @@ class BlockDecorationsComponent
@domNode.style.width = @newState.width + "px"
@oldState.width = @newState.width
for id, blockDecorationState of @oldState.blockDecorations
for id of @oldState.blockDecorations
unless @newState.blockDecorations.hasOwnProperty(id)
blockDecorationNode = @blockDecorationNodesById[id]
blockDecorationNode.previousSibling.remove()
@@ -33,7 +33,7 @@ class BlockDecorationsComponent
delete @blockDecorationNodesById[id]
delete @oldState.blockDecorations[id]
for id, blockDecorationState of @newState.blockDecorations
for id of @newState.blockDecorations
if @oldState.blockDecorations.hasOwnProperty(id)
@updateBlockDecorationNode(id)
else
@@ -42,7 +42,6 @@ class BlockDecorationsComponent
measureBlockDecorations: ->
for decorationId, blockDecorationNode of @blockDecorationNodesById
style = getComputedStyle(blockDecorationNode)
decoration = @newState.blockDecorations[decorationId].decoration
topRuler = blockDecorationNode.previousSibling
bottomRuler = blockDecorationNode.nextSibling

View File

@@ -36,13 +36,10 @@ exports.compile = function (sourceCode, filePath) {
var output = CoffeeScript.compile(sourceCode, {
filename: filePath,
sourceFiles: [filePath],
sourceMap: true
inlineMap: true
})
var js = output.js
js += '\n'
js += '//# sourceMappingURL=data:application/json;base64,'
js += new Buffer(output.v3SourceMap).toString('base64')
js += '\n'
return js
// Strip sourceURL from output so there wouldn't be duplicate entries
// in devtools.
return output.replace(/\/\/# sourceURL=[^'"\n]+\s*$/, '')
}

View File

@@ -214,7 +214,6 @@ class CommandRegistry
immediatePropagationStopped = false
matched = false
currentTarget = event.target
{preventDefault, stopPropagation, stopImmediatePropagation, abortKeyBinding} = event
dispatchedEvent = new CustomEvent(event.type, {bubbles: true, detail: event.detail})
Object.defineProperty dispatchedEvent, 'eventPhase', value: Event.BUBBLING_PHASE

View File

@@ -74,7 +74,7 @@ function compileFileAtPath (compiler, filePath, extension) {
cacheStats[extension].hits++
} else {
cacheStats[extension].misses++
compiledCode = addSourceURL(compiler.compile(sourceCode, filePath), filePath)
compiledCode = compiler.compile(sourceCode, filePath)
writeCachedJavascript(cachePath, compiledCode)
}
return compiledCode
@@ -97,13 +97,6 @@ function writeCachedJavascript (relativeCachePath, code) {
fs.writeFileSync(cachePath, code, 'utf8')
}
function addSourceURL (jsCode, filePath) {
if (process.platform === 'win32') {
filePath = '/' + path.resolve(filePath).replace(/\\/g, '/')
}
return jsCode + '\n' + '//# sourceURL=' + encodeURI(filePath) + '\n'
}
var INLINE_SOURCE_MAP_REGEXP = /\/\/[#@]\s*sourceMappingURL=([^'"\n]+)\s*$/mg
require('source-map-support').install({

View File

@@ -12,7 +12,7 @@ module.exports =
default: [".git", ".hg", ".svn", ".DS_Store", "._*", "Thumbs.db"]
items:
type: 'string'
description: 'List of string glob patterns. Files and directories matching these patterns will be ignored by some packages, such as the fuzzy finder and tree view. Individual packages might have additional config settings for ignoring names.'
description: 'List of [glob patterns](https://en.wikipedia.org/wiki/Glob_%28programming%29). Files and directories matching these patterns will be ignored by some packages, such as the fuzzy finder and tree view. Individual packages might have additional config settings for ignoring names.'
excludeVcsIgnoredPaths:
type: 'boolean'
default: true

View File

@@ -1,6 +1,6 @@
_ = require 'underscore-plus'
fs = require 'fs-plus'
{CompositeDisposable, Disposable, Emitter} = require 'event-kit'
{Emitter} = require 'event-kit'
CSON = require 'season'
path = require 'path'
async = require 'async'
@@ -561,7 +561,7 @@ class Config
# * `scopeDescriptor` The {ScopeDescriptor} with which the value is associated
# * `value` The value for the key-path
getAll: (keyPath, options) ->
{scope, sources} = options if options?
{scope} = options if options?
result = []
if scope?
@@ -1045,7 +1045,6 @@ class Config
resetSettingsForSchemaChange: (source=@getUserConfigPath()) ->
@transact =>
@settings = @makeValueConformToSchema(null, @settings, suppressException: true)
priority = @priorityForSource(source)
selectorsAndSettings = @scopedSettingsStore.propertiesForSource(source)
@scopedSettingsStore.removePropertiesForSource(source)
for scopeSelector, settings of selectorsAndSettings

View File

@@ -1,4 +1,3 @@
_ = require 'underscore-plus'
path = require 'path'
CSON = require 'season'
fs = require 'fs-plus'

View File

@@ -682,7 +682,6 @@ class Cursor extends Model
{row, column} = start
scanRange = [[row-1, column], [0, 0]]
position = new Point(0, 0)
zero = new Point(0, 0)
@editor.backwardsScanInBufferRange EmptyLineRegExp, scanRange, ({range, stop}) ->
position = range.start.traverse(Point(1, 0))
stop() unless position.isEqual(start)

View File

@@ -1,4 +1,4 @@
{basename, join} = require 'path'
{join} = require 'path'
_ = require 'underscore-plus'
{Emitter, Disposable, CompositeDisposable} = require 'event-kit'

View File

@@ -1,5 +1,4 @@
_ = require 'underscore-plus'
{Emitter} = require 'event-kit'
FirstMate = require 'first-mate'
Token = require './token'
fs = require 'fs-plus'

View File

@@ -18,7 +18,7 @@ class GutterContainerComponent
@domNode.style.display = 'flex'
destroy: ->
for {name, component} in @gutterComponents
for {component} in @gutterComponents
component.destroy?()
return

View File

@@ -5,7 +5,7 @@ module.exports = ({blobStore}) ->
require './window'
{getWindowLoadSettings} = require './window-load-settings-helpers'
{ipcRenderer} = require 'electron'
{resourcePath, isSpec, devMode, env} = getWindowLoadSettings()
{resourcePath, devMode, env} = getWindowLoadSettings()
require '../src/electron-shims'
updateProcessEnv(env)
@@ -20,16 +20,21 @@ module.exports = ({blobStore}) ->
AtomEnvironment = require './atom-environment'
ApplicationDelegate = require './application-delegate'
Clipboard = require './clipboard'
TextEditor = require './text-editor'
clipboard = new Clipboard
TextEditor.setClipboard(clipboard)
window.atom = new AtomEnvironment({
window, document, blobStore,
window, document, clipboard, blobStore,
applicationDelegate: new ApplicationDelegate,
configDirPath: process.env.ATOM_HOME
enablePersistence: true
configDirPath: process.env.ATOM_HOME,
enablePersistence: true,
env: process.env
})
atom.startEditorWindow().then ->
# Workaround for focus getting cleared upon window creation
windowFocused = ->
window.removeEventListener('focus', windowFocused)

View File

@@ -0,0 +1,111 @@
/** @babel */
import {remote} from 'electron'
import path from 'path'
import ipcHelpers from './ipc-helpers'
import util from 'util'
export default async function () {
const {getWindowLoadSettings} = require('./window-load-settings-helpers')
const {test, headless, resourcePath, benchmarkPaths} = getWindowLoadSettings()
try {
const Clipboard = require('../src/clipboard')
const ApplicationDelegate = require('../src/application-delegate')
const AtomEnvironment = require('../src/atom-environment')
const TextEditor = require('../src/text-editor')
const exportsPath = path.join(resourcePath, 'exports')
require('module').globalPaths.push(exportsPath) // Add 'exports' to module search path.
process.env.NODE_PATH = exportsPath // Set NODE_PATH env variable since tasks may need it.
document.title = 'Benchmarks'
// Allow `document.title` to be assigned in benchmarks without actually changing the window title.
let documentTitle = null
Object.defineProperty(document, 'title', {
get () { return documentTitle },
set (title) { documentTitle = title }
})
window.addEventListener('keydown', (event) => {
// Reload: cmd-r / ctrl-r
if ((event.metaKey || event.ctrlKey) && event.keyCode === 82) {
ipcHelpers.call('window-method', 'reload')
}
// Toggle Dev Tools: cmd-alt-i (Mac) / ctrl-shift-i (Linux/Windows)
if (event.keyCode === 73) {
const isDarwin = process.platform === 'darwin'
if ((isDarwin && event.metaKey && event.altKey) || (!isDarwin && event.ctrlKey && event.shiftKey)) {
ipcHelpers.call('window-method', 'toggleDevTools')
}
}
// Close: cmd-w / ctrl-w
if ((event.metaKey || event.ctrlKey) && event.keyCode === 87) {
ipcHelpers.call('window-method', 'close')
}
// Copy: cmd-c / ctrl-c
if ((event.metaKey || event.ctrlKey) && event.keyCode === 67) {
ipcHelpers.call('window-method', 'copy')
}
}, true)
const clipboard = new Clipboard()
TextEditor.setClipboard(clipboard)
const applicationDelegate = new ApplicationDelegate()
global.atom = new AtomEnvironment({
applicationDelegate,
window,
document,
clipboard,
configDirPath: process.env.ATOM_HOME,
enablePersistence: false
})
// Prevent benchmarks from modifying application menus
global.atom.menu.sendToBrowserProcess = function () { }
if (headless) {
Object.defineProperties(process, {
stdout: { value: remote.process.stdout },
stderr: { value: remote.process.stderr }
})
console.log = function (...args) {
const formatted = util.format(...args)
process.stdout.write(formatted + '\n')
}
console.warn = function (...args) {
const formatted = util.format(...args)
process.stderr.write(formatted + '\n')
}
console.error = function (...args) {
const formatted = util.format(...args)
process.stderr.write(formatted + '\n')
}
} else {
remote.getCurrentWindow().show()
}
const benchmarkRunner = require('../benchmarks/benchmark-runner')
const statusCode = await benchmarkRunner({test, benchmarkPaths})
if (headless) {
exitWithStatusCode(statusCode)
}
} catch (error) {
if (headless) {
console.error(error.stack || error)
exitWithStatusCode(1)
} else {
ipcHelpers.call('window-method', 'openDevTools')
throw error
}
}
}
function exitWithStatusCode (statusCode) {
remote.app.emit('will-quit')
remote.process.exit(statusCode)
}

View File

@@ -1,3 +1,5 @@
ipcHelpers = require './ipc-helpers'
cloneObject = (object) ->
clone = {}
clone[key] = value for key, value of object
@@ -19,6 +21,8 @@ module.exports = ({blobStore}) ->
{getWindowLoadSettings} = require './window-load-settings-helpers'
AtomEnvironment = require '../src/atom-environment'
ApplicationDelegate = require '../src/application-delegate'
Clipboard = require '../src/clipboard'
TextEditor = require '../src/text-editor'
require '../src/electron-shims'
{testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings()
@@ -31,19 +35,21 @@ module.exports = ({blobStore}) ->
handleKeydown = (event) ->
# Reload: cmd-r / ctrl-r
if (event.metaKey or event.ctrlKey) and event.keyCode is 82
ipcRenderer.send('call-window-method', 'reload')
ipcHelpers.call('window-method', 'reload')
# Toggle Dev Tools: cmd-alt-i / ctrl-alt-i
if (event.metaKey or event.ctrlKey) and event.altKey and event.keyCode is 73
ipcRenderer.send('call-window-method', 'toggleDevTools')
# Toggle Dev Tools: cmd-alt-i (Mac) / ctrl-shift-i (Linux/Windows)
if event.keyCode is 73 and (
(process.platform is 'darwin' and event.metaKey and event.altKey) or
(process.platform isnt 'darwin' and event.ctrlKey and event.shiftKey))
ipcHelpers.call('window-method', 'toggleDevTools')
# Close: cmd-w / ctrl-w
if (event.metaKey or event.ctrlKey) and event.keyCode is 87
ipcRenderer.send('call-window-method', 'close')
ipcHelpers.call('window-method', 'close')
# Copy: cmd-c / ctrl-c
if (event.metaKey or event.ctrlKey) and event.keyCode is 67
ipcRenderer.send('call-window-method', 'copy')
ipcHelpers.call('window-method', 'copy')
window.addEventListener('keydown', handleKeydown, true)
@@ -54,11 +60,15 @@ module.exports = ({blobStore}) ->
document.title = "Spec Suite"
clipboard = new Clipboard
TextEditor.setClipboard(clipboard)
testRunner = require(testRunnerPath)
legacyTestRunner = require(legacyTestRunnerPath)
buildDefaultApplicationDelegate = -> new ApplicationDelegate()
buildAtomEnvironment = (params) ->
params = cloneObject(params)
params.clipboard = clipboard unless params.hasOwnProperty("clipboard")
params.blobStore = blobStore unless params.hasOwnProperty("blobStore")
params.onlyLoadBaseStyleSheets = true unless params.hasOwnProperty("onlyLoadBaseStyleSheets")
new AtomEnvironment(params)

Some files were not shown because too many files have changed in this diff Show More