mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-12-28 17:13:45 +03:00
Merge branch 'master' into dh-async-repo
This commit is contained in:
commit
3a06953820
@ -34,9 +34,7 @@ script: script/cibuild
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.atom/.apm
|
||||
- $HOME/.atom/.node-gyp/.atom
|
||||
- $HOME/.atom/.npm
|
||||
- node_modules
|
||||
|
||||
notifications:
|
||||
email:
|
||||
|
@ -4,3 +4,9 @@ See https://atom.io/releases
|
||||
|
||||
* The tree-view now sorts directory entries more naturally, in a locale-sensitive way.
|
||||
* Lines can now be moved up and down with multiple cursors.
|
||||
* Improved the performance of marker-dependent code paths such as spell-check and find and replace.
|
||||
* Fixed copying and pasting in native input fields.
|
||||
* By default, windows with no pane items are now closed via the `core:close` command. The previous behavior can be restored via the `Close Empty Windows` option in settings.
|
||||
* Fixed an issue where characters were inserted when toggling the settings view on some keyboard layouts.
|
||||
* Modules can now temporarily override `Error.prepareStackTrace`. There is also an `Error.prototype.getRawStack()` method if you just need access to the raw v8 trace structure.
|
||||
* Fixed a problem that caused blurry fonts on monitors that have a slightly higher resolution than 96 DPI.
|
||||
|
@ -13,6 +13,7 @@ These are just guidelines, not rules, use your best judgment and feel free to pr
|
||||
|
||||
[How Can I Contribute?](#how-can-i-contribute)
|
||||
* [Reporting Bugs](#reporting-bugs)
|
||||
* [Suggesting Enhancements](#suggesting-enhancements)
|
||||
* [Your First Code Contribution](#your-first-code-contribution)
|
||||
* [Pull Requests](#pull-requests)
|
||||
|
||||
@ -157,6 +158,60 @@ Include details about your configuration and environment:
|
||||
* Problem can be reliably reproduced, doesn't happen randomly: [Yes/No]
|
||||
* Problem happens with all files and projects, not only some files or projects: [Yes/No]
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for Atom, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion :pencil: and find related suggestions :mag_right:.
|
||||
|
||||
Before creating enhancement suggestions, please check [this list](#before-submitting-an-enhancement-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). If you'd like, you can use [this template](#template-for-submitting-enhancement-suggestions) to structure the information.
|
||||
|
||||
#### Before Submitting An Enhancement Suggestion
|
||||
|
||||
* **Check the [debugging guide](https://atom.io/docs/latest/hacking-atom-debugging)** for tips — you might discover that the enhancement is already available. Most importantly, check if you're using [the latest version of Atom](https://atom.io/docs/latest/hacking-atom-debugging#update-to-the-latest-version) and if you can get the desired behavior by changing [Atom's or packages' config settings](https://atom.io/docs/latest/hacking-atom-debugging#check-atom-and-package-settings).
|
||||
* **Check if there's already [a package](https://atom.io/packages) which provides that enhancement.**
|
||||
* **Determine [which repository the enhancement should be suggested in](#atom-and-packages).**
|
||||
* **Perform a [cursory search](https://github.com/issues?q=+is%3Aissue+user%3Aatom)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
|
||||
|
||||
#### How Do I Submit A (Good) Enhancement Suggestion?
|
||||
|
||||
Enhancement suggestions are tracked as [GitHub issues](https://guides.github.com/features/issues/). After you've determined [which repository](#atom-and-packages) your enhancement suggestions is related to, create an issue on that repository and provide the following information:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the suggestion.
|
||||
* **Provide a step-by-step description of the suggested enhancement** in as many details as possible.
|
||||
* **Provide specific examples to demonstrate the steps**. Include copy/pasteable snippets which you use in those examples, as [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
|
||||
* **Include screenshots and animated GIFs** which help you demonstrate the steps or point out the part of Atom which the suggestion is related to. You can use [this tool](http://www.cockos.com/licecap/) to record GIFs on OSX and Windows, and [this tool](https://github.com/colinkeenan/silentcast) or [this tool](https://github.com/GNOME/byzanz) on Linux.
|
||||
* **Explain why this enhancement would be useful** to most Atom users and isn't something that can or should be implemented as a [community package](#atom-and-packages).
|
||||
* **List some other text editors or applications where this enhancement exists.**
|
||||
* **Specify which version of Atom you're using.** You can get the exact version by running `atom -v` in your terminal, or by starting Atom and running the `Application: About` command from the [Command Palette](https://github.com/atom/command-palette).
|
||||
* **Specify the name and version of the OS you're using.**
|
||||
|
||||
#### Template For Submitting Enhancement Suggestions
|
||||
|
||||
[Short description of suggestion]
|
||||
|
||||
**Steps which explain the enhancement**
|
||||
|
||||
1. [First Step]
|
||||
2. [Second Step]
|
||||
3. [Other Steps...]
|
||||
|
||||
**Current and suggested behavior**
|
||||
|
||||
[Describe current and suggested behavior here]
|
||||
|
||||
**Why would the enhancement be useful to most users**
|
||||
|
||||
[Explain why the enhancement would be useful to most users]
|
||||
|
||||
[List some other text editors or applications where this enhancement exists]
|
||||
|
||||
**Screenshots and GIFs**
|
||||
|
||||
![Screenshots and GIFs which demonstrate the steps or part of Atom the enhancement suggestion is related to](url)
|
||||
|
||||
**Atom Version:** [Enter Atom version here]
|
||||
**OS and Version:** [Enter OS name and version here]
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to Atom? You can start by looking through these `beginner` and `help-wanted` issues:
|
||||
@ -200,6 +255,7 @@ Both issue lists are sorted by total number of comments. While not perfect, numb
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...")
|
||||
* Limit the first line to 72 characters or less
|
||||
* Reference issues and pull requests liberally
|
||||
* When only changing documentation, include `[ci skip]` in the commit description
|
||||
* Consider starting the commit message with an applicable emoji:
|
||||
* :art: `:art:` when improving the format/structure of the code
|
||||
* :racehorse: `:racehorse:` when improving performance
|
||||
|
@ -6,6 +6,6 @@
|
||||
"url": "https://github.com/atom/atom.git"
|
||||
},
|
||||
"dependencies": {
|
||||
"atom-package-manager": "1.4.1"
|
||||
"atom-package-manager": "1.5.0"
|
||||
}
|
||||
}
|
||||
|
4
atom.sh
4
atom.sh
@ -50,6 +50,10 @@ if [ $REDIRECT_STDERR ]; then
|
||||
exec 2> /dev/null
|
||||
fi
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
export ELECTRON_ENABLE_LOGGING=1
|
||||
fi
|
||||
|
||||
if [ $OS == 'Mac' ]; then
|
||||
if [ -n "$BETA_VERSION" ]; then
|
||||
ATOM_APP_NAME="Atom Beta.app"
|
||||
|
@ -284,6 +284,7 @@ module.exports = (grunt) ->
|
||||
ciTasks.push('download-electron')
|
||||
ciTasks.push('download-electron-chromedriver')
|
||||
ciTasks.push('build')
|
||||
ciTasks.push('fingerprint')
|
||||
ciTasks.push('dump-symbols') if process.platform isnt 'win32'
|
||||
ciTasks.push('set-version', 'check-licenses', 'lint', 'generate-asar')
|
||||
ciTasks.push('mkdeb') if process.platform is 'linux'
|
||||
|
@ -27,7 +27,7 @@
|
||||
"grunt-peg": "~1.1.0",
|
||||
"grunt-shell": "~0.3.1",
|
||||
"grunt-standard": "^1.0.2",
|
||||
"legal-eagle": "~0.12.0",
|
||||
"legal-eagle": "~0.13.0",
|
||||
"minidump": "~0.9",
|
||||
"npm": "2.13.3",
|
||||
"rcedit": "~0.3.0",
|
||||
|
7
build/tasks/fingerprint-task.js
Normal file
7
build/tasks/fingerprint-task.js
Normal file
@ -0,0 +1,7 @@
|
||||
var fingerprint = require('../../script/utils/fingerprint')
|
||||
|
||||
module.exports = function (grunt) {
|
||||
grunt.registerTask('fingerprint', 'Fingerpint the node_modules folder for caching on CI', function () {
|
||||
fingerprint.writeFingerprint()
|
||||
})
|
||||
}
|
@ -36,7 +36,6 @@ unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE
|
||||
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, look for for the existence of
|
||||
a public method that you're using (e.g. `::getText`).
|
||||
To check if an object is a text editor, use `atom.workspace.isTextEditor(object)`.
|
||||
"""
|
||||
TextEditor
|
||||
|
40
package.json
40
package.json
@ -12,7 +12,7 @@
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"license": "MIT",
|
||||
"electronVersion": "0.34.3",
|
||||
"electronVersion": "0.34.5",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"atom-keymap": "^6.1.1",
|
||||
@ -53,7 +53,7 @@
|
||||
"service-hub": "^0.7.0",
|
||||
"source-map-support": "^0.3.2",
|
||||
"temp": "0.8.1",
|
||||
"text-buffer": "^8.0.4",
|
||||
"text-buffer": "8.0.9",
|
||||
"typescript-simple": "1.0.0",
|
||||
"underscore-plus": "^1.6.6",
|
||||
"yargs": "^3.23.0"
|
||||
@ -65,10 +65,10 @@
|
||||
"atom-light-ui": "0.43.0",
|
||||
"base16-tomorrow-dark-theme": "1.0.0",
|
||||
"base16-tomorrow-light-theme": "1.0.0",
|
||||
"one-dark-ui": "1.1.5",
|
||||
"one-dark-ui": "1.1.7",
|
||||
"one-dark-syntax": "1.1.1",
|
||||
"one-light-syntax": "1.1.1",
|
||||
"one-light-ui": "1.1.5",
|
||||
"one-light-ui": "1.1.7",
|
||||
"solarized-dark-syntax": "0.39.0",
|
||||
"solarized-light-syntax": "0.23.0",
|
||||
"about": "1.1.0",
|
||||
@ -76,7 +76,7 @@
|
||||
"autocomplete-atom-api": "0.9.2",
|
||||
"autocomplete-css": "0.11.0",
|
||||
"autocomplete-html": "0.7.2",
|
||||
"autocomplete-plus": "2.23.0",
|
||||
"autocomplete-plus": "2.23.1",
|
||||
"autocomplete-snippets": "1.8.0",
|
||||
"autoflow": "0.26.0",
|
||||
"autosave": "0.23.0",
|
||||
@ -99,12 +99,12 @@
|
||||
"line-ending-selector": "0.3.0",
|
||||
"link": "0.31.0",
|
||||
"markdown-preview": "0.156.2",
|
||||
"metrics": "0.53.0",
|
||||
"notifications": "0.61.0",
|
||||
"metrics": "0.53.1",
|
||||
"notifications": "0.62.1",
|
||||
"open-on-github": "0.40.0",
|
||||
"package-generator": "0.41.0",
|
||||
"release-notes": "0.53.0",
|
||||
"settings-view": "0.232.0",
|
||||
"settings-view": "0.232.1",
|
||||
"snippets": "1.0.1",
|
||||
"spell-check": "0.63.0",
|
||||
"status-bar": "0.80.0",
|
||||
@ -115,39 +115,39 @@
|
||||
"tree-view": "0.198.0",
|
||||
"update-package-dependencies": "0.10.0",
|
||||
"welcome": "0.33.0",
|
||||
"whitespace": "0.32.0",
|
||||
"whitespace": "0.32.1",
|
||||
"wrap-guide": "0.38.1",
|
||||
"language-c": "0.49.0",
|
||||
"language-c": "0.50.1",
|
||||
"language-clojure": "0.18.0",
|
||||
"language-coffee-script": "0.43.0",
|
||||
"language-coffee-script": "0.46.0",
|
||||
"language-csharp": "0.11.0",
|
||||
"language-css": "0.35.0",
|
||||
"language-css": "0.35.1",
|
||||
"language-gfm": "0.81.0",
|
||||
"language-git": "0.10.0",
|
||||
"language-go": "0.40.0",
|
||||
"language-html": "0.42.0",
|
||||
"language-hyperlink": "0.15.0",
|
||||
"language-java": "0.16.1",
|
||||
"language-javascript": "0.100.0",
|
||||
"language-java": "0.17.0",
|
||||
"language-javascript": "0.102.2",
|
||||
"language-json": "0.17.1",
|
||||
"language-less": "0.28.3",
|
||||
"language-less": "0.29.0",
|
||||
"language-make": "0.20.0",
|
||||
"language-mustache": "0.13.0",
|
||||
"language-objective-c": "0.15.0",
|
||||
"language-perl": "0.31.0",
|
||||
"language-php": "0.34.0",
|
||||
"language-property-list": "0.8.0",
|
||||
"language-python": "0.41.0",
|
||||
"language-ruby": "0.62.0",
|
||||
"language-python": "0.42.1",
|
||||
"language-ruby": "0.64.1",
|
||||
"language-ruby-on-rails": "0.24.0",
|
||||
"language-sass": "0.43.0",
|
||||
"language-sass": "0.44.1",
|
||||
"language-shellscript": "0.20.0",
|
||||
"language-source": "0.9.0",
|
||||
"language-sql": "0.19.0",
|
||||
"language-text": "0.7.0",
|
||||
"language-todo": "0.27.0",
|
||||
"language-toml": "0.16.0",
|
||||
"language-xml": "0.34.0",
|
||||
"language-toml": "0.17.0",
|
||||
"language-xml": "0.34.1",
|
||||
"language-yaml": "0.24.0"
|
||||
},
|
||||
"private": true,
|
||||
|
@ -16,6 +16,7 @@ FOR %%a IN (%*) DO (
|
||||
)
|
||||
|
||||
IF "%EXPECT_OUTPUT%"=="YES" (
|
||||
SET ELECTRON_ENABLE_LOGGING=YES
|
||||
"%~dp0\..\..\atom.exe" %*
|
||||
) ELSE (
|
||||
"%~dp0\..\app\apm\bin\node.exe" "%~dp0\atom.js" %*
|
||||
|
@ -18,6 +18,7 @@ done
|
||||
directory=$(dirname "$0")
|
||||
|
||||
if [ $EXPECT_OUTPUT ]; then
|
||||
export ELECTRON_ENABLE_LOGGING=1
|
||||
"$directory/../../atom.exe" "$@"
|
||||
else
|
||||
"$directory/../app/apm/bin/node.exe" "$directory/atom.js" "$@"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
var cp = require('./utils/child-process-wrapper.js');
|
||||
var crypto = require('crypto')
|
||||
var fingerprint = require('./utils/fingerprint')
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
@ -42,6 +44,11 @@ function setEnvironmentVariables() {
|
||||
}
|
||||
|
||||
function removeNodeModules() {
|
||||
if (fingerprint.fingerprintMatches()) {
|
||||
console.log('node_modules matches current fingerprint ' + fingerprint.fingerprint() + ' - not removing')
|
||||
return
|
||||
}
|
||||
|
||||
var fsPlus;
|
||||
try {
|
||||
fsPlus = require('fs-plus');
|
||||
@ -98,8 +105,8 @@ cp.safeExec.bind(global, 'npm install npm --loglevel error', {cwd: path.resolve(
|
||||
var async = require('async');
|
||||
var gruntPath = path.join('build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
||||
var tasks = [
|
||||
cp.safeExec.bind(global, 'git clean -dff'),
|
||||
cp.safeExec.bind(global, gruntPath + ' ci --gruntfile build/Gruntfile.coffee --stack --no-color'),
|
||||
cp.safeExec.bind(global, 'git clean -dff -e node_modules'), // If we left them behind in removeNodeModules() they are OK to use
|
||||
cp.safeExec.bind(global, gruntPath + ' ci --gruntfile build/Gruntfile.coffee --stack --no-color')
|
||||
]
|
||||
async.series(tasks, function(error) {
|
||||
process.exit(error ? 1 : 0);
|
||||
|
31
script/utils/fingerprint.js
Normal file
31
script/utils/fingerprint.js
Normal file
@ -0,0 +1,31 @@
|
||||
var crypto = require('crypto')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
|
||||
var fingerprintPath = path.resolve(__dirname, '..', '..', 'node_modules', '.atom-ci-fingerprint')
|
||||
|
||||
module.exports = {
|
||||
fingerprint: function () {
|
||||
var packageJson = fs.readFileSync(path.resolve(__dirname, '..', '..', 'package.json'))
|
||||
var body = packageJson.toString() + process.platform + process.version
|
||||
return crypto.createHash('sha1').update(body).digest('hex')
|
||||
},
|
||||
|
||||
writeFingerprint: function () {
|
||||
var fingerprint = this.fingerprint()
|
||||
fs.writeFileSync(fingerprintPath, fingerprint)
|
||||
console.log('Wrote ci fingerprint:', fingerprintPath, fingerprint)
|
||||
},
|
||||
|
||||
readFingerprint: function() {
|
||||
if (fs.existsSync(fingerprintPath)) {
|
||||
return fs.readFileSync(fingerprintPath).toString()
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
},
|
||||
|
||||
fingerprintMatches: function () {
|
||||
return this.readFingerprint() && this.readFingerprint() === this.fingerprint()
|
||||
}
|
||||
}
|
@ -45,9 +45,11 @@ describe "AtomEnvironment", ->
|
||||
expect(atom.config.get('editor.showInvisibles')).toBe false
|
||||
|
||||
describe "window onerror handler", ->
|
||||
devToolsPromise = null
|
||||
beforeEach ->
|
||||
spyOn atom, 'openDevTools'
|
||||
spyOn atom, 'executeJavaScriptInDevTools'
|
||||
devToolsPromise = Promise.resolve()
|
||||
spyOn(atom, 'openDevTools').andReturn(devToolsPromise)
|
||||
spyOn(atom, 'executeJavaScriptInDevTools')
|
||||
|
||||
it "will open the dev tools when an error is triggered", ->
|
||||
try
|
||||
@ -55,8 +57,10 @@ describe "AtomEnvironment", ->
|
||||
catch e
|
||||
window.onerror.call(window, e.toString(), 'abc', 2, 3, e)
|
||||
|
||||
expect(atom.openDevTools).toHaveBeenCalled()
|
||||
expect(atom.executeJavaScriptInDevTools).toHaveBeenCalled()
|
||||
waitsForPromise -> devToolsPromise
|
||||
runs ->
|
||||
expect(atom.openDevTools).toHaveBeenCalled()
|
||||
expect(atom.executeJavaScriptInDevTools).toHaveBeenCalled()
|
||||
|
||||
describe "::onWillThrowError", ->
|
||||
willThrowSpy = null
|
||||
@ -243,6 +247,21 @@ describe "AtomEnvironment", ->
|
||||
|
||||
atomEnvironment.destroy()
|
||||
|
||||
describe "::destroy()", ->
|
||||
it "does not throw exceptions when unsubscribing from ipc events (regression)", ->
|
||||
configDirPath = temp.mkdirSync()
|
||||
fakeDocument = {
|
||||
addEventListener: ->
|
||||
removeEventListener: ->
|
||||
head: document.createElement('head')
|
||||
body: document.createElement('body')
|
||||
}
|
||||
atomEnvironment = new AtomEnvironment({applicationDelegate: atom.applicationDelegate, window, document: fakeDocument})
|
||||
spyOn(atomEnvironment.packages, 'getAvailablePackagePaths').andReturn []
|
||||
atomEnvironment.startEditorWindow()
|
||||
atomEnvironment.unloadEditorWindow()
|
||||
atomEnvironment.destroy()
|
||||
|
||||
describe "::openLocations(locations) (called via IPC from browser process)", ->
|
||||
beforeEach ->
|
||||
spyOn(atom.workspace, 'open')
|
||||
|
@ -69,3 +69,18 @@ describe 'CompileCache', ->
|
||||
|
||||
CompileCache.addPathToCache(path.join(fixtures, 'cson.cson'), atomHome)
|
||||
expect(CSONParser.parse.callCount).toBe 1
|
||||
|
||||
describe 'overriding Error.prepareStackTrace', ->
|
||||
it 'removes the override on the next tick, and always assigns the raw stack', ->
|
||||
Error.prepareStackTrace = -> 'a-stack-trace'
|
||||
|
||||
error = new Error("Oops")
|
||||
expect(error.stack).toBe 'a-stack-trace'
|
||||
expect(Array.isArray(error.getRawStack())).toBe true
|
||||
|
||||
waits(1)
|
||||
runs ->
|
||||
error = new Error("Oops again")
|
||||
console.log error.stack
|
||||
expect(error.stack).toContain('compile-cache-spec.coffee')
|
||||
expect(Array.isArray(error.getRawStack())).toBe true
|
||||
|
@ -7,6 +7,7 @@ class FakeLinesYardstick
|
||||
|
||||
prepareScreenRowsForMeasurement: ->
|
||||
@presenter.getPreMeasurementState()
|
||||
@screenRows = new Set(@presenter.getScreenRows())
|
||||
|
||||
getScopedCharacterWidth: (scopeNames, char) ->
|
||||
@getScopedCharacterWidths(scopeNames)[char]
|
||||
@ -34,6 +35,8 @@ class FakeLinesYardstick
|
||||
left = 0
|
||||
column = 0
|
||||
|
||||
return {top, left: 0} unless @screenRows.has(screenPosition.row)
|
||||
|
||||
iterator = @model.tokenizedLineForScreenRow(targetRow).getTokenIterator()
|
||||
while iterator.next()
|
||||
characterWidths = @getScopedCharacterWidths(iterator.getScopes())
|
||||
|
0
spec/fixtures/testdir/sample-theme-2/src/js/plugin/main.js
vendored
Normal file
0
spec/fixtures/testdir/sample-theme-2/src/js/plugin/main.js
vendored
Normal file
@ -694,6 +694,20 @@ describe "TextEditorPresenter", ->
|
||||
presenter = buildPresenter(explicitHeight: 100, contentFrameWidth: 10 * maxLineLength + 20, baseCharacterWidth: 10, verticalScrollbarWidth: 10)
|
||||
expect(presenter.getState().content.scrollWidth).toBe 10 * maxLineLength + 20 - 10 # subtract vertical scrollbar width
|
||||
|
||||
describe "when the longest screen row is the first one and it's hidden", ->
|
||||
it "doesn't compute an invalid value (regression)", ->
|
||||
presenter = buildPresenter(tileSize: 2, contentFrameWidth: 10, explicitHeight: 20)
|
||||
editor.setText """
|
||||
a very long long long long long long line
|
||||
b
|
||||
c
|
||||
d
|
||||
e
|
||||
"""
|
||||
|
||||
expectStateUpdate presenter, -> presenter.setScrollTop(40)
|
||||
expect(presenter.getState().content.scrollWidth).toBe 10 * editor.getMaxScreenLineLength() + 1
|
||||
|
||||
it "updates when the ::contentFrameWidth changes", ->
|
||||
maxLineLength = editor.getMaxScreenLineLength()
|
||||
presenter = buildPresenter(contentFrameWidth: 50, baseCharacterWidth: 10)
|
||||
@ -1704,6 +1718,18 @@ describe "TextEditorPresenter", ->
|
||||
|
||||
expectUndefinedStateForHighlight(presenter, highlight)
|
||||
|
||||
it "does not include highlights that end before the first visible row", ->
|
||||
editor.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.")
|
||||
editor.setSoftWrapped(true)
|
||||
editor.setWidth(100, true)
|
||||
editor.setDefaultCharWidth(10)
|
||||
|
||||
marker = editor.markBufferRange([[0, 0], [0, 4]], invalidate: 'never')
|
||||
highlight = editor.decorateMarker(marker, type: 'highlight', class: 'a')
|
||||
presenter = buildPresenter(explicitHeight: 30, scrollTop: 10, tileSize: 2)
|
||||
|
||||
expect(stateForHighlightInTile(presenter, highlight, 0)).toBeUndefined()
|
||||
|
||||
it "updates when ::scrollTop changes", ->
|
||||
editor.setSelectedBufferRanges([
|
||||
[[6, 2], [6, 4]],
|
||||
|
@ -168,7 +168,7 @@ describe "TextEditor", ->
|
||||
buffer.setPath(undefined)
|
||||
expect(editor.getLongTitle()).toBe 'untitled'
|
||||
|
||||
it "returns <parent-directory>/<filename> when opened files has identical file names", ->
|
||||
it "returns '<filename> — <parent-directory>' when opened files have identical file names", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
@ -177,10 +177,10 @@ describe "TextEditor", ->
|
||||
atom.workspace.open(path.join('sample-theme-2', 'readme')).then (o) ->
|
||||
editor2 = o
|
||||
runs ->
|
||||
expect(editor1.getLongTitle()).toBe 'sample-theme-1/readme'
|
||||
expect(editor2.getLongTitle()).toBe 'sample-theme-2/readme'
|
||||
expect(editor1.getLongTitle()).toBe "readme \u2014 sample-theme-1"
|
||||
expect(editor2.getLongTitle()).toBe "readme \u2014 sample-theme-2"
|
||||
|
||||
it "or returns <parent-directory>/.../<filename> when opened files has identical file names", ->
|
||||
it "returns '<filename> — <parent-directories>' when opened files have identical file and dir names", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
@ -189,9 +189,20 @@ describe "TextEditor", ->
|
||||
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) ->
|
||||
editor2 = o
|
||||
runs ->
|
||||
expect(editor1.getLongTitle()).toBe 'sample-theme-1/.../main.js'
|
||||
expect(editor2.getLongTitle()).toBe 'sample-theme-2/.../main.js'
|
||||
expect(editor1.getLongTitle()).toBe "main.js \u2014 sample-theme-1/src/js"
|
||||
expect(editor2.getLongTitle()).toBe "main.js \u2014 sample-theme-2/src/js"
|
||||
|
||||
it "returns '<filename> — <parent-directories>' when opened files have identical file and same parent dir name", ->
|
||||
editor1 = null
|
||||
editor2 = null
|
||||
waitsForPromise ->
|
||||
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'main.js')).then (o) ->
|
||||
editor1 = o
|
||||
atom.workspace.open(path.join('sample-theme-2', 'src', 'js', 'plugin', 'main.js')).then (o) ->
|
||||
editor2 = o
|
||||
runs ->
|
||||
expect(editor1.getLongTitle()).toBe "main.js \u2014 js"
|
||||
expect(editor2.getLongTitle()).toBe "main.js \u2014 js/plugin"
|
||||
|
||||
it "notifies ::onDidChangeTitle observers when the underlying buffer path changes", ->
|
||||
observed = []
|
||||
|
@ -154,7 +154,7 @@ 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.brace.round.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[1]).toEqual(value: '(', scopes: ['source.js', 'meta.function-call.js', 'punctuation.definition.arguments.begin.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: '7', scopes: ['source.js', 'constant.numeric.js'])
|
||||
# line 2 is unchanged
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[2]).toEqual(value: 'if', scopes: ['source.js', 'keyword.control.js'])
|
||||
@ -201,7 +201,7 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual(value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
# previous line 3 should be combined with input to form line 1
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js'])
|
||||
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'])
|
||||
|
||||
# lines below deleted regions should be shifted upward
|
||||
@ -245,12 +245,12 @@ describe "TokenizedBuffer", ->
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(0).tokens[0]).toEqual( value: 'var', scopes: ['source.js', 'storage.modifier.js'])
|
||||
|
||||
# 3 new lines inserted
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(1).tokens[0]).toEqual(value: 'foo', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(2).tokens[0]).toEqual(value: 'bar', scopes: ['source.js'])
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(3).tokens[0]).toEqual(value: 'baz', scopes: ['source.js'])
|
||||
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'])
|
||||
|
||||
# previous line 2 is joined with quux() on line 4
|
||||
expect(tokenizedBuffer.tokenizedLineForRow(4).tokens[0]).toEqual(value: 'quux', scopes: ['source.js'])
|
||||
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'])
|
||||
|
||||
# previous line 3 is pushed down to become line 5
|
||||
|
@ -200,3 +200,34 @@ describe "WindowEventHandler", ->
|
||||
|
||||
expect(dispatchedCommands.length).toBe 1
|
||||
expect(dispatchedCommands[0].type).toBe 'foo-command'
|
||||
|
||||
describe "native key bindings", ->
|
||||
it "correctly dispatches them to active elements with the '.native-key-bindings' class", ->
|
||||
webContentsSpy = jasmine.createSpyObj("webContents", ["copy", "paste"])
|
||||
spyOn(atom.applicationDelegate, "getCurrentWindow").andReturn({
|
||||
webContents: webContentsSpy
|
||||
})
|
||||
|
||||
nativeKeyBindingsInput = document.createElement("input")
|
||||
nativeKeyBindingsInput.classList.add("native-key-bindings")
|
||||
jasmine.attachToDOM(nativeKeyBindingsInput)
|
||||
nativeKeyBindingsInput.focus()
|
||||
|
||||
atom.dispatchApplicationMenuCommand("core:copy")
|
||||
atom.dispatchApplicationMenuCommand("core:paste")
|
||||
|
||||
expect(webContentsSpy.copy).toHaveBeenCalled()
|
||||
expect(webContentsSpy.paste).toHaveBeenCalled()
|
||||
|
||||
webContentsSpy.copy.reset()
|
||||
webContentsSpy.paste.reset()
|
||||
|
||||
normalInput = document.createElement("input")
|
||||
jasmine.attachToDOM(normalInput)
|
||||
normalInput.focus()
|
||||
|
||||
atom.dispatchApplicationMenuCommand("core:copy")
|
||||
atom.dispatchApplicationMenuCommand("core:paste")
|
||||
|
||||
expect(webContentsSpy.copy).not.toHaveBeenCalled()
|
||||
expect(webContentsSpy.paste).not.toHaveBeenCalled()
|
||||
|
@ -76,7 +76,7 @@ describe "Workspace", ->
|
||||
expect(editor4.getCursorScreenPosition()).toEqual [2, 4]
|
||||
|
||||
expect(atom.workspace.getActiveTextEditor().getPath()).toBe editor3.getPath()
|
||||
expect(document.title).toBe "#{path.basename(editor3.getPath())} - #{atom.project.getPaths()[0]} - Atom"
|
||||
expect(document.title).toBe "#{path.basename(editor3.getLongTitle())} - #{atom.project.getPaths()[0]} - Atom"
|
||||
|
||||
describe "where there are no open panes or editors", ->
|
||||
it "constructs the view with no open editors", ->
|
||||
@ -658,6 +658,13 @@ describe "Workspace", ->
|
||||
waitsForPromise -> workspace.openLicense()
|
||||
runs -> expect(workspace.getActivePaneItem().getText()).toMatch /Copyright/
|
||||
|
||||
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({getText: ->})).toBe(false)
|
||||
expect(workspace.isTextEditor(null)).toBe(false)
|
||||
expect(workspace.isTextEditor(undefined)).toBe(false)
|
||||
|
||||
describe "::observeTextEditors()", ->
|
||||
it "invokes the observer with current and future text editors", ->
|
||||
observed = []
|
||||
@ -776,8 +783,8 @@ describe "Workspace", ->
|
||||
applicationDelegate: atom.applicationDelegate, assert: atom.assert.bind(atom)
|
||||
})
|
||||
workspace2.deserialize(atom.workspace.serialize(), atom.deserializers)
|
||||
item = atom.workspace.getActivePaneItem()
|
||||
expect(document.title).toBe "#{item.getTitle()} - #{atom.project.getPaths()[0]} - Atom"
|
||||
item = workspace2.getActivePaneItem()
|
||||
expect(document.title).toBe "#{item.getLongTitle()} - #{atom.project.getPaths()[0]} - Atom"
|
||||
workspace2.destroy()
|
||||
|
||||
describe "document edited status", ->
|
||||
@ -1438,11 +1445,12 @@ describe "Workspace", ->
|
||||
save = -> atom.workspace.saveActivePaneItem()
|
||||
expect(save).toThrow()
|
||||
|
||||
describe "::destroyActivePaneItemOrEmptyPane", ->
|
||||
describe "::closeActivePaneItemOrEmptyPaneOrWindow", ->
|
||||
beforeEach ->
|
||||
spyOn(atom, 'close')
|
||||
waitsForPromise -> atom.workspace.open()
|
||||
|
||||
it "closes the active pane item until all that remains is a single empty pane", ->
|
||||
it "closes the active pane item, or the active pane if it is empty, or the current window if there is only the empty root pane", ->
|
||||
atom.config.set('core.destroyEmptyPanes', false)
|
||||
|
||||
pane1 = atom.workspace.getActivePane()
|
||||
@ -1450,19 +1458,22 @@ describe "Workspace", ->
|
||||
|
||||
expect(atom.workspace.getPanes().length).toBe 2
|
||||
expect(pane2.getItems().length).toBe 1
|
||||
atom.workspace.destroyActivePaneItemOrEmptyPane()
|
||||
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
|
||||
expect(atom.workspace.getPanes().length).toBe 2
|
||||
expect(pane2.getItems().length).toBe 0
|
||||
|
||||
atom.workspace.destroyActivePaneItemOrEmptyPane()
|
||||
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
|
||||
expect(atom.workspace.getPanes().length).toBe 1
|
||||
expect(pane1.getItems().length).toBe 1
|
||||
|
||||
atom.workspace.destroyActivePaneItemOrEmptyPane()
|
||||
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
expect(atom.workspace.getPanes().length).toBe 1
|
||||
expect(pane1.getItems().length).toBe 0
|
||||
|
||||
atom.workspace.destroyActivePaneItemOrEmptyPane()
|
||||
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
expect(atom.workspace.getPanes().length).toBe 1
|
||||
|
||||
atom.workspace.closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
expect(atom.close).toHaveBeenCalled()
|
||||
|
@ -66,13 +66,42 @@ class ApplicationDelegate
|
||||
ipc.send("call-window-method", "setFullScreen", fullScreen)
|
||||
|
||||
openWindowDevTools: ->
|
||||
remote.getCurrentWindow().openDevTools()
|
||||
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())
|
||||
ipc.send("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())
|
||||
ipc.send("call-window-method", "closeDevTools")
|
||||
|
||||
toggleWindowDevTools: ->
|
||||
remote.getCurrentWindow().toggleDevTools()
|
||||
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)
|
||||
|
||||
executeJavaScriptInWindowDevTools: (code) ->
|
||||
remote.getCurrentWindow().executeJavaScriptInDevTools(code)
|
||||
ipc.send("call-window-method", "executeJavaScriptInDevTools", code)
|
||||
|
||||
setWindowDocumentEdited: (edited) ->
|
||||
ipc.send("call-window-method", "setDocumentEdited", edited)
|
||||
@ -138,7 +167,7 @@ class ApplicationDelegate
|
||||
|
||||
ipc.on('message', outerCallback)
|
||||
new Disposable ->
|
||||
ipc.removeEventListener('message', outerCallback)
|
||||
ipc.removeListener('message', outerCallback)
|
||||
|
||||
onUpdateAvailable: (callback) ->
|
||||
outerCallback = (message, detail) ->
|
||||
@ -147,17 +176,17 @@ class ApplicationDelegate
|
||||
|
||||
ipc.on('message', outerCallback)
|
||||
new Disposable ->
|
||||
ipc.removeEventListener('message', outerCallback)
|
||||
ipc.removeListener('message', outerCallback)
|
||||
|
||||
onApplicationMenuCommand: (callback) ->
|
||||
ipc.on('command', callback)
|
||||
new Disposable ->
|
||||
ipc.removeEventListener('command', callback)
|
||||
ipc.removeListener('command', callback)
|
||||
|
||||
onContextMenuCommand: (callback) ->
|
||||
ipc.on('context-command', callback)
|
||||
new Disposable ->
|
||||
ipc.removeEventListener('context-command', callback)
|
||||
ipc.removeListener('context-command', callback)
|
||||
|
||||
didCancelWindowUnload: ->
|
||||
ipc.send('did-cancel-window-unload')
|
||||
|
@ -623,7 +623,7 @@ class AtomEnvironment extends Model
|
||||
@registerDefaultTargetForKeymaps()
|
||||
|
||||
@packages.loadPackages()
|
||||
|
||||
@loadStateSync()
|
||||
@document.body.appendChild(@views.getView(@workspace))
|
||||
|
||||
@watchProjectPath()
|
||||
@ -670,8 +670,7 @@ class AtomEnvironment extends Model
|
||||
@emitter.emit 'will-throw-error', eventObject
|
||||
|
||||
if openDevTools
|
||||
@openDevTools()
|
||||
@executeJavaScriptInDevTools('DevToolsAPI.showConsole()')
|
||||
@openDevTools().then => @executeJavaScriptInDevTools('DevToolsAPI.showConsole()')
|
||||
|
||||
@emitter.emit 'did-throw-error', {message, url, line, column, originalError}
|
||||
|
||||
@ -721,10 +720,15 @@ class AtomEnvironment extends Model
|
||||
###
|
||||
|
||||
# Extended: Open the dev tools for the current window.
|
||||
#
|
||||
# Returns a {Promise} that resolves when the DevTools have been opened.
|
||||
openDevTools: ->
|
||||
@applicationDelegate.openWindowDevTools()
|
||||
|
||||
# Extended: Toggle the visibility of the dev tools for the current window.
|
||||
#
|
||||
# Returns a {Promise} that resolves when the DevTools have been opened or
|
||||
# closed.
|
||||
toggleDevTools: ->
|
||||
@applicationDelegate.toggleWindowDevTools()
|
||||
|
||||
|
@ -373,6 +373,8 @@ class AtomApplication
|
||||
# :windowDimensions - Object with height and width keys.
|
||||
# :window - {AtomWindow} to open file paths in.
|
||||
openPaths: ({pathsToOpen, executedFrom, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, profileStartup, window}={}) ->
|
||||
devMode = Boolean(devMode)
|
||||
safeMode = Boolean(safeMode)
|
||||
locationsToOpen = (@locationForPathToOpen(pathToOpen, executedFrom) for pathToOpen in pathsToOpen)
|
||||
pathsToOpen = (locationToOpen.pathToOpen for locationToOpen in locationsToOpen)
|
||||
|
||||
|
@ -158,25 +158,33 @@ require('source-map-support').install({
|
||||
}
|
||||
})
|
||||
|
||||
var sourceMapPrepareStackTrace = Error.prepareStackTrace
|
||||
var prepareStackTrace = sourceMapPrepareStackTrace
|
||||
var prepareStackTraceWithSourceMapping = Error.prepareStackTrace
|
||||
|
||||
// Prevent coffee-script from reassigning Error.prepareStackTrace
|
||||
Object.defineProperty(Error, 'prepareStackTrace', {
|
||||
get: function () { return prepareStackTrace },
|
||||
set: function (newValue) {}
|
||||
})
|
||||
let prepareStackTrace = prepareStackTraceWithSourceMapping
|
||||
|
||||
// Enable Grim to access the raw stack without reassigning Error.prepareStackTrace
|
||||
Error.prototype.getRawStack = function () { // eslint-disable-line no-extend-native
|
||||
prepareStackTrace = getRawStack
|
||||
var result = this.stack
|
||||
prepareStackTrace = sourceMapPrepareStackTrace
|
||||
return result
|
||||
function prepareStackTraceWithRawStackAssignment (error, frames) {
|
||||
error.rawStack = frames
|
||||
return prepareStackTrace(error, frames)
|
||||
}
|
||||
|
||||
function getRawStack (_, stack) {
|
||||
return stack
|
||||
Object.defineProperty(Error, 'prepareStackTrace', {
|
||||
get: function () {
|
||||
return prepareStackTraceWithRawStackAssignment
|
||||
},
|
||||
|
||||
set: function (newValue) {
|
||||
prepareStackTrace = newValue
|
||||
process.nextTick(function () {
|
||||
prepareStackTrace = prepareStackTraceWithSourceMapping
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Error.prototype.getRawStack = function () { // eslint-disable-line no-extend-native
|
||||
// Access this.stack to ensure prepareStackTrace has been run on this error
|
||||
// because it assigns this.rawStack as a side-effect
|
||||
this.stack
|
||||
return this.rawStack
|
||||
}
|
||||
|
||||
Object.keys(COMPILERS).forEach(function (extension) {
|
||||
|
@ -21,7 +21,6 @@ module.exports =
|
||||
followSymlinks:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
title: 'Follow symlinks'
|
||||
description: 'Follow symbolic links when searching files and when opening files with the fuzzy finder.'
|
||||
disabledPackages:
|
||||
type: 'array'
|
||||
@ -54,7 +53,12 @@ module.exports =
|
||||
destroyEmptyPanes:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
description: 'When the last item of a pane is removed, remove that pane as well.'
|
||||
title: 'Remove Empty Panes'
|
||||
description: 'When the last tab of a pane is closed, remove that pane as well.'
|
||||
closeEmptyWindows:
|
||||
type: 'boolean'
|
||||
default: true
|
||||
description: 'When a window with no open tabs or panes is given the \'Close Tab\' command, close that window.'
|
||||
fileEncoding:
|
||||
description: 'Default character set encoding to use when reading and writing files.'
|
||||
type: 'string'
|
||||
|
@ -699,7 +699,7 @@ class Config
|
||||
@endTransaction()
|
||||
fn(args...)
|
||||
result = callback()
|
||||
new Promise (resolve, reject) =>
|
||||
new Promise (resolve, reject) ->
|
||||
result.then(endTransaction(resolve)).catch(endTransaction(reject))
|
||||
catch error
|
||||
@endTransaction()
|
||||
|
@ -1,8 +1,7 @@
|
||||
Task = require './task'
|
||||
|
||||
# Public: Searches local files for lines matching a specified regex.
|
||||
#
|
||||
# Implements thenable so it can be used with `Promise.all()`.
|
||||
# Searches local files for lines matching a specified regex. Implements `.then()`
|
||||
# so that it can be used with `Promise.all()`.
|
||||
class DirectorySearch
|
||||
constructor: (rootPaths, regex, options) ->
|
||||
scanHandlerOptions =
|
||||
@ -22,31 +21,25 @@ class DirectorySearch
|
||||
@task.terminate()
|
||||
resolve()
|
||||
|
||||
# Public: Implementation of `then()` to satisfy the *thenable* contract.
|
||||
# This makes it possible to use a `DirectorySearch` with `Promise.all()`.
|
||||
#
|
||||
# Returns `Promise`.
|
||||
then: (args...) ->
|
||||
@promise.then.apply(@promise, args)
|
||||
|
||||
# Public: Cancels the search.
|
||||
cancel: ->
|
||||
# This will cause @promise to reject.
|
||||
@task.cancel()
|
||||
null
|
||||
|
||||
|
||||
# Default provider for the `atom.directory-searcher` service.
|
||||
module.exports =
|
||||
class DefaultDirectorySearcher
|
||||
# Public: Determines whether this object supports search for a `Directory`.
|
||||
# Determines whether this object supports search for a `Directory`.
|
||||
#
|
||||
# * `directory` {Directory} whose search needs might be supported by this object.
|
||||
#
|
||||
# Returns a `boolean` indicating whether this object can search this `Directory`.
|
||||
canSearchDirectory: (directory) -> true
|
||||
|
||||
# Public: Performs a text search for files in the specified `Directory`, subject to the
|
||||
# Performs a text search for files in the specified `Directory`, subject to the
|
||||
# specified parameters.
|
||||
#
|
||||
# Results are streamed back to the caller by invoking methods on the specified `options`,
|
||||
|
@ -24,7 +24,6 @@ module.exports = ({blobStore}) ->
|
||||
})
|
||||
|
||||
atom.displayWindow()
|
||||
atom.loadStateSync()
|
||||
atom.startEditorWindow()
|
||||
|
||||
# Workaround for focus getting cleared upon window creation
|
||||
|
@ -21,16 +21,7 @@ module.exports = ({blobStore}) ->
|
||||
|
||||
{testRunnerPath, legacyTestRunnerPath, headless, logFile, testPaths} = getWindowLoadSettings()
|
||||
|
||||
if headless
|
||||
# Override logging in headless mode so it goes to the console, regardless
|
||||
# of the --enable-logging flag to Electron.
|
||||
console.log = (args...) ->
|
||||
ipc.send 'write-to-stdout', args.join(' ') + '\n'
|
||||
console.warn = (args...) ->
|
||||
ipc.send 'write-to-stderr', args.join(' ') + '\n'
|
||||
console.error = (args...) ->
|
||||
ipc.send 'write-to-stderr', args.join(' ') + '\n'
|
||||
else
|
||||
unless headless
|
||||
# Show window synchronously so a focusout doesn't fire on input elements
|
||||
# that are focused in the very first spec run.
|
||||
remote.getCurrentWindow().show()
|
||||
|
@ -55,7 +55,7 @@ module.exports = ({commandRegistry, commandInstaller, config}) ->
|
||||
'window:log-deprecation-warnings': -> Grim.logDeprecations()
|
||||
'window:toggle-auto-indent': -> config.set("editor.autoIndent", not config.get("editor.autoIndent"))
|
||||
'pane:reopen-closed-item': -> @getModel().reopenItem()
|
||||
'core:close': -> @getModel().destroyActivePaneItemOrEmptyPane()
|
||||
'core:close': -> @getModel().closeActivePaneItemOrEmptyPaneOrWindow()
|
||||
'core:save': -> @getModel().saveActivePaneItem()
|
||||
'core:save-as': -> @getModel().saveActivePaneItemAs()
|
||||
|
||||
|
@ -377,7 +377,8 @@ class TextEditorPresenter
|
||||
endRow = @constrainRow(@getEndTileRow() + @tileSize)
|
||||
|
||||
screenRows = [startRow...endRow]
|
||||
if longestScreenRow = @model.getLongestScreenRow()
|
||||
longestScreenRow = @model.getLongestScreenRow()
|
||||
if longestScreenRow?
|
||||
screenRows.push(longestScreenRow)
|
||||
if @screenRowsToMeasure?
|
||||
screenRows.push(@screenRowsToMeasure...)
|
||||
@ -1244,14 +1245,7 @@ class TextEditorPresenter
|
||||
updateHighlightState: (decorationId, properties, screenRange) ->
|
||||
return unless @startRow? and @endRow? and @lineHeight? and @hasPixelPositionRequirements()
|
||||
|
||||
return if screenRange.isEmpty()
|
||||
|
||||
if screenRange.start.row < @startRow
|
||||
screenRange.start.row = @startRow
|
||||
screenRange.start.column = 0
|
||||
if screenRange.end.row >= @endRow
|
||||
screenRange.end.row = @endRow
|
||||
screenRange.end.column = 0
|
||||
@constrainRangeToVisibleRowRange(screenRange)
|
||||
|
||||
return if screenRange.isEmpty()
|
||||
|
||||
@ -1281,6 +1275,23 @@ class TextEditorPresenter
|
||||
|
||||
true
|
||||
|
||||
constrainRangeToVisibleRowRange: (screenRange) ->
|
||||
if screenRange.start.row < @startRow
|
||||
screenRange.start.row = @startRow
|
||||
screenRange.start.column = 0
|
||||
|
||||
if screenRange.end.row < @startRow
|
||||
screenRange.end.row = @startRow
|
||||
screenRange.end.column = 0
|
||||
|
||||
if screenRange.start.row >= @endRow
|
||||
screenRange.start.row = @endRow
|
||||
screenRange.start.column = 0
|
||||
|
||||
if screenRange.end.row >= @endRow
|
||||
screenRange.end.row = @endRow
|
||||
screenRange.end.column = 0
|
||||
|
||||
repositionRegionWithinTile: (region, tileStartRow) ->
|
||||
region.top += @scrollTop - tileStartRow * @lineHeight
|
||||
region.left += @scrollLeft
|
||||
|
@ -581,10 +581,7 @@ class TextEditor extends Model
|
||||
#
|
||||
# Returns a {String}.
|
||||
getTitle: ->
|
||||
if sessionPath = @getPath()
|
||||
path.basename(sessionPath)
|
||||
else
|
||||
'untitled'
|
||||
@getFileName() ? 'untitled'
|
||||
|
||||
# Essential: Get unique title for display in other parts of the UI, such as
|
||||
# the window title.
|
||||
@ -593,41 +590,52 @@ class TextEditor extends Model
|
||||
# If the editor's buffer is saved, its unique title is formatted as one
|
||||
# of the following,
|
||||
# * "<filename>" when it is the only editing buffer with this file name.
|
||||
# * "<unique-dir-prefix>/.../<filename>", where the "..." may be omitted
|
||||
# if the the direct parent directory is already different.
|
||||
# * "<filename> — <unique-dir-prefix>" when other buffers have this file name.
|
||||
#
|
||||
# Returns a {String}
|
||||
getLongTitle: ->
|
||||
if sessionPath = @getPath()
|
||||
title = @getTitle()
|
||||
if @getPath()
|
||||
fileName = @getFileName()
|
||||
|
||||
# find text editors with identical file name.
|
||||
paths = []
|
||||
allPathSegments = []
|
||||
for textEditor in atom.workspace.getTextEditors() when textEditor isnt this
|
||||
if textEditor.getTitle() is title
|
||||
paths.push(textEditor.getPath())
|
||||
if paths.length is 0
|
||||
return title
|
||||
fileName = path.basename(sessionPath)
|
||||
if textEditor.getFileName() is fileName
|
||||
allPathSegments.push(textEditor.getDirectoryPath().split(path.sep))
|
||||
|
||||
# find the first directory in all these paths that is unique
|
||||
nLevel = 0
|
||||
while (_.some(paths, (apath) -> path.basename(apath) is path.basename(sessionPath)))
|
||||
sessionPath = path.dirname(sessionPath)
|
||||
paths = _.map(paths, (apath) -> path.dirname(apath))
|
||||
nLevel += 1
|
||||
if allPathSegments.length is 0
|
||||
return fileName
|
||||
|
||||
directory = path.basename sessionPath
|
||||
if nLevel > 1
|
||||
path.join(directory, "...", fileName)
|
||||
else
|
||||
path.join(directory, fileName)
|
||||
ourPathSegments = @getDirectoryPath().split(path.sep)
|
||||
allPathSegments.push ourPathSegments
|
||||
|
||||
loop
|
||||
firstSegment = ourPathSegments[0]
|
||||
|
||||
commonBase = _.all(allPathSegments, (pathSegments) -> pathSegments.length > 1 and pathSegments[0] is firstSegment)
|
||||
if commonBase
|
||||
pathSegments.shift() for pathSegments in allPathSegments
|
||||
else
|
||||
break
|
||||
|
||||
"#{fileName} \u2014 #{path.join(pathSegments...)}"
|
||||
else
|
||||
'untitled'
|
||||
|
||||
# Essential: Returns the {String} path of this editor's text buffer.
|
||||
getPath: -> @buffer.getPath()
|
||||
|
||||
getFileName: ->
|
||||
if fullPath = @getPath()
|
||||
path.basename(fullPath)
|
||||
else
|
||||
null
|
||||
|
||||
getDirectoryPath: ->
|
||||
if fullPath = @getPath()
|
||||
path.dirname(fullPath)
|
||||
else
|
||||
null
|
||||
|
||||
# Extended: Returns the {String} character set encoding of this editor's text
|
||||
# buffer.
|
||||
getEncoding: -> @buffer.getEncoding()
|
||||
@ -678,16 +686,16 @@ class TextEditor extends Model
|
||||
getSaveDialogOptions: -> {}
|
||||
|
||||
checkoutHeadRevision: ->
|
||||
if filePath = this.getPath()
|
||||
if @getPath()
|
||||
checkoutHead = =>
|
||||
@project.repositoryForDirectory(new Directory(path.dirname(filePath)))
|
||||
@project.repositoryForDirectory(new Directory(@getDirectoryPath()))
|
||||
.then (repository) =>
|
||||
repository?.async.checkoutHeadForEditor(this)
|
||||
|
||||
if @config.get('editor.confirmCheckoutHeadRevision')
|
||||
@applicationDelegate.confirm
|
||||
message: 'Confirm Checkout HEAD Revision'
|
||||
detailedMessage: "Are you sure you want to discard all changes to \"#{path.basename(filePath)}\" since the last Git commit?"
|
||||
detailedMessage: "Are you sure you want to discard all changes to \"#{@getFileName()}\" since the last Git commit?"
|
||||
buttons:
|
||||
OK: checkoutHead
|
||||
Cancel: null
|
||||
|
@ -42,9 +42,8 @@ class WindowEventHandler
|
||||
# `.native-key-bindings` class.
|
||||
handleNativeKeybindings: ->
|
||||
bindCommandToAction = (command, action) =>
|
||||
@addEventListener @document, command, (event) =>
|
||||
if event.target.webkitMatchesSelector('.native-key-bindings')
|
||||
@applicationDelegate.getCurrentWindow().webContents[action]()
|
||||
@subscriptions.add @atomEnvironment.commands.add '.native-key-bindings', command, (event) =>
|
||||
@applicationDelegate.getCurrentWindow().webContents[action]()
|
||||
|
||||
bindCommandToAction('core:copy', 'copy')
|
||||
bindCommandToAction('core:paste', 'paste')
|
||||
|
@ -155,7 +155,7 @@ class Workspace extends Model
|
||||
projectPaths = @project.getPaths() ? []
|
||||
if item = @getActivePaneItem()
|
||||
itemPath = item.getPath?()
|
||||
itemTitle = item.getTitle?()
|
||||
itemTitle = item.getLongTitle?() ? item.getTitle?()
|
||||
projectPath = _.find projectPaths, (projectPath) ->
|
||||
itemPath is projectPath or itemPath?.startsWith(projectPath + path.sep)
|
||||
itemTitle ?= "untitled"
|
||||
@ -518,6 +518,12 @@ class Workspace extends Model
|
||||
@project.bufferForPath(filePath, options).then (buffer) =>
|
||||
@buildTextEditor(_.extend({buffer, largeFileMode}, options))
|
||||
|
||||
# Public: Returns a {Boolean} that is `true` if `object` is a `TextEditor`.
|
||||
#
|
||||
# * `object` An {Object} you want to perform the check against.
|
||||
isTextEditor: (object) ->
|
||||
object instanceof TextEditor
|
||||
|
||||
# Extended: Create a new text editor.
|
||||
#
|
||||
# Returns a {TextEditor}.
|
||||
@ -675,9 +681,15 @@ class Workspace extends Model
|
||||
destroyActivePane: ->
|
||||
@getActivePane()?.destroy()
|
||||
|
||||
# Destroy the active pane item or the active pane if it is empty.
|
||||
destroyActivePaneItemOrEmptyPane: ->
|
||||
if @getActivePaneItem()? then @destroyActivePaneItem() else @destroyActivePane()
|
||||
# Close the active pane item, or the active pane if it is empty,
|
||||
# or the current window if there is only the empty root pane.
|
||||
closeActivePaneItemOrEmptyPaneOrWindow: ->
|
||||
if @getActivePaneItem()?
|
||||
@destroyActivePaneItem()
|
||||
else if @getPanes().length > 1
|
||||
@destroyActivePane()
|
||||
else if @config.get('core.closeEmptyWindows')
|
||||
atom.close()
|
||||
|
||||
# Increase the editor font size by 1px.
|
||||
increaseFontSize: ->
|
||||
|
@ -31,12 +31,18 @@
|
||||
font-size: @font-size - 2px;
|
||||
height: auto;
|
||||
line-height: 1.3em;
|
||||
&.icon:before {
|
||||
font-size: @font-size - 2px;
|
||||
}
|
||||
}
|
||||
.btn.btn-sm,
|
||||
.btn-group-sm > .btn {
|
||||
padding: @component-padding/4 @component-padding/2;
|
||||
height: auto;
|
||||
line-height: 1.3em;
|
||||
&.icon:before {
|
||||
font-size: @font-size + 1px;
|
||||
}
|
||||
}
|
||||
.btn.btn-lg,
|
||||
.btn-group-lg > .btn {
|
||||
@ -44,6 +50,9 @@
|
||||
padding: @component-padding - 2px @component-padding + 2px;
|
||||
height: auto;
|
||||
line-height: 1.3em;
|
||||
&.icon:before {
|
||||
font-size: @font-size + 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-group > .btn {
|
||||
@ -63,6 +72,18 @@
|
||||
border-bottom-right-radius: @component-border-radius;
|
||||
}
|
||||
|
||||
// Icon buttons
|
||||
.btn.icon {
|
||||
&:before {
|
||||
width: initial;
|
||||
height: initial;
|
||||
margin-right: .3125em;
|
||||
}
|
||||
&:empty:before {
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-toolbar {
|
||||
> .btn-group + .btn-group, > .btn-group + .btn, > .btn + .btn {
|
||||
float: none;
|
||||
|
Loading…
Reference in New Issue
Block a user