Comparar commits
166 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| e3f4a72ab3 | |||
| ee3b7cee76 | |||
| 5a357a54dc | |||
| d07bf338c8 | |||
| 516ddec854 | |||
| 0ab2b89c1a | |||
| 2c2c7e67d7 | |||
| e1f8b042ed | |||
| f7ce6a015d | |||
| 4775783ba3 | |||
| d0bf4c1d2e | |||
| 4f1d862bc0 | |||
| 059671c454 | |||
| 1f16cd3912 | |||
| 2d16fc33a3 | |||
| 6ad8062d45 | |||
| 8f0c0362e8 | |||
| 91436bec25 | |||
| e93d83dcdf | |||
| 62f44e64f4 | |||
| c571d6a9d4 | |||
| bdd4ac63f4 | |||
| 0c77712a77 | |||
| a00db81765 | |||
| c91bca44cb | |||
| dbf4ba099b | |||
| e67324dcc9 | |||
| 1528d6ea49 | |||
| a49fd569e3 | |||
| 44213aff96 | |||
| 22589bf2dd | |||
| 28a2b48688 | |||
| 668ef0b3a1 | |||
| 9a4db9d95d | |||
| e457600f38 | |||
| 2f62123a75 | |||
| e7e28b568b | |||
| b70df78041 | |||
| c4b24fe738 | |||
| b1f5d1e276 | |||
| cd9d6ca6ee | |||
| d6159a38d4 | |||
| a828f389f4 | |||
| 91c8371752 | |||
| 05c70aceec | |||
| 002fc570e7 | |||
| f81c64f068 | |||
| e9bcb4637e | |||
| e21f1c1394 | |||
| eae5a25872 | |||
| 6364589630 | |||
| 41f6d6b0dd | |||
| c581135029 | |||
| af92c96a73 | |||
| cdd4c9669a | |||
| 1368b60f16 | |||
| cc42db3bff | |||
| cc3a2ab2d5 | |||
| f9837aadaa | |||
| 20c7f298a9 | |||
| 86506752a7 | |||
| 83206ac3a7 | |||
| dc54ebf416 | |||
| d5b960f32b | |||
| ffaaa21b37 | |||
| ef2a322229 | |||
| 1931cb6dff | |||
| 6040221d26 | |||
| 7c70c43c1c | |||
| cde0fae1f3 | |||
| 95107052d0 | |||
| 650915724b | |||
| ad67abc2a2 | |||
| 50d2d5b1cd | |||
| 010905db0b | |||
| 232bc8be8e | |||
| 57577966e7 | |||
| 08d5231d28 | |||
| 05c3d89381 | |||
| 7a3dc2c3b8 | |||
| 8eecc56d08 | |||
| e009ff6c59 | |||
| f500e2e9fc | |||
| 2a98ccec8d | |||
| 8742f6c06c | |||
| 9605da9d56 | |||
| 1cdb87fdce | |||
| 330bb1df4b | |||
| 45ceb3f9f9 | |||
| 3fa7c8fb48 | |||
| 97c183d6df | |||
| 42362e6ce9 | |||
| 2266ea25e8 | |||
| 970d7654cb | |||
| 82cbfb3829 | |||
| c2c6b5f868 | |||
| 0dd0c39918 | |||
| 7002b4e5f6 | |||
| 78f1865bcf | |||
| bb281ce5af | |||
| b02d906cfb | |||
| b5b07c1052 | |||
| c77b44d5ef | |||
| eba1e474f8 | |||
| 6fa580f543 | |||
| feed72b68e | |||
| 5cee47c207 | |||
| 1d1a14b8e9 | |||
| 18421465c0 | |||
| ea9930db70 | |||
| 2d40cb09d1 | |||
| 8956881192 | |||
| 32bc8a6258 | |||
| 30c1124e5e | |||
| 63cb53b169 | |||
| 17ebb079eb | |||
| 9f4f3d26e5 | |||
| 8bc9c9aba3 | |||
| 2e20c7696e | |||
| 78bb8b473b | |||
| a0fb4333d5 | |||
| 197291e453 | |||
| bafea9b95b | |||
| 23b635db1e | |||
| 7aa57c44f8 | |||
| ece0ea2a54 | |||
| f22732b109 | |||
| 71b9188ece | |||
| a2017628bc | |||
| cf025639bd | |||
| df6ebddc69 | |||
| aa2734f3bf | |||
| b9e3a8bd40 | |||
| 2a3a38a5f8 | |||
| 0254812446 | |||
| 11186f627e | |||
| db44df040e | |||
| cdf439b556 | |||
| e4fc15deec | |||
| 53547b5a8d | |||
| 6460cbe288 | |||
| 29646cdff8 | |||
| feff67457d | |||
| 1f30231d5c | |||
| 3e584f29b1 | |||
| c424f7bafa | |||
| 48fbdc69fb | |||
| c1b0ba2773 | |||
| d4949c872b | |||
| a8a28c8635 | |||
| 6f47010a72 | |||
| 39fb929af6 | |||
| 1b8f8cd914 | |||
| b288a5c68f | |||
| b79068ea65 | |||
| afb2ec86b7 | |||
| f2f915c0d0 | |||
| 8503a53fec | |||
| d0ed2a87cd | |||
| eeb24e1d5c | |||
| d805b6f6ac | |||
| 58ef0f4176 | |||
| 6ed3bb48f2 | |||
| 814ab4e980 | |||
| ffbce2020e | |||
| 0fc2f70dc5 |
-101
@@ -1,101 +0,0 @@
|
||||
* Improved: Faster and better looking find and replace
|
||||
* Improved: Double-click selection behavior between word/non-word
|
||||
* Added: Solarized theme now bundled by default
|
||||
* Added: Base16 Tomorrow Dark theme now bundled by default
|
||||
|
||||
* Fixed: Make Atom's version the same as Speakeasy's version
|
||||
|
||||
* Fixed: Package generator package not opening window to generated package
|
||||
|
||||
* Fixed: Precompile bootstrap.less for faster startup
|
||||
|
||||
* Fixed: Save sometimes failing from an editor that was split
|
||||
* Fixed: Search results not appearing when set to exclude ignores
|
||||
|
||||
* Fixed: Status bar and gutter displaying incorrect Git status information
|
||||
* Fixed: Packages not installing from the Settings view
|
||||
* Fixed: Spec runner now works from a released build
|
||||
* Fixed: Literate CoffeeScript not syntax highlighting correctly
|
||||
|
||||
* Added: Soft wrap and tab length can now be set in the settings view
|
||||
* Fixed: Python import statements not syntax highlighting correctly
|
||||
|
||||
* Added: Terminal package now bundled by default, open with ctrl-`
|
||||
* Fixed: Fuzzy finder not showing results for files at a certain depth
|
||||
* Fixed: Atom > Preferences... menu not opening settings in focused window
|
||||
|
||||
* Fixed: Atom failing to launch if the theme being used was not found
|
||||
|
||||
* Improved: Theme changes now immediately take effect
|
||||
* Fixed: Wrap in quotes/parens now works in split panes
|
||||
* Improved: Autocomplete now includes CSS property names and values
|
||||
* Improved: Settings GUI is now a pane item
|
||||
* Added: Support package filtering in Settings GUI
|
||||
* Added: Dynamically load all config options in the Settings GUI
|
||||
* Added: Ability to bookmark lines and navigate bookmarks
|
||||
* Fixed: Error when inserting newlines in CSS
|
||||
* Fixed: Folding all will fold comments as well
|
||||
* Added: Ability to fold all code at a given indentation level
|
||||
|
||||
* Improved: cmd-n now opens a new tab and cmd-shift-n now opens a new window.
|
||||
* Added: Inspect Element context menu
|
||||
* Fixed: Save As dialog now defaults to directory path of current editor
|
||||
* Fixed: Using toggle comment shortcut respects indentation level
|
||||
|
||||
* Fixed: Search never completing in the command panel
|
||||
|
||||
* Fixed: cmd-n now works when no windows are open
|
||||
|
||||
* Fixed: Error selecting a grammar for an untitled editor
|
||||
|
||||
* Added: j/k now can be used to navigate the tree view and archive editor
|
||||
|
||||
* Fixed: Atom can now be launched when ~/.atom/config.cson doesn't exist
|
||||
* Added: Initial collaboration sessions
|
||||
* Fixed: Empty lines being deleted via uppercase/downcase command
|
||||
* Fixed: Keybindings not working when using non-English keyboard language
|
||||
* Fixed: cmd-shift-p and cmd-alt-w not doing anything when pressed
|
||||
|
||||
* Improved: Use grunt (instead of rake) for build system
|
||||
* Fixed: Java files not syntax highlighting correctly.
|
||||
* Fixed: LESS/CSS now indents properly after hitting enter.
|
||||
* Added: Support for browsing .tar.gz and .zip files in the editor
|
||||
* Added: TODO/FIXME/CHANGED are now highlighted in comments.
|
||||
* Fixed: Full screen state of windows is now persisted across restarts.
|
||||
* Added: Makefile syntax highlighting now included.
|
||||
* Added: Open fuzzy finder to specific line using colon suffix (i.e ':25')
|
||||
* Fixed: Issues deleting and moving over certain UTF-8 characters
|
||||
* Fixed: Tree view not properly highlighting or revealing for open images.
|
||||
* Added: Packages can now be installed from the configuration UI.
|
||||
* Fixed: .git folder now ignored by default when searching
|
||||
|
||||
* Fixed: Not being able to disable packages from configuration UI.
|
||||
* Fixed: Fuzzy finder showing poor results for entered text
|
||||
* Improved: App icon
|
||||
|
||||
* Fixed: Fuzzy finder being empty sometimes
|
||||
|
||||
* Improved: App icon
|
||||
* Fixed: End of line invisibles rendering incorrectly with the indent guide
|
||||
* Fixed: Updates not installing automatically on restart
|
||||
* Fixed: Wrap guide not displaying
|
||||
* Fixed: Error when saving with the markdown preview focused
|
||||
|
||||
* Fixed: Atom always running in dev mode
|
||||
* Fixed: Crash when running in dev mode without a path to the Atom source
|
||||
|
||||
* Fixed: Freeze when editing a RoR class
|
||||
* Added: meta-N to open a new untitled editor in the current window
|
||||
|
||||
* Fixed: Styling in command logger
|
||||
* Added: XML and Ruby syntax highlighting in Markdown files
|
||||
* Fixed: Error when editing files in a HEAD-less Git repository
|
||||
|
||||
* Fixed: Invisible characters not being visible when enabled
|
||||
* Added: Editor gutter now displays Git status for lines
|
||||
|
||||
* Improved: Startup time
|
||||
* Added: SQL bundle now included
|
||||
* Added: PEG.js bundle now included
|
||||
* Added: Hyperlinks can now be opened with ctrl-O
|
||||
* Fixed: PHP syntax highlighting
|
||||
|
||||
+22
-8
@@ -8,14 +8,24 @@ _ = require 'underscore-plus'
|
||||
packageJson = require './package.json'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
appName = 'Atom.app'
|
||||
[major, minor, patch] = packageJson.version.split('.')
|
||||
tmpDir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
installDir = path.join('/Applications', appName)
|
||||
if process.platform is 'win32'
|
||||
appName = 'Atom'
|
||||
tmpDir = os.tmpdir()
|
||||
installRoot = process.env.ProgramFiles
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
appDir = path.join(shellAppDir, 'resources', 'app')
|
||||
else
|
||||
appName = 'Atom.app'
|
||||
tmpDir = '/tmp'
|
||||
installRoot = '/Applications'
|
||||
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
|
||||
shellAppDir = path.join(buildDir, appName)
|
||||
contentsDir = path.join(shellAppDir, 'Contents')
|
||||
appDir = path.join(contentsDir, 'Resources', 'app')
|
||||
|
||||
installDir = path.join(installRoot, appName)
|
||||
|
||||
coffeeConfig =
|
||||
options:
|
||||
@@ -178,4 +188,8 @@ module.exports = (grunt) ->
|
||||
grunt.registerTask('ci', ['update-atom-shell', 'build', 'set-development-version', 'lint', 'test'])
|
||||
grunt.registerTask('deploy', ['partial-clean', 'update-atom-shell', 'build', 'codesign'])
|
||||
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
|
||||
grunt.registerTask('default', ['update-atom-shell', 'build', 'set-development-version', 'install'])
|
||||
|
||||
defaultTasks = ['update-atom-shell', 'build']
|
||||
defaultTasks.push('set-development-version') if process.platform is 'darwin'
|
||||
defaultTasks.push('install')
|
||||
grunt.registerTask('default', defaultTasks)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
require '../spec/spec-helper'
|
||||
|
||||
path = require 'path'
|
||||
{$, _, Point, fs} = require 'atom'
|
||||
Project = require '../src/project'
|
||||
fsUtils = require '../src/fs-utils'
|
||||
|
||||
@@ -30,8 +30,9 @@ built-in keymaps:
|
||||
'.editor':
|
||||
'enter': 'editor:newline'
|
||||
|
||||
".select-list .editor.mini":
|
||||
'enter': 'core:confirm'
|
||||
'body':
|
||||
'ctrl-P': 'core:move-up'
|
||||
'ctrl-p': 'core:move-down'
|
||||
```
|
||||
|
||||
This keymap defines the meaning of `enter` in two different contexts. In a
|
||||
@@ -40,10 +41,9 @@ the editor to insert a newline. But if the same keystroke occurs inside of a
|
||||
select list's mini-editor, it instead emits the `core:confirm` event based on
|
||||
the binding in the more-specific selector.
|
||||
|
||||
By default, any keymap files in your `~/.atom/keymaps` directory are loaded
|
||||
in alphabetical order when Atom is started. They will always be loaded last,
|
||||
giving you the chance to override bindings that are defined by Atom's core
|
||||
keymaps or third-party packages.
|
||||
By default, `~/.atom/keymap.cson` is loaded when Atom is started. It will always
|
||||
be loaded last, giving you the chance to override bindings that are defined by
|
||||
Atom's core keymaps or third-party packages.
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
@@ -63,7 +63,6 @@ namespaces: `core` and `editor`.
|
||||
### Configuration Key Reference
|
||||
|
||||
- `core`
|
||||
- `autosave`: Save a buffer when its view loses focus
|
||||
- `disabledPackages`: An array of package names to disable
|
||||
- `excludeVcsIgnoredPaths`: Don't search within files specified by _.gitignore_
|
||||
- `hideGitIgnoredFiles`: Whether files in the _.gitignore_ should be hidden
|
||||
|
||||
@@ -7,7 +7,7 @@ read config settings. You can read a value from `config` with `config.get`:
|
||||
|
||||
```coffeescript
|
||||
# read a value with `config.get`
|
||||
@autosave() if config.get "core.autosave"
|
||||
@showInvisibles() if config.get "edtior.showInvisibles"
|
||||
```
|
||||
|
||||
Or you can use `observeConfig` to track changes from a view object.
|
||||
@@ -47,7 +47,7 @@ the following way:
|
||||
|
||||
```coffeescript
|
||||
# basic key update
|
||||
config.set("core.autosave", true)
|
||||
config.set("core.showInvisibles", true)
|
||||
|
||||
config.pushAtKeyPath("core.disabledPackages", "wrap-guide")
|
||||
```
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# User keymap
|
||||
#
|
||||
# Atom keymaps work similarly to stylesheets. Just as stylesheets use selectors
|
||||
# to apply styles to elements, Atom keymaps use selectors to associate
|
||||
# keystrokes with events in specific contexts. Here's a small example, excerpted
|
||||
# from Atom's built-in keymaps:
|
||||
#
|
||||
# '.editor':
|
||||
# 'enter': 'editor:newline'
|
||||
#
|
||||
# 'body':
|
||||
# 'ctrl-P': 'core:move-up'
|
||||
# 'ctrl-p': 'core:move-down'
|
||||
+48
-48
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "atom",
|
||||
"version": "32.0.0",
|
||||
"version": "33.0.0",
|
||||
"main": "./src/browser/main.js",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -9,32 +9,31 @@
|
||||
"bugs": {
|
||||
"url": "https://github.com/atom/atom/issues"
|
||||
},
|
||||
"atomShellVersion": "0.6.4",
|
||||
"atomShellVersion": "0.6.6",
|
||||
"dependencies": {
|
||||
"async": "0.2.6",
|
||||
"bootstrap": "git://github.com/twbs/bootstrap.git#v3.0.0",
|
||||
"clear-cut": "0.1.0",
|
||||
"coffee-script": "1.6.2",
|
||||
"coffee-script": "1.6.3",
|
||||
"coffeestack": "0.6.0",
|
||||
"emissary": "0.6.0",
|
||||
"first-mate": "0.4.0",
|
||||
"emissary": "0.9.0",
|
||||
"first-mate": "0.5.0",
|
||||
"fuzzaldrin": "0.1.0",
|
||||
"git-utils": "0.26.0",
|
||||
"git-utils": "0.28.0",
|
||||
"guid": "0.0.10",
|
||||
"jasmine-focused": "~0.15.0",
|
||||
"mkdirp": "0.3.5",
|
||||
"less": "git://github.com/nathansobo/less.js.git",
|
||||
"less-cache": "0.8.0",
|
||||
"less-cache": "0.9.0",
|
||||
"nslog": "0.1.0",
|
||||
"oniguruma": "0.21.0",
|
||||
"oniguruma": "0.22.0",
|
||||
"optimist": "0.4.0",
|
||||
"pathwatcher": "0.5.0",
|
||||
"pathwatcher": "0.8.0",
|
||||
"pegjs": "0.7.0",
|
||||
"plist": "git://github.com/nathansobo/node-plist.git",
|
||||
"q": "0.9.7",
|
||||
"rimraf": "2.1.4",
|
||||
"scandal": "0.5.0",
|
||||
"season": "0.13.0",
|
||||
"scandal": "0.6.0",
|
||||
"season": "0.14.0",
|
||||
"semver": "1.1.4",
|
||||
"space-pen": "2.0.0",
|
||||
"telepath": "0.8.1",
|
||||
@@ -52,7 +51,7 @@
|
||||
"grunt-cson": "0.5.0",
|
||||
"grunt-contrib-csslint": "~0.1.2",
|
||||
"grunt-contrib-coffee": "~0.7.0",
|
||||
"grunt-contrib-less": "~0.6.4",
|
||||
"grunt-contrib-less": "~0.8.0",
|
||||
"walkdir": "0.0.7",
|
||||
"ws": "0.4.27",
|
||||
"js-yaml": "~2.1.0",
|
||||
@@ -73,20 +72,21 @@
|
||||
"archive-view": "0.11.0",
|
||||
"autocomplete": "0.11.0",
|
||||
"autoflow": "0.5.0",
|
||||
"autosave": "0.3.0",
|
||||
"bookmarks": "0.8.0",
|
||||
"bracket-matcher": "0.7.0",
|
||||
"collaboration": "0.29.0",
|
||||
"collaboration": "0.34.0",
|
||||
"command-logger": "0.6.0",
|
||||
"command-palette": "0.5.0",
|
||||
"dev-live-reload": "0.11.0",
|
||||
"command-palette": "0.6.0",
|
||||
"dev-live-reload": "0.12.0",
|
||||
"editor-stats": "0.5.0",
|
||||
"exception-reporting": "0.5.0",
|
||||
"find-and-replace": "0.31.0",
|
||||
"find-and-replace": "0.32.0",
|
||||
"fuzzy-finder": "0.15.0",
|
||||
"gfm": "0.5.0",
|
||||
"gists": "0.6.0",
|
||||
"git-diff": "0.12.0",
|
||||
"gists": "0.5.0",
|
||||
"github-sign-in": "0.8.0",
|
||||
"github-sign-in": "0.9.0",
|
||||
"go-to-line": "0.8.0",
|
||||
"grammar-selector": "0.8.0",
|
||||
"image-view": "0.7.0",
|
||||
@@ -94,58 +94,58 @@
|
||||
"markdown-preview": "0.12.0",
|
||||
"metrics": "0.8.0",
|
||||
"package-generator": "0.14.0",
|
||||
"release-notes": "0.8.0",
|
||||
"settings-view": "0.33.0",
|
||||
"release-notes": "0.11.0",
|
||||
"settings-view": "0.34.0",
|
||||
"snippets": "0.11.0",
|
||||
"spell-check": "0.8.0",
|
||||
"spell-check": "0.9.0",
|
||||
"status-bar": "0.15.0",
|
||||
"styleguide": "0.9.0",
|
||||
"symbols-view": "0.14.0",
|
||||
"symbols-view": "0.15.0",
|
||||
"tabs": "0.7.0",
|
||||
"terminal": "0.14.0",
|
||||
"timecop": "0.7.0",
|
||||
"timecop": "0.9.0",
|
||||
"to-the-hubs": "0.8.0",
|
||||
"toml": "0.3.0",
|
||||
"tree-view": "0.21.0",
|
||||
"tree-view": "0.22.0",
|
||||
"visual-bell": "0.3.0",
|
||||
"whitespace": "0.7.0",
|
||||
"wrap-guide": "0.4.0",
|
||||
|
||||
"language-c": "0.1.0",
|
||||
"language-c": "0.2.0",
|
||||
"language-clojure": "0.1.0",
|
||||
"language-coffee-script": "0.1.0",
|
||||
"language-css": "0.1.0",
|
||||
"language-git": "0.1.0",
|
||||
"language-css": "0.2.0",
|
||||
"language-git": "0.2.0",
|
||||
"language-go": "0.2.0",
|
||||
"language-html": "0.1.0",
|
||||
"language-hyperlink": "0.2.0",
|
||||
"language-java": "0.1.0",
|
||||
"language-javascript": "0.1.0",
|
||||
"language-json": "0.1.0",
|
||||
"language-html": "0.2.0",
|
||||
"language-hyperlink": "0.3.0",
|
||||
"language-java": "0.2.0",
|
||||
"language-javascript": "0.3.0",
|
||||
"language-json": "0.2.0",
|
||||
"language-less": "0.1.0",
|
||||
"language-make": "0.1.0",
|
||||
"language-mustache": "0.1.0",
|
||||
"language-objective-c": "0.1.0",
|
||||
"language-objective-c": "0.2.0",
|
||||
"language-pegjs": "0.1.0",
|
||||
"language-perl": "0.1.0",
|
||||
"language-php": "0.1.0",
|
||||
"language-perl": "0.2.0",
|
||||
"language-php": "0.2.0",
|
||||
"language-property-list": "0.2.0",
|
||||
"language-puppet": "0.1.0",
|
||||
"language-python": "0.1.0",
|
||||
"language-ruby-on-rails": "0.2.0",
|
||||
"language-ruby": "0.2.0",
|
||||
"language-sass": "0.2.0",
|
||||
"language-shellscript": "0.1.0",
|
||||
"language-source": "0.1.0",
|
||||
"language-sql": "0.1.0",
|
||||
"language-text": "0.1.0",
|
||||
"language-puppet": "0.2.0",
|
||||
"language-python": "0.2.0",
|
||||
"language-ruby": "0.4.0",
|
||||
"language-ruby-on-rails": "0.3.0",
|
||||
"language-sass": "0.3.0",
|
||||
"language-shellscript": "0.2.0",
|
||||
"language-source": "0.2.0",
|
||||
"language-sql": "0.2.0",
|
||||
"language-text": "0.2.0",
|
||||
"language-todo": "0.2.0",
|
||||
"language-xml": "0.1.0",
|
||||
"language-xml": "0.2.0",
|
||||
"language-yaml": "0.1.0"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"preinstall": "true",
|
||||
"test": "script/test"
|
||||
"preinstall": "node -e 'process.exit(0)'",
|
||||
"test": "node script/test"
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@ var commands = [
|
||||
joinCommands('cd vendor/apm', 'npm install --silent .'),
|
||||
'npm install --silent vendor/apm',
|
||||
echoNewLine,
|
||||
'node vendor/apm/bin/apm install --silent',
|
||||
'node node_modules/.bin/apm install --silent'
|
||||
];
|
||||
|
||||
process.chdir(path.dirname(__dirname));
|
||||
|
||||
+25
-25
@@ -10,31 +10,31 @@ if (process.platform != 'darwin')
|
||||
|
||||
var homeDir = process.platform == 'win32' ? process.env.USERPROFILE : process.env.HOME;
|
||||
|
||||
function readEnvironmentVariables(callback) {
|
||||
var credenticalsPath = '/var/lib/jenkins/config/atomcredentials';
|
||||
fs.readFile(credenticalsPath, function(error, data) {
|
||||
if (!error) {
|
||||
var lines = String(data).trim().split('\n');
|
||||
for (i in lines) {
|
||||
var parts = lines[i].split('=');
|
||||
var key = parts[0].trim();
|
||||
var value = parts[1].trim().substr(1, parts[1].length - 2);
|
||||
process.env[key] = value;
|
||||
}
|
||||
function readEnvironmentVariables() {
|
||||
var credentialsPath = '/var/lib/jenkins/config/atomcredentials';
|
||||
try {
|
||||
var credentials = fs.readFileSync(credentialsPath, 'utf8');
|
||||
var lines = credentials.trim().split('\n');
|
||||
for (i in lines) {
|
||||
var parts = lines[i].split('=');
|
||||
var key = parts[0].trim();
|
||||
var value = parts[1].trim().substr(1, parts[1].length - 2);
|
||||
process.env[key] = value;
|
||||
}
|
||||
// Do not quit when got error.
|
||||
callback(null);
|
||||
});
|
||||
} catch(error) { }
|
||||
}
|
||||
|
||||
var async = require('async');
|
||||
async.series([
|
||||
readEnvironmentVariables,
|
||||
cp.safeExec.bind(global, 'node script/bootstrap'),
|
||||
require('rimraf').bind(global, path.join(homeDir, '.atom')),
|
||||
cp.safeExec.bind(global, 'git clean -dff'),
|
||||
cp.safeExec.bind(global, 'node node_modules/.bin/apm clean'),
|
||||
cp.safeExec.bind(global, 'node node_modules/.bin/grunt ci --stack --no-color'),
|
||||
], function(error) {
|
||||
process.exit(error ? 1 : 0);
|
||||
});
|
||||
readEnvironmentVariables();
|
||||
cp.safeExec.bind(global, 'node script/bootstrap', function(error) {
|
||||
if (error)
|
||||
process.exit(1);
|
||||
var async = require('async');
|
||||
async.series([
|
||||
require('rimraf').bind(global, path.join(homeDir, '.atom')),
|
||||
cp.safeExec.bind(global, 'git clean -dff'),
|
||||
cp.safeExec.bind(global, 'node node_modules/.bin/apm clean'),
|
||||
cp.safeExec.bind(global, 'node node_modules/.bin/grunt ci --stack --no-color'),
|
||||
], function(error) {
|
||||
process.exit(error ? 1 : 0);
|
||||
});
|
||||
})();
|
||||
|
||||
@@ -56,6 +56,17 @@ describe "Config", ->
|
||||
expect(config.get("foo.bar.baz")).toEqual ["a", "b"]
|
||||
expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz"), {previous: ['a']}
|
||||
|
||||
describe ".unshiftAtKeyPath(keyPath, value)", ->
|
||||
it "unshifts the given value to the array at the key path and updates observers", ->
|
||||
config.set("foo.bar.baz", ["b"])
|
||||
observeHandler = jasmine.createSpy "observeHandler"
|
||||
config.observe "foo.bar.baz", observeHandler
|
||||
observeHandler.reset()
|
||||
|
||||
expect(config.unshiftAtKeyPath("foo.bar.baz", "a")).toBe 2
|
||||
expect(config.get("foo.bar.baz")).toEqual ["a", "b"]
|
||||
expect(observeHandler).toHaveBeenCalledWith config.get("foo.bar.baz"), {previous: ['b']}
|
||||
|
||||
describe ".removeAtKeyPath(keyPath, value)", ->
|
||||
it "removes the given value from the array at the key path and updates observers", ->
|
||||
config.set("foo.bar.baz", ["a", "b", "c"])
|
||||
|
||||
@@ -32,6 +32,18 @@ describe "LanguageMode", ->
|
||||
expect(buffer.lineForRow(6)).toBe " // current < pivot ? left.push(current) : right.push(current);"
|
||||
expect(buffer.lineForRow(7)).toBe " // }"
|
||||
|
||||
buffer.setText('\tvar i;')
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe "\t// var i;"
|
||||
|
||||
buffer.setText('var i;')
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe "// var i;"
|
||||
|
||||
buffer.setText(' var i;')
|
||||
languageMode.toggleLineCommentsForBufferRows(0, 0)
|
||||
expect(buffer.lineForRow(0)).toBe " // var i;"
|
||||
|
||||
describe "fold suggestion", ->
|
||||
describe ".doesBufferRowStartFold(bufferRow)", ->
|
||||
it "returns true only when the buffer row starts a foldable region", ->
|
||||
|
||||
@@ -167,8 +167,8 @@ describe "PaneContainer", ->
|
||||
|
||||
describe ".confirmClose()", ->
|
||||
it "returns true after modified files are saved", ->
|
||||
pane1.itemAtIndex(0).isModified = -> true
|
||||
pane2.itemAtIndex(0).isModified = -> true
|
||||
pane1.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
pane2.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
spyOn(atom, "confirmSync").andReturn(0)
|
||||
|
||||
saved = container.confirmClose()
|
||||
@@ -178,8 +178,8 @@ describe "PaneContainer", ->
|
||||
expect(atom.confirmSync).toHaveBeenCalled()
|
||||
|
||||
it "returns false if the user cancels saving", ->
|
||||
pane1.itemAtIndex(0).isModified = -> true
|
||||
pane2.itemAtIndex(0).isModified = -> true
|
||||
pane1.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
pane2.itemAtIndex(0).shouldPromptToSave = -> true
|
||||
spyOn(atom, "confirmSync").andReturn(1)
|
||||
|
||||
saved = container.confirmClose()
|
||||
|
||||
@@ -659,68 +659,6 @@ describe "Pane", ->
|
||||
expect(container.children('.pane').length).toBe 1
|
||||
expect(pane1.outerWidth()).toBe container.width()
|
||||
|
||||
describe "autosave", ->
|
||||
[initialActiveItem, initialActiveItemUri] = []
|
||||
|
||||
beforeEach ->
|
||||
initialActiveItem = pane.activeItem
|
||||
initialActiveItemUri = null
|
||||
pane.activeItem.getUri = -> initialActiveItemUri
|
||||
pane.activeItem.save = jasmine.createSpy("activeItem.save")
|
||||
spyOn(pane, 'saveItem').andCallThrough()
|
||||
|
||||
describe "when the active view loses focus", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
pane.activeView.trigger 'focusout'
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(pane.activeItem.save).not.toHaveBeenCalled()
|
||||
|
||||
config.set('core.autosave', true)
|
||||
pane.activeView.trigger 'focusout'
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(pane.activeItem.save).not.toHaveBeenCalled()
|
||||
|
||||
initialActiveItemUri = path.join(temp.dir, 'hi')
|
||||
pane.activeView.trigger 'focusout'
|
||||
expect(pane.activeItem.save).toHaveBeenCalled()
|
||||
|
||||
describe "when an item becomes inactive", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
expect(view2).not.toBe pane.activeItem
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(initialActiveItem.save).not.toHaveBeenCalled()
|
||||
pane.showItem(view2)
|
||||
|
||||
pane.showItem(initialActiveItem)
|
||||
config.set('core.autosave', true)
|
||||
pane.showItem(view2)
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
expect(initialActiveItem.save).not.toHaveBeenCalled()
|
||||
|
||||
pane.showItem(initialActiveItem)
|
||||
initialActiveItemUri = path.join(temp.dir, 'hi')
|
||||
pane.showItem(view2)
|
||||
expect(initialActiveItem.save).toHaveBeenCalled()
|
||||
|
||||
describe "when an item is destroyed", ->
|
||||
it "saves the item if core.autosave is true and the item has a uri", ->
|
||||
# doesn't have to be the active item
|
||||
expect(view2).not.toBe pane.activeItem
|
||||
pane.showItem(view2)
|
||||
|
||||
pane.destroyItem(editSession1)
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
|
||||
config.set("core.autosave", true)
|
||||
view2.getUri = -> undefined
|
||||
view2.save = ->
|
||||
pane.destroyItem(view2)
|
||||
expect(pane.saveItem).not.toHaveBeenCalled()
|
||||
|
||||
initialActiveItemUri = path.join(temp.dir, 'hi')
|
||||
pane.destroyItem(initialActiveItem)
|
||||
expect(initialActiveItem.save).toHaveBeenCalled()
|
||||
|
||||
describe ".itemForUri(uri)", ->
|
||||
it "returns the item for which a call to .getUri() returns the given uri", ->
|
||||
expect(pane.itemForUri(editSession1.getUri())).toBe editSession1
|
||||
|
||||
@@ -425,8 +425,20 @@ describe "Project", ->
|
||||
resultHandler = jasmine.createSpy("result found")
|
||||
waitsForPromise ->
|
||||
project.scan /dollar/, (results) ->
|
||||
console.log results
|
||||
resultHandler()
|
||||
|
||||
runs ->
|
||||
expect(resultHandler).not.toHaveBeenCalled()
|
||||
|
||||
it "scans buffer contents if the buffer is modified", ->
|
||||
editSession = project.openSync("a")
|
||||
editSession.setText("Elephant")
|
||||
results = []
|
||||
waitsForPromise ->
|
||||
project.scan /a|Elephant/, (result) -> results.push result
|
||||
|
||||
runs ->
|
||||
expect(results).toHaveLength 3
|
||||
resultForA = _.find results, ({filePath}) -> path.basename(filePath) == 'a'
|
||||
expect(resultForA.matches).toHaveLength 1
|
||||
expect(resultForA.matches[0].matchText).toBe 'Elephant'
|
||||
|
||||
@@ -5,7 +5,6 @@ describe "TextBuffer replication", ->
|
||||
|
||||
beforeEach ->
|
||||
buffer1 = project.buildBufferSync('sample.js')
|
||||
buffer1.insert([0, 0], 'changed\n')
|
||||
doc1 = buffer1.getState()
|
||||
doc2 = doc1.clone(new Site(2))
|
||||
doc1.connect(doc2)
|
||||
@@ -14,6 +13,9 @@ describe "TextBuffer replication", ->
|
||||
waitsFor ->
|
||||
buffer1.loaded and buffer2.loaded
|
||||
|
||||
runs ->
|
||||
buffer1.insert([0, 0], 'changed\n')
|
||||
|
||||
afterEach ->
|
||||
buffer1.destroy()
|
||||
buffer2.destroy()
|
||||
|
||||
@@ -949,24 +949,48 @@ describe 'TextBuffer', ->
|
||||
expect(buffer2.getText()).toBe(buffer.getText())
|
||||
|
||||
describe "when the serialized buffer had unsaved changes", ->
|
||||
it "restores the previous unsaved state of the buffer", ->
|
||||
previousText = buffer.getText()
|
||||
buffer.setText("abc")
|
||||
describe "when the disk contents were changed since serialization", ->
|
||||
it "loads the disk contents instead of the previous unsaved state", ->
|
||||
buffer.release()
|
||||
|
||||
state = buffer.serialize()
|
||||
expect(state.getObject('text')).toBe 'abc'
|
||||
filePath = temp.openSync('atom').path
|
||||
fs.writeSync(filePath, "words")
|
||||
{buffer} = project.openSync(filePath)
|
||||
buffer.setText("BUFFER CHANGE")
|
||||
|
||||
buffer2 = deserialize(state, {project})
|
||||
state = buffer.serialize()
|
||||
expect(state.getObject('text')).toBe 'BUFFER CHANGE'
|
||||
fs.writeSync(filePath, "DISK CHANGE")
|
||||
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
buffer2 = deserialize(state, {project})
|
||||
|
||||
runs ->
|
||||
expect(buffer2.getPath()).toBe(buffer.getPath())
|
||||
expect(buffer2.getText()).toBe(buffer.getText())
|
||||
expect(buffer2.isModified()).toBeTruthy()
|
||||
buffer2.setText(previousText)
|
||||
expect(buffer2.isModified()).toBeFalsy()
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
|
||||
runs ->
|
||||
expect(buffer2.getPath()).toBe(buffer.getPath())
|
||||
expect(buffer2.getText()).toBe("DISK CHANGE")
|
||||
expect(buffer2.isModified()).toBeFalsy()
|
||||
|
||||
describe "when the disk contents are the same since serialization", ->
|
||||
it "restores the previous unsaved state of the buffer", ->
|
||||
previousText = buffer.getText()
|
||||
buffer.setText("abc")
|
||||
|
||||
state = buffer.serialize()
|
||||
expect(state.getObject('text')).toBe 'abc'
|
||||
|
||||
buffer2 = deserialize(state, {project})
|
||||
|
||||
waitsFor ->
|
||||
buffer2.cachedDiskContents
|
||||
|
||||
runs ->
|
||||
expect(buffer2.getPath()).toBe(buffer.getPath())
|
||||
expect(buffer2.getText()).toBe(buffer.getText())
|
||||
expect(buffer2.isModified()).toBeTruthy()
|
||||
buffer2.setText(previousText)
|
||||
expect(buffer2.isModified()).toBeFalsy()
|
||||
|
||||
describe "when the serialized buffer was unsaved and had no path", ->
|
||||
it "restores the previous unsaved state of the buffer", ->
|
||||
|
||||
@@ -15,7 +15,7 @@ describe "ThemeManager", ->
|
||||
|
||||
describe "theme getters and setters", ->
|
||||
beforeEach ->
|
||||
atom.packages.loadPackages()
|
||||
atom.packages.loadPackages(sync: true)
|
||||
|
||||
it 'getLoadedThemes get all the loaded themes', ->
|
||||
themes = themeManager.getLoadedThemes()
|
||||
|
||||
@@ -350,7 +350,8 @@ describe "TokenizedBuffer", ->
|
||||
describe "when the buffer contains surrogate pairs", ->
|
||||
beforeEach ->
|
||||
atom.activatePackage('language-javascript', sync: true)
|
||||
buffer = project.buildBufferSync 'sample-with-pairs.js', """
|
||||
buffer = project.buildBufferSync 'sample-with-pairs.js'
|
||||
buffer.setText """
|
||||
'abc\uD835\uDF97def'
|
||||
//\uD835\uDF97xyz
|
||||
"""
|
||||
@@ -389,7 +390,8 @@ describe "TokenizedBuffer", ->
|
||||
atom.activatePackage('language-ruby-on-rails', sync: true)
|
||||
atom.activatePackage('language-ruby', sync: true)
|
||||
|
||||
buffer = project.bufferForPathSync(null, "<div class='name'><%= User.find(2).full_name %></div>")
|
||||
buffer = project.bufferForPathSync()
|
||||
buffer.setText "<div class='name'><%= User.find(2).full_name %></div>"
|
||||
tokenizedBuffer = new TokenizedBuffer({buffer})
|
||||
tokenizedBuffer.setGrammar(syntax.selectGrammar('test.erb'))
|
||||
fullyTokenize(tokenizedBuffer)
|
||||
|
||||
+4
-2
@@ -54,7 +54,7 @@ class Atom
|
||||
@__defineGetter__ 'packageStates', => @packages.packageStates
|
||||
@__defineSetter__ 'packageStates', (packageStates) => @packages.packageStates = packageStates
|
||||
|
||||
@subscribe @packages, 'loaded', => @watchThemes()
|
||||
@subscribe @packages, 'activated', => @watchThemes()
|
||||
@themes = new ThemeManager(@packages)
|
||||
@contextMenu = new ContextMenuManager(devMode)
|
||||
@menu = new MenuManager()
|
||||
@@ -161,7 +161,9 @@ class Atom
|
||||
|
||||
watchThemes: ->
|
||||
@themes.on 'reloaded', =>
|
||||
pack.reloadStylesheets?() for name, pack of @packages.getActivePackages()
|
||||
# Only reload stylesheets from non-theme packages
|
||||
for pack in @packages.getActivePackages() when pack.getType() isnt 'theme'
|
||||
pack.reloadStylesheets?()
|
||||
null
|
||||
|
||||
open: (options) ->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
startTime = new Date().getTime()
|
||||
startTime = Date.now()
|
||||
|
||||
autoUpdater = require 'auto-updater'
|
||||
crashReporter = require 'crash-reporter'
|
||||
@@ -8,11 +8,17 @@ fs = require 'fs'
|
||||
module = require 'module'
|
||||
path = require 'path'
|
||||
optimist = require 'optimist'
|
||||
nslog = require 'nslog'
|
||||
# TODO: NSLog is missing .lib on windows
|
||||
nslog = require 'nslog' unless process.platform is 'win32'
|
||||
dialog = require 'dialog'
|
||||
|
||||
console.log = (args...) ->
|
||||
nslog(args.map((arg) -> JSON.stringify(arg)).join(" "))
|
||||
# TODO: Make NSLog work as expected
|
||||
output = args.map((arg) -> JSON.stringify(arg)).join(" ")
|
||||
if process.platform == 'darwin'
|
||||
nslog(output)
|
||||
else
|
||||
fs.writeFileSync('debug.log', output, flag: 'a')
|
||||
|
||||
process.on 'uncaughtException', (error={}) ->
|
||||
nslog(error.message) if error.message?
|
||||
@@ -56,7 +62,7 @@ delegate.browserMainParts.preMainMessageLoopRun = ->
|
||||
AtomApplication = require './atom-application'
|
||||
|
||||
AtomApplication.open(args)
|
||||
console.log("App load time: #{new Date().getTime() - startTime}ms")
|
||||
console.log("App load time: #{Date.now() - startTime}ms")
|
||||
|
||||
global.devResourcePath = path.join(app.getHomeDir(), 'github', 'atom')
|
||||
|
||||
|
||||
@@ -1,23 +1,46 @@
|
||||
BufferedProcess = require './buffered-process'
|
||||
path = require 'path'
|
||||
|
||||
# Public: Like BufferedProcess, but accepts a node script instead of an
|
||||
# executable, on Unix which allows running scripts and executables, this seems
|
||||
# unnecessary, but on Windows we have to separate scripts from executables since
|
||||
# it doesn't support shebang strings.
|
||||
# Public: Like {BufferedProcess}, but accepts a Node script instead of an
|
||||
# executable.
|
||||
#
|
||||
# This may seem unnecessary but on Windows we have to have separate executables
|
||||
# for each script without this since Windows doesn't support shebang strings.
|
||||
module.exports =
|
||||
class BufferedNodeProcess extends BufferedProcess
|
||||
# Executes the given Node script.
|
||||
#
|
||||
# * options
|
||||
# + command:
|
||||
# The path to the Javascript script to execute.
|
||||
# + args:
|
||||
# The array of arguments to pass to the script (optional).
|
||||
# + options:
|
||||
# The options Object to pass to Node's `ChildProcess.spawn` (optional).
|
||||
# + stdout:
|
||||
# The callback that receives a single argument which contains the
|
||||
# standard output of the script. The callback is called as data is
|
||||
# received but it's buffered to ensure only complete lines are passed
|
||||
# until the source stream closes. After the source stream has closed
|
||||
# all remaining data is sent in a final call (optional).
|
||||
# + stderr:
|
||||
# The callback that receives a single argument which contains the
|
||||
# standard error of the script. The callback is called as data is
|
||||
# received but it's buffered to ensure only complete lines are passed
|
||||
# until the source stream closes. After the source stream has closed
|
||||
# all remaining data is sent in a final call (optional).
|
||||
# + exit:
|
||||
# The callback which receives a single argument containing the exit
|
||||
# status (optional).
|
||||
constructor: ({command, args, options, stdout, stderr, exit}) ->
|
||||
node =
|
||||
if process.platform is 'darwin'
|
||||
# On OS X we use the helper process to run script, because it doesn't
|
||||
# create an icon on the Dock.
|
||||
# Use a helper to prevent an icon from appearing on the Dock
|
||||
path.resolve(process.resourcesPath, '..', 'Frameworks',
|
||||
'Atom Helper.app', 'Contents', 'MacOS', 'Atom Helper')
|
||||
else
|
||||
process.execPath
|
||||
|
||||
# Tell atom-shell to run like upstream node.
|
||||
options ?= {}
|
||||
options.env ?= Object.create(process.env)
|
||||
options.env['ATOM_SHELL_INTERNAL_RUN_AS_NODE'] = 1
|
||||
|
||||
@@ -1,28 +1,35 @@
|
||||
ChildProcess = require 'child_process'
|
||||
path = require 'path'
|
||||
_ = require 'underscore-plus'
|
||||
|
||||
# Public: A wrapper which provides buffering for ChildProcess.
|
||||
# Public: A wrapper which provides line buffering for Node's ChildProcess.
|
||||
module.exports =
|
||||
class BufferedProcess
|
||||
process: null
|
||||
killed: false
|
||||
|
||||
# Executes the given command.
|
||||
# Executes the given executable.
|
||||
#
|
||||
# * options
|
||||
# + command:
|
||||
# The command to execute.
|
||||
# The path to the executable to execute.
|
||||
# + args:
|
||||
# The arguments for the given command.
|
||||
# The array of arguments to pass to the script (optional).
|
||||
# + options:
|
||||
# The options to pass to ChildProcess.
|
||||
# The options Object to pass to Node's `ChildProcess.spawn` (optional).
|
||||
# + stdout:
|
||||
# The callback to receive stdout data.
|
||||
# The callback that receives a single argument which contains the
|
||||
# standard output of the script. The callback is called as data is
|
||||
# received but it's buffered to ensure only complete lines are passed
|
||||
# until the source stream closes. After the source stream has closed
|
||||
# all remaining data is sent in a final call (optional).
|
||||
# + stderr:
|
||||
# The callback to receive stderr data.
|
||||
# The callback that receives a single argument which contains the
|
||||
# standard error of the script. The callback is called as data is
|
||||
# received but it's buffered to ensure only complete lines are passed
|
||||
# until the source stream closes. After the source stream has closed
|
||||
# all remaining data is sent in a final call (optional).
|
||||
# + exit:
|
||||
# The callback to receive exit status.
|
||||
# The callback which receives a single argument containing the exit
|
||||
# status (optional).
|
||||
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
|
||||
options ?= {}
|
||||
@process = ChildProcess.spawn(command, args, options)
|
||||
|
||||
+15
-3
@@ -176,6 +176,18 @@ class Config
|
||||
@set(keyPath, arrayValue)
|
||||
result
|
||||
|
||||
# Public: Add the value to the beginning of the array at the key path.
|
||||
#
|
||||
# keyPath - The {String} key path.
|
||||
# value - The value to shift onto the array.
|
||||
#
|
||||
# Returns the new array length of the setting.
|
||||
unshiftAtKeyPath: (keyPath, value) ->
|
||||
arrayValue = @get(keyPath) ? []
|
||||
result = arrayValue.unshift(value)
|
||||
@set(keyPath, arrayValue)
|
||||
result
|
||||
|
||||
# Public: Remove the value from the array at the key path.
|
||||
#
|
||||
# keyPath - The {String} key path.
|
||||
@@ -211,12 +223,12 @@ class Config
|
||||
previousValue = _.clone(value)
|
||||
callback(value, {previous})
|
||||
|
||||
subscription = { cancel: => @off 'updated', updateCallback }
|
||||
@on "updated.#{keyPath.replace(/\./, '-')}", updateCallback
|
||||
eventName = "updated.#{keyPath.replace(/\./, '-')}"
|
||||
subscription = { cancel: => @off eventName, updateCallback }
|
||||
@on eventName, updateCallback
|
||||
callback(value) if options.callNow ? true
|
||||
subscription
|
||||
|
||||
|
||||
# Public: Unobserve all callbacks on a given key
|
||||
#
|
||||
# keyPath - The {String} name of the key to unobserve
|
||||
|
||||
+17
-13
@@ -1,4 +1,3 @@
|
||||
fs = require 'fs'
|
||||
path = require 'path'
|
||||
fsUtils = require './fs-utils'
|
||||
pathWatcher = require 'pathwatcher'
|
||||
@@ -13,40 +12,45 @@ class Directory
|
||||
path: null
|
||||
realPath: null
|
||||
|
||||
# Public: Configures an new Directory instance, no files are accessed.
|
||||
# Public: Configures a new Directory instance, no files are accessed.
|
||||
#
|
||||
# * path:
|
||||
# A {String} representing the file directory
|
||||
# A String containing the absolute path to the directory.
|
||||
# + symlink:
|
||||
# A {Boolean} indicating if the path is a symlink
|
||||
# A Boolean indicating if the path is a symlink (defaults to false).
|
||||
constructor: (@path, @symlink=false) ->
|
||||
@on 'first-contents-changed-subscription-will-be-added', =>
|
||||
# Triggered by emissary, when a new contents-changed listener attaches
|
||||
@subscribeToNativeChangeEvents()
|
||||
|
||||
@on 'last-contents-changed-subscription-removed', =>
|
||||
# Triggered by emissary, when the last contents-changed listener detaches
|
||||
@unsubscribeFromNativeChangeEvents()
|
||||
|
||||
# Public: Returns the basename of the directory.
|
||||
getBaseName: ->
|
||||
path.basename(@path)
|
||||
|
||||
# Public: Returns the directory's path.
|
||||
# Public: Returns the directory's symbolic path.
|
||||
#
|
||||
# FIXME what is the difference between real path and path?
|
||||
# This may include unfollowed symlinks or relative directory entries. Or it
|
||||
# may be fully resolved, it depends on what you give it.
|
||||
getPath: -> @path
|
||||
|
||||
# Public: Returns this directory's real path.
|
||||
# Public: Returns this directory's completely resolved path.
|
||||
#
|
||||
# FIXME what is the difference between real path and path?
|
||||
# All relative directory entries are removed and symlinks are resolved to
|
||||
# their final destination.
|
||||
getRealPath: ->
|
||||
unless @realPath?
|
||||
try
|
||||
@realPath = fs.realpathSync(@path)
|
||||
@realPath = fsUtils.realpathSync(@path)
|
||||
catch e
|
||||
@realPath = @path
|
||||
@realPath
|
||||
|
||||
# Public: Returns whether the given path is inside this directory.
|
||||
# Public: Returns whether the given path (real or symbolic) is inside this
|
||||
# directory.
|
||||
contains: (pathToCheck) ->
|
||||
return false unless pathToCheck
|
||||
|
||||
@@ -76,15 +80,15 @@ class Directory
|
||||
#
|
||||
# Note: It follows symlinks.
|
||||
#
|
||||
# Returns an {Array} of {Files}.
|
||||
# Returns an Array of {Files}.
|
||||
getEntries: ->
|
||||
directories = []
|
||||
files = []
|
||||
for entryPath in fsUtils.listSync(@path)
|
||||
try
|
||||
stat = fs.lstatSync(entryPath)
|
||||
stat = fsUtils.lstatSync(entryPath)
|
||||
symlink = stat.isSymbolicLink()
|
||||
stat = fs.statSync(entryPath) if symlink
|
||||
stat = fsUtils.statSync(entryPath) if symlink
|
||||
catch e
|
||||
continue
|
||||
if stat.isDirectory()
|
||||
|
||||
+20
-6
@@ -1,3 +1,4 @@
|
||||
crypto = require 'crypto'
|
||||
path = require 'path'
|
||||
pathWatcher = require 'pathwatcher'
|
||||
Q = require 'q'
|
||||
@@ -5,10 +6,10 @@ Q = require 'q'
|
||||
_ = require 'underscore-plus'
|
||||
fsUtils = require './fs-utils'
|
||||
|
||||
# Public: Represents an individual file in the editor.
|
||||
# Public: Represents an individual file.
|
||||
#
|
||||
# This class shouldn't be created directly, instead you should create a
|
||||
# {Directory} and access the {File} objects that it creates.
|
||||
# You should probably create a {Directory} and access the {File} objects that
|
||||
# it creates, rather than instantiating the {File} class directly.
|
||||
module.exports =
|
||||
class File
|
||||
Emitter.includeInto(this)
|
||||
@@ -16,10 +17,10 @@ class File
|
||||
path: null
|
||||
cachedContents: null
|
||||
|
||||
# Private: Creates a new file.
|
||||
# Public: Creates a new file.
|
||||
#
|
||||
# * path:
|
||||
# A String representing the file path
|
||||
# A String containing the absolute path to the file
|
||||
# * symlink:
|
||||
# A Boolean indicating if the path is a symlink (default: false)
|
||||
constructor: (@path, @symlink=false) ->
|
||||
@@ -27,15 +28,18 @@ class File
|
||||
|
||||
@handleEventSubscriptions()
|
||||
|
||||
# Private: Subscribes to file system notifications when necessary.
|
||||
handleEventSubscriptions: ->
|
||||
eventNames = ['contents-changed', 'moved', 'removed']
|
||||
|
||||
subscriptionsAdded = eventNames.map (eventName) -> "first-#{eventName}-subscription-will-be-added"
|
||||
@on subscriptionsAdded.join(' '), =>
|
||||
# Only subscribe when a listener of eventName attaches (triggered by emissary)
|
||||
@subscribeToNativeChangeEvents() if @exists()
|
||||
|
||||
subscriptionsRemoved = eventNames.map (eventName) -> "last-#{eventName}-subscription-removed"
|
||||
@on subscriptionsRemoved.join(' '), =>
|
||||
# Detach when the last listener of eventName detaches (triggered by emissary)
|
||||
subscriptionsEmpty = _.every eventNames, (eventName) => @getSubscriptionCount(eventName) is 0
|
||||
@unsubscribeFromNativeChangeEvents() if subscriptionsEmpty
|
||||
|
||||
@@ -65,6 +69,9 @@ class File
|
||||
else
|
||||
@cachedContents
|
||||
|
||||
@setDigest(@cachedContents)
|
||||
@cachedContents
|
||||
|
||||
# Public: Reads the contents of the file.
|
||||
#
|
||||
# * flushCache:
|
||||
@@ -98,12 +105,19 @@ class File
|
||||
promise = Q(@cachedContents)
|
||||
|
||||
promise.then (contents) =>
|
||||
@setDigest(contents)
|
||||
@cachedContents = contents
|
||||
|
||||
# Public: Returns whether a file exists.
|
||||
# Public: Returns whether the file exists.
|
||||
exists: ->
|
||||
fsUtils.exists(@getPath())
|
||||
|
||||
setDigest: (contents) ->
|
||||
@digest = crypto.createHash('sha1').update(contents ? '').digest('hex')
|
||||
|
||||
getDigest: ->
|
||||
@digest ? @setDigest(@readSync())
|
||||
|
||||
# Private:
|
||||
handleNativeChangeEvent: (eventType, path) ->
|
||||
if eventType is "delete"
|
||||
|
||||
+163
-40
@@ -7,9 +7,22 @@ rimraf = require 'rimraf'
|
||||
path = require 'path'
|
||||
|
||||
# Public: Useful extensions to node's built-in fs module
|
||||
#
|
||||
# Important, this extends Node's builtin in ['fs' module][fs], which means that you
|
||||
# can do anything that you can do with Node's 'fs' module plus a few extra
|
||||
# functions that we've found to be helpful.
|
||||
#
|
||||
# [fs]: http://nodejs.org/api/fs.html
|
||||
fsExtensions =
|
||||
# Make the given path absolute by resolving it against the
|
||||
# current working directory.
|
||||
# Public: Make the given path absolute by resolving it against the current
|
||||
# working directory.
|
||||
#
|
||||
# * relativePath:
|
||||
# The String containing the relative path. If the path is prefixed with
|
||||
# '~', it will be expanded to the current user's home directory.
|
||||
#
|
||||
# Returns the absolute path or the relative path if it's unable to determine
|
||||
# it's realpath.
|
||||
absolute: (relativePath) ->
|
||||
return null unless relativePath?
|
||||
|
||||
@@ -25,11 +38,24 @@ fsExtensions =
|
||||
catch e
|
||||
relativePath
|
||||
|
||||
# Returns true if a file or folder at the specified path exists.
|
||||
# Public: Is the given path absolute?
|
||||
#
|
||||
# * pathToCheck:
|
||||
# The relative or absolute path to check.
|
||||
#
|
||||
# Returns true if the path is absolute, false otherwise.
|
||||
isAbsolute: (pathToCheck='') ->
|
||||
if process.platform is 'win32'
|
||||
pathToCheck[1] is ':' # C:\ style
|
||||
else
|
||||
pathToCheck[0] is '/' # /usr style
|
||||
|
||||
# Public: Returns true if a file or folder at the specified path exists.
|
||||
exists: (pathToCheck) ->
|
||||
# TODO: rename to existsSync
|
||||
pathToCheck? and fs.statSyncNoException(pathToCheck) isnt false
|
||||
|
||||
# Returns true if the specified path is a directory that exists.
|
||||
# Public: Returns true if the given path exists and is a directory.
|
||||
isDirectorySync: (directoryPath) ->
|
||||
return false unless directoryPath?.length > 0
|
||||
if stat = fs.statSyncNoException(directoryPath)
|
||||
@@ -37,6 +63,7 @@ fsExtensions =
|
||||
else
|
||||
false
|
||||
|
||||
# Public: Asynchronously checks that the given path exists and is a directory.
|
||||
isDirectory: (directoryPath, done) ->
|
||||
return done(false) unless directoryPath?.length > 0
|
||||
fs.exists directoryPath, (exists) ->
|
||||
@@ -49,7 +76,7 @@ fsExtensions =
|
||||
else
|
||||
done(false)
|
||||
|
||||
# Returns true if the specified path is a regular file that exists.
|
||||
# Public: Returns true if the specified path exists and is a file.
|
||||
isFileSync: (filePath) ->
|
||||
return false unless filePath?.length > 0
|
||||
if stat = fs.statSyncNoException(filePath)
|
||||
@@ -57,7 +84,7 @@ fsExtensions =
|
||||
else
|
||||
false
|
||||
|
||||
# Returns true if the specified path is executable.
|
||||
# Public: Returns true if the specified path is executable.
|
||||
isExecutableSync: (pathToCheck) ->
|
||||
return false unless pathToCheck?.length > 0
|
||||
if stat = fs.statSyncNoException(pathToCheck)
|
||||
@@ -65,8 +92,14 @@ fsExtensions =
|
||||
else
|
||||
false
|
||||
|
||||
# Returns an array with the paths of the files and folders
|
||||
# contained in the directory path.
|
||||
# Public: Returns an Array with the paths of the files and directories
|
||||
# contained within the directory path. It is not recursive.
|
||||
#
|
||||
# * rootPath:
|
||||
# The absolute path to the directory to list.
|
||||
# * extensions:
|
||||
# An array of extensions to filter the results by. If none are given, none
|
||||
# are filtered (optional).
|
||||
listSync: (rootPath, extensions) ->
|
||||
return [] unless @isDirectorySync(rootPath)
|
||||
paths = fs.readdirSync(rootPath)
|
||||
@@ -74,6 +107,16 @@ fsExtensions =
|
||||
paths = paths.map (childPath) -> path.join(rootPath, childPath)
|
||||
paths
|
||||
|
||||
# Public: Asynchronously lists the files and directories in the given path.
|
||||
# The listing is not recursive.
|
||||
#
|
||||
# * rootPath:
|
||||
# The absolute path to the directory to list.
|
||||
# * extensions:
|
||||
# An array of extensions to filter the results by. If none are given, none
|
||||
# are filtered (optional)
|
||||
# * callback:
|
||||
# The function to call
|
||||
list: (rootPath, rest...) ->
|
||||
extensions = rest.shift() if rest.length > 1
|
||||
done = rest.shift()
|
||||
@@ -85,6 +128,7 @@ fsExtensions =
|
||||
paths = paths.map (childPath) -> path.join(rootPath, childPath)
|
||||
done(null, paths)
|
||||
|
||||
# Private: Returns only the paths which end with one of the given extensions.
|
||||
filterExtensions: (paths, extensions) ->
|
||||
extensions = extensions.map (ext) ->
|
||||
if ext is ''
|
||||
@@ -93,6 +137,7 @@ fsExtensions =
|
||||
'.' + ext.replace(/^\./, '')
|
||||
paths.filter (pathToCheck) -> _.include(extensions, path.extname(pathToCheck))
|
||||
|
||||
# Deprecated: No one currently uses this.
|
||||
listTreeSync: (rootPath) ->
|
||||
paths = []
|
||||
onPath = (childPath) ->
|
||||
@@ -101,22 +146,34 @@ fsExtensions =
|
||||
@traverseTreeSync(rootPath, onPath, onPath)
|
||||
paths
|
||||
|
||||
# Public: Moves the file or directory to the target synchronously.
|
||||
move: (source, target) ->
|
||||
# TODO: This should be renamed to moveSync
|
||||
fs.renameSync(source, target)
|
||||
|
||||
# Remove the file or directory at the given path.
|
||||
# Public: Removes the file or directory at the given path synchronously.
|
||||
remove: (pathToRemove) ->
|
||||
# TODO: This should be renamed to removeSync
|
||||
rimraf.sync(pathToRemove)
|
||||
|
||||
# Open, read, and close a file, returning the file's contents.
|
||||
# Public: Open, read, and close a file, returning the file's contents
|
||||
# synchronously.
|
||||
read: (filePath) ->
|
||||
# TODO: This should be renamed to readSync
|
||||
fs.readFileSync(filePath, 'utf8')
|
||||
|
||||
# Open, write, flush, and close a file, writing the given content.
|
||||
# Public: Open, write, flush, and close a file, writing the given content
|
||||
# synchronously.
|
||||
#
|
||||
# It also creates the necessary parent directories.
|
||||
writeSync: (filePath, content) ->
|
||||
mkdirp.sync(path.dirname(filePath))
|
||||
fs.writeFileSync(filePath, content)
|
||||
|
||||
# Public: Open, write, flush, and close a file, writing the given content
|
||||
# asynchronously.
|
||||
#
|
||||
# It also creates the necessary parent directories.
|
||||
write: (filePath, content, callback) ->
|
||||
mkdirp path.dirname(filePath), (error) ->
|
||||
if error?
|
||||
@@ -124,6 +181,7 @@ fsExtensions =
|
||||
else
|
||||
fs.writeFile(filePath, content, callback)
|
||||
|
||||
# Public: Copies the given path asynchronously.
|
||||
copy: (sourcePath, destinationPath, done) ->
|
||||
mkdirp path.dirname(destinationPath), (error) ->
|
||||
if error?
|
||||
@@ -145,11 +203,23 @@ fsExtensions =
|
||||
|
||||
sourceStream.pipe(destinationStream)
|
||||
|
||||
# Create a directory at the specified path including any missing parent
|
||||
# directories.
|
||||
# Public: Create a directory at the specified path including any missing
|
||||
# parent directories synchronously.
|
||||
makeTree: (directoryPath) ->
|
||||
# TODO: rename to makeTreeSync
|
||||
mkdirp.sync(directoryPath) if directoryPath and not @exists(directoryPath)
|
||||
|
||||
# Public: Recursively walk the given path and execute the given functions
|
||||
# synchronously.
|
||||
#
|
||||
# * rootPath:
|
||||
# The String containing the directory to recurse into.
|
||||
# * onFile:
|
||||
# The function to execute on each file, receives a single argument the
|
||||
# absolute path.
|
||||
# * onDirectory:
|
||||
# The function to execute on each directory, receives a single argument the
|
||||
# absolute path (defaults to onFile)
|
||||
traverseTreeSync: (rootPath, onFile, onDirectory=onFile) ->
|
||||
return unless @isDirectorySync(rootPath)
|
||||
|
||||
@@ -167,6 +237,17 @@ fsExtensions =
|
||||
|
||||
traverse(rootPath, onFile, onDirectory)
|
||||
|
||||
# Public: Recursively walk the given path and execute the given functions
|
||||
# asynchronously.
|
||||
#
|
||||
# * rootPath:
|
||||
# The String containing the directory to recurse into.
|
||||
# * onFile:
|
||||
# The function to execute on each file, receives a single argument the
|
||||
# absolute path.
|
||||
# * onDirectory:
|
||||
# The function to execute on each directory, receives a single argument the
|
||||
# absolute path (defaults to onFile)
|
||||
traverseTree: (rootPath, onFile, onDirectory, onDone) ->
|
||||
fs.readdir rootPath, (error, files) ->
|
||||
if error
|
||||
@@ -194,16 +275,34 @@ fsExtensions =
|
||||
queue.drain = onDone
|
||||
queue.push(path.join(rootPath, file)) for file in files
|
||||
|
||||
# Public: Hashes the contents of the given file.
|
||||
#
|
||||
# * pathToDigest:
|
||||
# The String containing the absolute path.
|
||||
#
|
||||
# Returns a String containing the MD5 hexadecimal hash.
|
||||
md5ForPath: (pathToDigest) ->
|
||||
contents = fs.readFileSync(pathToDigest)
|
||||
require('crypto').createHash('md5').update(contents).digest('hex')
|
||||
|
||||
# Public: Finds a relative path among the given array of paths.
|
||||
#
|
||||
# * loadPaths:
|
||||
# An Array of absolute and relative paths to search.
|
||||
# * pathToResolve:
|
||||
# The string containing the path to resolve.
|
||||
# * extensions:
|
||||
# An array of extensions to pass to {resolveExtensions} in which case
|
||||
# pathToResolve should not contain an extension (optional).
|
||||
#
|
||||
# Returns the absolute path of the file to be resolved if it's found and
|
||||
# undefined otherwise.
|
||||
resolve: (args...) ->
|
||||
extensions = args.pop() if _.isArray(_.last(args))
|
||||
pathToResolve = args.pop()
|
||||
loadPaths = args
|
||||
|
||||
if pathToResolve[0] is '/'
|
||||
if @isAbsolute(pathToResolve)
|
||||
if extensions and resolvedPath = @resolveExtension(pathToResolve, extensions)
|
||||
return resolvedPath
|
||||
else
|
||||
@@ -218,10 +317,22 @@ fsExtensions =
|
||||
return @absolute(candidatePath) if @exists(candidatePath)
|
||||
undefined
|
||||
|
||||
# Deprecated:
|
||||
resolveOnLoadPath: (args...) ->
|
||||
loadPaths = Module.globalPaths.concat(module.paths)
|
||||
@resolve(loadPaths..., args...)
|
||||
|
||||
# Public: Finds the first file in the given path which matches the extension
|
||||
# in the order given.
|
||||
#
|
||||
# * pathToResolve:
|
||||
# The String containing relative or absolute path of the file in question
|
||||
# without the extension or '.'.
|
||||
# * extensions:
|
||||
# The ordered Array of extensions to try.
|
||||
#
|
||||
# Returns the absolute path of the file if it exists with any of the given
|
||||
# extensions, otherwise it's undefined.
|
||||
resolveExtension: (pathToResolve, extensions) ->
|
||||
for extension in extensions
|
||||
if extension == ""
|
||||
@@ -231,6 +342,7 @@ fsExtensions =
|
||||
return @absolute(pathWithExtension) if @exists(pathWithExtension)
|
||||
undefined
|
||||
|
||||
# Public: Returns true for extensions associated with compressed files.
|
||||
isCompressedExtension: (ext) ->
|
||||
_.indexOf([
|
||||
'.gz'
|
||||
@@ -240,6 +352,7 @@ fsExtensions =
|
||||
'.zip'
|
||||
], ext, true) >= 0
|
||||
|
||||
# Public: Returns true for extensions associated with image files.
|
||||
isImageExtension: (ext) ->
|
||||
_.indexOf([
|
||||
'.gif'
|
||||
@@ -249,9 +362,27 @@ fsExtensions =
|
||||
'.tiff'
|
||||
], ext, true) >= 0
|
||||
|
||||
# Public: Returns true for extensions associated with pdf files.
|
||||
isPdfExtension: (ext) ->
|
||||
ext is '.pdf'
|
||||
|
||||
# Public: Returns true for extensions associated with binary files.
|
||||
isBinaryExtension: (ext) ->
|
||||
_.indexOf([
|
||||
'.DS_Store'
|
||||
'.a'
|
||||
'.o'
|
||||
'.so'
|
||||
'.woff'
|
||||
], ext, true) >= 0
|
||||
|
||||
# Public: Returns true for files named similarily to 'README'
|
||||
isReadmePath: (readmePath) ->
|
||||
extension = path.extname(readmePath)
|
||||
base = path.basename(readmePath, extension).toLowerCase()
|
||||
base is 'readme' and (extension is '' or @isMarkdownExtension(extension))
|
||||
|
||||
# Private: Used by isReadmePath.
|
||||
isMarkdownExtension: (ext) ->
|
||||
_.indexOf([
|
||||
'.markdown'
|
||||
@@ -262,24 +393,30 @@ fsExtensions =
|
||||
'.ron'
|
||||
], ext, true) >= 0
|
||||
|
||||
isBinaryExtension: (ext) ->
|
||||
_.indexOf([
|
||||
'.DS_Store'
|
||||
'.a'
|
||||
'.o'
|
||||
'.so'
|
||||
'.woff'
|
||||
], ext, true) >= 0
|
||||
# Public: Reads and returns CSON, JSON or Plist files and returns the
|
||||
# corresponding Object.
|
||||
readObjectSync: (objectPath) ->
|
||||
CSON = require 'season'
|
||||
if CSON.isObjectPath(objectPath)
|
||||
CSON.readFileSync(objectPath)
|
||||
else
|
||||
@readPlistSync(objectPath)
|
||||
|
||||
isReadmePath: (readmePath) ->
|
||||
extension = path.extname(readmePath)
|
||||
base = path.basename(readmePath, extension).toLowerCase()
|
||||
base is 'readme' and (extension is '' or @isMarkdownExtension(extension))
|
||||
# Public: Reads and returns CSON, JSON or Plist files and calls the specified
|
||||
# callback with the corresponding Object.
|
||||
readObject: (objectPath, done) ->
|
||||
CSON = require 'season'
|
||||
if CSON.isObjectPath(objectPath)
|
||||
CSON.readFile(objectPath, done)
|
||||
else
|
||||
@readPlist(objectPath, done)
|
||||
|
||||
# Private: Used by readObjectSync.
|
||||
readPlistSync: (plistPath) ->
|
||||
plist = require 'plist'
|
||||
plist.parseStringSync(@read(plistPath))
|
||||
|
||||
# Private: Used by readObject.
|
||||
readPlist: (plistPath, done) ->
|
||||
plist = require 'plist'
|
||||
fs.readFile plistPath, 'utf8', (error, contents) ->
|
||||
@@ -291,18 +428,4 @@ fsExtensions =
|
||||
catch parseError
|
||||
done(parseError)
|
||||
|
||||
readObjectSync: (objectPath) ->
|
||||
CSON = require 'season'
|
||||
if CSON.isObjectPath(objectPath)
|
||||
CSON.readFileSync(objectPath)
|
||||
else
|
||||
@readPlistSync(objectPath)
|
||||
|
||||
readObject: (objectPath, done) ->
|
||||
CSON = require 'season'
|
||||
if CSON.isObjectPath(objectPath)
|
||||
CSON.readFile(objectPath, done)
|
||||
else
|
||||
@readPlist(objectPath, done)
|
||||
|
||||
module.exports = _.extend({}, fs, fsExtensions)
|
||||
|
||||
+27
-21
@@ -74,6 +74,7 @@ class Git
|
||||
@subscribeToBuffer(buffer) for buffer in project.getBuffers()
|
||||
@subscribe project, 'buffer-created', (buffer) => @subscribeToBuffer(buffer)
|
||||
|
||||
# Private: Subscribes to buffer events.
|
||||
subscribeToBuffer: (buffer) ->
|
||||
bufferStatusHandler = =>
|
||||
if path = buffer.getPath()
|
||||
@@ -82,8 +83,8 @@ class Git
|
||||
@subscribe buffer, 'reloaded', bufferStatusHandler
|
||||
@subscribe buffer, 'destroyed', => @unsubscribe(buffer)
|
||||
|
||||
# Public: Destroy this `Git` object. This destroys any tasks and
|
||||
# subscriptions and releases the underlying libgit2 repository handle.
|
||||
# Public: Destroy this `Git` object. This destroys any tasks and subscriptions
|
||||
# and releases the underlying libgit2 repository handle.
|
||||
destroy: ->
|
||||
if @statusTask?
|
||||
@statusTask.terminate()
|
||||
@@ -114,7 +115,8 @@ class Git
|
||||
|
||||
# Public: Returns the status of a single path in the repository.
|
||||
#
|
||||
# * path: A String defining a relative path
|
||||
# * path:
|
||||
# A String defining a relative path
|
||||
#
|
||||
# Returns a {Number}, FIXME representing what?
|
||||
getPathStatus: (path) ->
|
||||
@@ -128,24 +130,23 @@ class Git
|
||||
@emit 'status-changed', path, pathStatus
|
||||
pathStatus
|
||||
|
||||
# Public: Determines if the given path is ignored.
|
||||
# Public: Returns true if the given path is ignored.
|
||||
isPathIgnored: (path) -> @getRepo().isIgnored(@relativize(path))
|
||||
|
||||
# Public: Determine if the given status indicates modification.
|
||||
# Public: Returns true if the given status indicates modification.
|
||||
isStatusModified: (status) -> @getRepo().isStatusModified(status)
|
||||
|
||||
# Public: Determine if the given path is modified.
|
||||
# Public: Returns true if the given path is modified.
|
||||
isPathModified: (path) -> @isStatusModified(@getPathStatus(path))
|
||||
|
||||
# Public: Determine if the given status indicates a new path.
|
||||
# Public: Returns true if the given status indicates a new path.
|
||||
isStatusNew: (status) -> @getRepo().isStatusNew(status)
|
||||
|
||||
# Public: Determine if the given path is new.
|
||||
# Public: Returns true if the given path is new.
|
||||
isPathNew: (path) -> @isStatusNew(@getPathStatus(path))
|
||||
|
||||
# Public: Is the project at the root of this repository?
|
||||
#
|
||||
# Returns true if at the root, false if in a subfolder of the repository.
|
||||
# Public: Returns true if at the root, false if in a subfolder of the
|
||||
# repository.
|
||||
isProjectAtRoot: ->
|
||||
@projectAtRoot ?= project.relativize(@getWorkingDirectory()) is ''
|
||||
|
||||
@@ -170,9 +171,10 @@ class Git
|
||||
# git checkout HEAD -- <path>
|
||||
# ```
|
||||
#
|
||||
# path - The String path to checkout
|
||||
# * path:
|
||||
# The String path to checkout
|
||||
#
|
||||
# Returns a {Boolean} that's `true` if the method was successful.
|
||||
# Returns a Boolean that's true if the method was successful.
|
||||
checkoutHead: (path) ->
|
||||
headCheckedOut = @getRepo().checkoutHead(@relativize(path))
|
||||
@getPathStatus(path) if headCheckedOut
|
||||
@@ -180,10 +182,12 @@ class Git
|
||||
|
||||
# Public: Checks out a branch in your repository.
|
||||
#
|
||||
# reference - The {String} reference to checkout
|
||||
# create - A {Boolean} value which, if `true` creates the new reference if it doesn't exist.
|
||||
# * reference:
|
||||
# The String reference to checkout
|
||||
# * create:
|
||||
# A Boolean value which, if true creates the new reference if it doesn't exist.
|
||||
#
|
||||
# Returns a {Boolean} that's `true` if the method was successful.
|
||||
# Returns a Boolean that's true if the method was successful.
|
||||
checkoutReference: (reference, create) ->
|
||||
@getRepo().checkoutReference(reference, create)
|
||||
|
||||
@@ -204,7 +208,7 @@ class Git
|
||||
# * path:
|
||||
# The String path to check
|
||||
#
|
||||
# Returns a {Boolean}.
|
||||
# Returns a Boolean.
|
||||
isSubmodule: (path) -> @getRepo().isSubmodule(@relativize(path))
|
||||
|
||||
# Public: Retrieves the status of a directory.
|
||||
@@ -252,7 +256,7 @@ class Git
|
||||
# Returns a String.
|
||||
getUpstreamBranch: -> @getRepo().getUpstreamBranch()
|
||||
|
||||
# Public: ?
|
||||
# Public: Returns the current SHA for the given reference.
|
||||
getReferenceTarget: (reference) -> @getRepo().getReferenceTarget(reference)
|
||||
|
||||
# Public: Gets all the local and remote references.
|
||||
@@ -261,13 +265,15 @@ class Git
|
||||
# can be an array of strings containing the reference names.
|
||||
getReferences: -> @getRepo().getReferences()
|
||||
|
||||
# Public: ?
|
||||
# Public: Returns the number of commits behind the current branch is from the
|
||||
# default remote branch.
|
||||
getAheadBehindCount: (reference) -> @getRepo().getAheadBehindCount(reference)
|
||||
|
||||
# Public: ?
|
||||
# Public: Returns true if the given branch exists.
|
||||
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
|
||||
|
||||
# Private:
|
||||
# Private: Refreshes the current git status in an outside process and
|
||||
# asynchronously updates the relevant properties.
|
||||
refreshStatus: ->
|
||||
@statusTask = Task.once require.resolve('./repository-status-handler'), @getPath(), ({statuses, upstream, branch}) =>
|
||||
statusesUnchanged = _.isEqual(statuses, @statuses) and _.isEqual(upstream, @upstream) and _.isEqual(branch, @branch)
|
||||
|
||||
+3
-2
@@ -36,8 +36,9 @@ class Keymap
|
||||
@loadDirectory(config.bundledKeymapsDirPath)
|
||||
@emit('bundled-keymaps-loaded')
|
||||
|
||||
loadUserKeymaps: ->
|
||||
@loadDirectory(path.join(config.configDirPath, 'keymaps'))
|
||||
loadUserKeymap: ->
|
||||
userKeymapPath = CSON.resolve(path.join(config.configDirPath, 'keymap'))
|
||||
@load(userKeymapPath) if userKeymapPath
|
||||
|
||||
loadDirectory: (directoryPath) ->
|
||||
@load(filePath) for filePath in fsUtils.listSync(directoryPath, ['.cson', '.json'])
|
||||
|
||||
@@ -84,8 +84,14 @@ class LanguageMode
|
||||
else
|
||||
indent = @minIndentLevelForRowRange(start, end)
|
||||
indentString = @editSession.buildIndentString(indent)
|
||||
tabLength = @editSession.getTabLength()
|
||||
indentRegex = new RegExp("(\t|[ ]{#{tabLength}}){#{Math.floor(indent)}}")
|
||||
for row in [start..end]
|
||||
buffer.change([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
line = buffer.lineForRow(row)
|
||||
if indentLength = line.match(indentRegex)?[0].length
|
||||
buffer.insert([row, indentLength], commentStartString)
|
||||
else
|
||||
buffer.change([[row, 0], [row, indentString.length]], indentString + commentStartString)
|
||||
|
||||
# Folds all the foldable lines in the buffer.
|
||||
foldAll: ->
|
||||
|
||||
@@ -63,6 +63,7 @@ class PackageManager
|
||||
for [activator, types] in @packageActivators
|
||||
packages = @getLoadedPackagesForTypes(types)
|
||||
activator.activatePackages(packages)
|
||||
@emit 'activated'
|
||||
|
||||
# Public: another type of package manager can handle other package types.
|
||||
# See ThemeManager
|
||||
@@ -121,23 +122,27 @@ class PackageManager
|
||||
|
||||
@observingDisabledPackages = true
|
||||
|
||||
loadPackages: ->
|
||||
loadPackages: (options) ->
|
||||
# Ensure atom exports is already in the require cache so the load time
|
||||
# of the first package isn't skewed by being the first to require atom
|
||||
require '../exports/atom'
|
||||
|
||||
@loadPackage(name) for name in @getAvailablePackageNames() when not @isPackageDisabled(name)
|
||||
packagePaths = @getAvailablePackagePaths()
|
||||
packagePaths = packagePaths.filter (packagePath) => not @isPackageDisabled(path.basename(packagePath))
|
||||
packagePaths = _.uniq packagePaths, (packagePath) -> path.basename(packagePath)
|
||||
@loadPackage(packagePath, options) for packagePath in packagePaths
|
||||
@emit 'loaded'
|
||||
|
||||
loadPackage: (name, options) ->
|
||||
if packagePath = @resolvePackagePath(name)
|
||||
loadPackage: (nameOrPath, options) ->
|
||||
if packagePath = @resolvePackagePath(nameOrPath)
|
||||
name = path.basename(nameOrPath)
|
||||
return pack if pack = @getLoadedPackage(name)
|
||||
|
||||
pack = Package.load(packagePath, options)
|
||||
@loadedPackages[pack.name] = pack if pack?
|
||||
pack
|
||||
else
|
||||
throw new Error("Could not resolve '#{name}' to a package path")
|
||||
throw new Error("Could not resolve '#{nameOrPath}' to a package path")
|
||||
|
||||
unloadPackages: ->
|
||||
@unloadPackage(name) for name in _.keys(@loadedPackages)
|
||||
@@ -190,8 +195,13 @@ class PackageManager
|
||||
for packagePath in fsUtils.listSync(packageDirPath)
|
||||
packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
|
||||
|
||||
for packagePath in fsUtils.listSync(path.join(@resourcePath, 'node_modules'))
|
||||
packagePaths.push(packagePath) if @isInternalPackage(packagePath)
|
||||
try
|
||||
metadataPath = path.join(@resourcePath, 'package.json')
|
||||
{packageDependencies} = JSON.parse(fsUtils.read(metadataPath)) ? {}
|
||||
packagesPath = path.join(@resourcePath, 'node_modules')
|
||||
for packageName, packageVersion of packageDependencies ? {}
|
||||
packagePath = path.join(packagesPath, packageName)
|
||||
packagePaths.push(packagePath) if fsUtils.isDirectorySync(packagePath)
|
||||
|
||||
_.uniq(packagePaths)
|
||||
|
||||
|
||||
@@ -52,6 +52,6 @@ class Package
|
||||
|
||||
# Private:
|
||||
measure: (key, fn) ->
|
||||
startTime = new Date().getTime()
|
||||
startTime = Date.now()
|
||||
fn()
|
||||
@[key] = new Date().getTime() - startTime
|
||||
@[key] = Date.now() - startTime
|
||||
|
||||
@@ -128,8 +128,8 @@ class PaneContainer extends View
|
||||
confirmClose: ->
|
||||
saved = true
|
||||
for pane in @getPanes()
|
||||
for item in pane.getItems() when item.isModified?()
|
||||
if not @paneAtIndex(0).promptToSaveItem item
|
||||
for item in pane.getItems()
|
||||
if not pane.destroyItem(item)
|
||||
saved = false
|
||||
break
|
||||
saved
|
||||
|
||||
+9
-19
@@ -81,7 +81,6 @@ class Pane extends View
|
||||
@command 'pane:close-other-items', => @destroyInactiveItems()
|
||||
@on 'focus', => @activeView?.focus(); false
|
||||
@on 'focusin', => @makeActive()
|
||||
@on 'focusout', => @autosaveActiveItem()
|
||||
|
||||
# Private:
|
||||
afterAttach: (onDom) ->
|
||||
@@ -159,7 +158,6 @@ class Pane extends View
|
||||
|
||||
if @activeItem
|
||||
@activeItem.off? 'title-changed', @activeItemTitleChanged
|
||||
@autosaveActiveItem()
|
||||
|
||||
isFocused = @is(':has(:focus)')
|
||||
@addItem(item)
|
||||
@@ -185,7 +183,7 @@ class Pane extends View
|
||||
|
||||
@state.get('items').splice(index, 0, item.getState?() ? item.serialize()) if options.updateState ? true
|
||||
@items.splice(index, 0, item)
|
||||
@getContainer().itemAdded(item)
|
||||
@getContainer()?.itemAdded(item)
|
||||
@trigger 'pane:item-added', [item, index]
|
||||
item
|
||||
|
||||
@@ -196,18 +194,16 @@ class Pane extends View
|
||||
|
||||
# Public: Remove the specified item.
|
||||
destroyItem: (item) ->
|
||||
@trigger 'pane:before-item-destroyed', [item]
|
||||
container = @getContainer()
|
||||
reallyDestroyItem = =>
|
||||
|
||||
if @promptToSaveItem(item)
|
||||
@removeItem(item)
|
||||
container.itemDestroyed(item)
|
||||
item.destroy?()
|
||||
|
||||
@autosaveItem(item)
|
||||
|
||||
if item.shouldPromptToSave?()
|
||||
reallyDestroyItem() if @promptToSaveItem(item)
|
||||
true
|
||||
else
|
||||
reallyDestroyItem()
|
||||
false
|
||||
|
||||
# Public: Remove and delete all items.
|
||||
destroyItems: ->
|
||||
@@ -219,6 +215,8 @@ class Pane extends View
|
||||
|
||||
# Public: Prompt the user to save the given item.
|
||||
promptToSaveItem: (item) ->
|
||||
return true unless item.shouldPromptToSave?()
|
||||
|
||||
uri = item.getUri()
|
||||
chosen = atom.confirmSync(
|
||||
"'#{item.getTitle?() ? item.getUri()}' has changes, do you want to save them?"
|
||||
@@ -263,15 +261,7 @@ class Pane extends View
|
||||
saveItems: =>
|
||||
@saveItem(item) for item in @getItems()
|
||||
|
||||
# Public: Autosaves the currently focused item.
|
||||
autosaveActiveItem: ->
|
||||
@autosaveItem(@activeItem)
|
||||
|
||||
# Public: Autosaves the given focused item if configured to do so.
|
||||
autosaveItem: (item) ->
|
||||
@saveItem(item) if config.get('core.autosave') and item.getUri?()
|
||||
|
||||
# Public: Autosaves the given focused item if configured to do so.
|
||||
# Public:
|
||||
removeItem: (item) ->
|
||||
index = @items.indexOf(item)
|
||||
@removeItemAtIndex(index) if index >= 0
|
||||
|
||||
+21
-11
@@ -157,7 +157,7 @@ class Project
|
||||
if uri?.match(/[A-Za-z0-9+-.]+:\/\//) # leave path alone if it has a scheme
|
||||
uri
|
||||
else
|
||||
uri = path.join(@getPath(), uri) unless uri[0] == '/'
|
||||
uri = path.join(@getPath(), uri) unless fsUtils.isAbsolute(uri)
|
||||
fsUtils.absolute uri
|
||||
|
||||
# Public: Make the given path relative to the project directory.
|
||||
@@ -218,14 +218,19 @@ class Project
|
||||
getBuffers: ->
|
||||
new Array(@buffers...)
|
||||
|
||||
isPathModified: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
existingBuffer?.isModified()
|
||||
|
||||
# Private: Only to be used in specs
|
||||
bufferForPathSync: (filePath, text) ->
|
||||
bufferForPathSync: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
|
||||
if filePath
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
|
||||
existingBuffer ? @buildBufferSync(absoluteFilePath, text)
|
||||
existingBuffer ? @buildBufferSync(absoluteFilePath)
|
||||
|
||||
# Private: Given a file path, this retrieves or creates a new {TextBuffer}.
|
||||
#
|
||||
@@ -233,23 +238,22 @@ class Project
|
||||
# `text` is used as the contents of the new buffer.
|
||||
#
|
||||
# filePath - A {String} representing a path. If `null`, an "Untitled" buffer is created.
|
||||
# text - The {String} text to use as a buffer, if the file doesn't have any contents
|
||||
#
|
||||
# Returns a promise that resolves to the {TextBuffer}.
|
||||
bufferForPath: (filePath, text) ->
|
||||
bufferForPath: (filePath) ->
|
||||
absoluteFilePath = @resolve(filePath)
|
||||
if absoluteFilePath
|
||||
existingBuffer = _.find @buffers, (buffer) -> buffer.getPath() == absoluteFilePath
|
||||
|
||||
Q(existingBuffer ? @buildBuffer(absoluteFilePath, text))
|
||||
Q(existingBuffer ? @buildBuffer(absoluteFilePath))
|
||||
|
||||
# Private:
|
||||
bufferForId: (id) ->
|
||||
_.find @buffers, (buffer) -> buffer.id is id
|
||||
|
||||
# Private: DEPRECATED
|
||||
buildBufferSync: (absoluteFilePath, initialText) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath, initialText})
|
||||
buildBufferSync: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath})
|
||||
buffer.loadSync()
|
||||
@addBuffer(buffer)
|
||||
buffer
|
||||
@@ -260,8 +264,8 @@ class Project
|
||||
# text - The {String} text to use as a buffer
|
||||
#
|
||||
# Returns a promise that resolves to the {TextBuffer}.
|
||||
buildBuffer: (absoluteFilePath, initialText) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath, initialText})
|
||||
buildBuffer: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({project: this, filePath: absoluteFilePath})
|
||||
buffer.load().then (buffer) =>
|
||||
@addBuffer(buffer)
|
||||
buffer
|
||||
@@ -315,12 +319,18 @@ class Project
|
||||
deferred.resolve()
|
||||
|
||||
task.on 'scan:result-found', (result) =>
|
||||
iterator(result)
|
||||
iterator(result) unless @isPathModified(result.filePath)
|
||||
|
||||
if _.isFunction(options.onPathsSearched)
|
||||
task.on 'scan:paths-searched', (numberOfPathsSearched) ->
|
||||
options.onPathsSearched(numberOfPathsSearched)
|
||||
|
||||
for buffer in @buffers when buffer.isModified()
|
||||
filePath = buffer.getPath()
|
||||
matches = []
|
||||
buffer.scan regex, (match) -> matches.push match
|
||||
iterator {filePath, matches} if matches.length > 0
|
||||
|
||||
deferred.promise
|
||||
|
||||
# Private:
|
||||
|
||||
@@ -44,7 +44,6 @@ class RootView extends View
|
||||
@version: 1
|
||||
|
||||
@configDefaults:
|
||||
autosave: false
|
||||
ignoredNames: [".git", ".svn", ".DS_Store"]
|
||||
excludeVcsIgnoredPaths: true
|
||||
disabledPackages: []
|
||||
|
||||
@@ -15,7 +15,6 @@ child_process = require 'child_process'
|
||||
module.exports =
|
||||
class Task
|
||||
Emitter.includeInto(this)
|
||||
_.extend @prototype, Emitter
|
||||
|
||||
# Public: A helper method to easily launch and run a task once.
|
||||
#
|
||||
|
||||
+17
-13
@@ -1,3 +1,4 @@
|
||||
crypto = require 'crypto'
|
||||
{Emitter, Subscriber} = require 'emissary'
|
||||
guid = require 'guid'
|
||||
Q = require 'q'
|
||||
@@ -38,8 +39,8 @@ class TextBuffer
|
||||
|
||||
# Creates a new buffer.
|
||||
#
|
||||
# path - A {String} representing the file path
|
||||
# initialText - A {String} setting the starting text
|
||||
# * optionsOrState - An {Object} or a telepath.Document
|
||||
# + filePath - A {String} representing the file path
|
||||
constructor: (optionsOrState={}, params={}) ->
|
||||
if optionsOrState instanceof telepath.Document
|
||||
{@project} = params
|
||||
@@ -47,9 +48,9 @@ class TextBuffer
|
||||
@id = @state.get('id')
|
||||
filePath = @state.get('relativePath')
|
||||
@text = @state.get('text')
|
||||
@loadFromDisk = @state.get('isModified') == false
|
||||
@useSerializedText = @state.get('isModified') != false
|
||||
else
|
||||
{@project, filePath, initialText} = optionsOrState
|
||||
{@project, filePath} = optionsOrState
|
||||
@text = site.createDocument(initialText ? '', shareStrings: true)
|
||||
@id = guid.create().toString()
|
||||
@state = site.createDocument
|
||||
@@ -57,7 +58,6 @@ class TextBuffer
|
||||
deserializer: @constructor.name
|
||||
version: @constructor.version
|
||||
text: @text
|
||||
@loadFromDisk = not initialText
|
||||
|
||||
@loaded = false
|
||||
@subscribe @text, 'changed', @handleTextChange
|
||||
@@ -68,14 +68,19 @@ class TextBuffer
|
||||
|
||||
loadSync: ->
|
||||
@updateCachedDiskContentsSync()
|
||||
@reload() if @loadFromDisk
|
||||
@text.clearUndoStack()
|
||||
@finishLoading()
|
||||
|
||||
load: ->
|
||||
@updateCachedDiskContents().then =>
|
||||
@reload() if @loadFromDisk
|
||||
@text.clearUndoStack()
|
||||
this
|
||||
@updateCachedDiskContents().then => @finishLoading()
|
||||
|
||||
finishLoading: ->
|
||||
@loaded = true
|
||||
if @useSerializedText and @state.get('diskContentsDigest') == @file?.getDigest()
|
||||
@emitModifiedStatusChanged(true)
|
||||
else
|
||||
@reload()
|
||||
@text.clearUndoStack()
|
||||
this
|
||||
|
||||
### Internal ###
|
||||
|
||||
@@ -108,6 +113,7 @@ class TextBuffer
|
||||
serialize: ->
|
||||
state = @state.clone()
|
||||
state.set('isModified', @isModified())
|
||||
state.set('diskContentsDigest', @file.getDigest()) if @file
|
||||
for marker in state.get('text').getMarkers() when marker.isRemote()
|
||||
marker.destroy()
|
||||
state
|
||||
@@ -158,13 +164,11 @@ class TextBuffer
|
||||
|
||||
# Private: Rereads the contents of the file, and stores them in the cache.
|
||||
updateCachedDiskContentsSync: ->
|
||||
@loaded = true
|
||||
@cachedDiskContents = @file?.readSync() ? ""
|
||||
|
||||
# Private: Rereads the contents of the file, and stores them in the cache.
|
||||
updateCachedDiskContents: ->
|
||||
Q(@file?.read() ? "").then (contents) =>
|
||||
@loaded = true
|
||||
@cachedDiskContents = contents
|
||||
|
||||
# Gets the file's basename--that is, the file without any directory information.
|
||||
|
||||
@@ -11,9 +11,7 @@ class ThemePackage extends AtomPackage
|
||||
getStylesheetType: -> 'theme'
|
||||
|
||||
enable: ->
|
||||
themes = atom.config.get('core.themes')
|
||||
themes = [@metadata.name].concat(themes)
|
||||
atom.config.set('core.themes', themes)
|
||||
atom.config.unshiftAtKeyPath('core.themes', @metadata.name)
|
||||
|
||||
disable: ->
|
||||
atom.config.removeAtKeyPath('core.themes', @metadata.name)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# Like sands through the hourglass, so are the days of our lives.
|
||||
startTime = new Date().getTime()
|
||||
startTime = Date.now()
|
||||
|
||||
require './window'
|
||||
|
||||
@@ -7,4 +7,4 @@ Atom = require './atom'
|
||||
window.atom = new Atom()
|
||||
window.setUpEnvironment('editor')
|
||||
window.startEditorWindow()
|
||||
console.log "Window load time: #{new Date().getTime() - startTime}ms"
|
||||
console.log "Window load time: #{Date.now() - startTime}ms"
|
||||
|
||||
@@ -14,7 +14,11 @@ class WindowEventHandler
|
||||
@reloadRequested = false
|
||||
|
||||
@subscribe ipc, 'command', (command, args...) ->
|
||||
$(document.activeElement).trigger(command, args...)
|
||||
activeElement = document.activeElement
|
||||
# Use root view if body has focus
|
||||
if activeElement is document.body and atom.rootView?
|
||||
activeElement = atom.rootView
|
||||
$(activeElement).trigger(command, args...)
|
||||
|
||||
@subscribe ipc, 'context-command', (command, args...) ->
|
||||
$(atom.contextMenu.activeElement).trigger(command, args...)
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ window.startEditorWindow = ->
|
||||
atom.packages.loadPackages()
|
||||
deserializeEditorWindow()
|
||||
atom.packages.activate()
|
||||
atom.keymap.loadUserKeymaps()
|
||||
atom.keymap.loadUserKeymap()
|
||||
atom.requireUserInitScript()
|
||||
atom.menu.update()
|
||||
$(window).on 'unload', ->
|
||||
|
||||
@@ -11,7 +11,11 @@ module.exports = (grunt) ->
|
||||
|
||||
rm shellAppDir
|
||||
mkdir path.dirname(buildDir)
|
||||
cp 'atom-shell/Atom.app', shellAppDir
|
||||
|
||||
if process.platform is 'darwin'
|
||||
cp 'atom-shell/Atom.app', shellAppDir
|
||||
else if process.platform is 'win32'
|
||||
cp 'atom-shell', shellAppDir
|
||||
|
||||
mkdir appDir
|
||||
|
||||
@@ -37,7 +41,6 @@ module.exports = (grunt) ->
|
||||
path.join('git-utils', 'deps')
|
||||
path.join('oniguruma', 'deps')
|
||||
path.join('vendor', 'apm')
|
||||
path.join('vendor', 'bootstrap', 'docs')
|
||||
]
|
||||
ignoredPaths = ignoredPaths.map (ignoredPath) -> "(#{ignoredPath})"
|
||||
nodeModulesFilter = new RegExp(ignoredPaths.join('|'))
|
||||
@@ -50,8 +53,11 @@ module.exports = (grunt) ->
|
||||
cp 'src', path.join(appDir, 'src'), filter: /.+\.(cson|coffee)$/
|
||||
cp 'static', path.join(appDir, 'static')
|
||||
|
||||
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
||||
unless /.+\.plist/.test(sourcePath)
|
||||
grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))
|
||||
if process.platform is 'darwin'
|
||||
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->
|
||||
unless /.+\.plist/.test(sourcePath)
|
||||
grunt.file.copy(sourcePath, path.resolve(appDir, '..', subDirectory, filename))
|
||||
|
||||
grunt.task.run('compile', 'copy-info-plist')
|
||||
dependencies = ['compile']
|
||||
dependencies.push('copy-info-plist') if process.platform is 'darwin'
|
||||
grunt.task.run(dependencies...)
|
||||
|
||||
+16
-10
@@ -4,18 +4,24 @@ walkdir = require 'walkdir'
|
||||
|
||||
module.exports = (grunt) ->
|
||||
cp: (source, destination, {filter}={}) ->
|
||||
walkdir.sync source, (sourcePath, stats) ->
|
||||
return if filter?.test(sourcePath)
|
||||
unless grunt.file.exists(source)
|
||||
grunt.fatal("Cannot copy non-existent #{source.cyan} to #{destination.cyan}")
|
||||
|
||||
destinationPath = path.join(destination, path.relative(source, sourcePath))
|
||||
if stats.isSymbolicLink()
|
||||
grunt.file.mkdir(path.dirname(destinationPath))
|
||||
fs.symlinkSync(fs.readlinkSync(sourcePath), destinationPath)
|
||||
else if stats.isFile()
|
||||
grunt.file.copy(sourcePath, destinationPath)
|
||||
try
|
||||
walkdir.sync source, (sourcePath, stats) ->
|
||||
return if filter?.test(sourcePath)
|
||||
|
||||
if grunt.file.exists(destinationPath)
|
||||
fs.chmodSync(destinationPath, fs.statSync(sourcePath).mode)
|
||||
destinationPath = path.join(destination, path.relative(source, sourcePath))
|
||||
if stats.isSymbolicLink()
|
||||
grunt.file.mkdir(path.dirname(destinationPath))
|
||||
fs.symlinkSync(fs.readlinkSync(sourcePath), destinationPath)
|
||||
else if stats.isFile()
|
||||
grunt.file.copy(sourcePath, destinationPath)
|
||||
|
||||
if grunt.file.exists(destinationPath)
|
||||
fs.chmodSync(destinationPath, fs.statSync(sourcePath).mode)
|
||||
catch error
|
||||
grunt.fatal(error)
|
||||
|
||||
grunt.log.writeln("Copied #{source.cyan} to #{destination.cyan}.")
|
||||
|
||||
|
||||
@@ -157,6 +157,7 @@ module.exports = (grunt) ->
|
||||
if newVersion and newVersion isnt previousVersion
|
||||
grunt.log.writeln("Rebuilding native modules for new atom-shell version #{newVersion.cyan}.")
|
||||
cmd = path.join('node_modules', '.bin', 'apm')
|
||||
cmd += ".cmd" if process.platform is 'win32'
|
||||
spawn {cmd, args: ['rebuild']}, (error) -> callback(error)
|
||||
else
|
||||
callback()
|
||||
|
||||
externo
+1
-1
Submodule vendor/apm updated: 6e0142697c...8b629a043b
Referência em uma Nova Issue
Bloquear um usuário