mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2025-01-06 06:28:33 +03:00
Merge branch 'master' into ns-workspace-specs-cleanup
This commit is contained in:
commit
29f480661c
@ -1,4 +1,4 @@
|
|||||||
# Atom — The hackable, ~~collaborative~~ editor
|
# Atom — The hackable editor
|
||||||
|
|
||||||
![Atom](http://i.imgur.com/OrTvUAD.png)
|
![Atom](http://i.imgur.com/OrTvUAD.png)
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "~0.2.9",
|
"async": "~0.2.9",
|
||||||
"biscotto": "0.0.17",
|
"biscotto": "git://github.com/atom/biscotto.git#12188bfbe5f7303fa9f1aa3c4f8662d40ce3c3be",
|
||||||
"first-mate": "~0.13.0",
|
"first-mate": "~0.13.0",
|
||||||
"formidable": "~1.0.14",
|
"formidable": "~1.0.14",
|
||||||
"fs-plus": "1.x",
|
"fs-plus": "1.x",
|
||||||
@ -19,7 +19,7 @@
|
|||||||
"grunt-contrib-coffee": "~0.7.0",
|
"grunt-contrib-coffee": "~0.7.0",
|
||||||
"grunt-contrib-less": "~0.8.0",
|
"grunt-contrib-less": "~0.8.0",
|
||||||
"grunt-cson": "0.5.0",
|
"grunt-cson": "0.5.0",
|
||||||
"grunt-download-atom-shell": "git+https://atom-bot:362295be4c5258d3f7b967bbabae662a455ca2a7@github.com/atom/grunt-download-atom-shell#v0.5.0",
|
"grunt-download-atom-shell": "git+https://atom-bot:362295be4c5258d3f7b967bbabae662a455ca2a7@github.com/atom/grunt-download-atom-shell#v0.6.0",
|
||||||
"grunt-lesslint": "0.13.0",
|
"grunt-lesslint": "0.13.0",
|
||||||
"grunt-markdown": "~0.4.0",
|
"grunt-markdown": "~0.4.0",
|
||||||
"grunt-peg": "~1.1.0",
|
"grunt-peg": "~1.1.0",
|
||||||
@ -30,6 +30,7 @@
|
|||||||
"rcedit": "~0.1.2",
|
"rcedit": "~0.1.2",
|
||||||
"request": "~2.27.0",
|
"request": "~2.27.0",
|
||||||
"rimraf": "~2.2.2",
|
"rimraf": "~2.2.2",
|
||||||
|
"runas": "~0.3.0",
|
||||||
"unzip": "~0.1.9",
|
"unzip": "~0.1.9",
|
||||||
"vm-compatibility-layer": "~0.1.0",
|
"vm-compatibility-layer": "~0.1.0",
|
||||||
"walkdir": "0.0.7"
|
"walkdir": "0.0.7"
|
||||||
|
@ -5,12 +5,14 @@ fs = require 'fs-plus'
|
|||||||
request = require 'request'
|
request = require 'request'
|
||||||
|
|
||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
|
{rm} = require('./task-helpers')(grunt)
|
||||||
|
|
||||||
cmd = path.join('node_modules', '.bin', 'coffee')
|
cmd = path.join('node_modules', '.bin', 'coffee')
|
||||||
commonArgs = [path.join('build', 'node_modules', '.bin', 'biscotto'), '--']
|
commonArgs = [path.join('build', 'node_modules', '.bin', 'biscotto'), '--']
|
||||||
opts =
|
opts =
|
||||||
stdio: 'inherit'
|
stdio: 'inherit'
|
||||||
|
|
||||||
grunt.registerTask 'build-docs', 'Builds the API docs in src/app', ->
|
grunt.registerTask 'build-docs', 'Builds the API docs in src', ->
|
||||||
done = @async()
|
done = @async()
|
||||||
|
|
||||||
downloadFileFromRepo = ({repo, file}, callback) ->
|
downloadFileFromRepo = ({repo, file}, callback) ->
|
||||||
@ -34,6 +36,7 @@ module.exports = (grunt) ->
|
|||||||
if error?
|
if error?
|
||||||
done(error)
|
done(error)
|
||||||
else
|
else
|
||||||
|
rm('docs/output/api')
|
||||||
args = [
|
args = [
|
||||||
commonArgs...
|
commonArgs...
|
||||||
'--title', 'Atom API Documentation'
|
'--title', 'Atom API Documentation'
|
||||||
|
@ -1,11 +1,25 @@
|
|||||||
path = require 'path'
|
path = require 'path'
|
||||||
|
|
||||||
module.exports = (grunt) ->
|
module.exports = (grunt) ->
|
||||||
{cp, mkdir, rm} = require('./task-helpers')(grunt)
|
{cp, mkdir, rm, spawn} = require('./task-helpers')(grunt)
|
||||||
|
|
||||||
grunt.registerTask 'install', 'Install the built application', ->
|
grunt.registerTask 'install', 'Install the built application', ->
|
||||||
installDir = grunt.config.get('atom.installDir')
|
installDir = grunt.config.get('atom.installDir')
|
||||||
shellAppDir = grunt.config.get('atom.shellAppDir')
|
shellAppDir = grunt.config.get('atom.shellAppDir')
|
||||||
rm installDir
|
if process.platform is 'win32'
|
||||||
mkdir path.dirname(installDir)
|
done = @async()
|
||||||
cp shellAppDir, installDir
|
|
||||||
|
runas = require 'runas'
|
||||||
|
copyFolder = path.resolve 'script', 'copy-folder.cmd'
|
||||||
|
# cmd /c ""script" "source" "destination""
|
||||||
|
arg = "/c \"\"#{copyFolder}\" \"#{shellAppDir}\" \"#{installDir}\"\""
|
||||||
|
if runas('cmd', [arg], hide: true) isnt 0
|
||||||
|
done("Failed to copy #{shellAppDir} to #{installDir}")
|
||||||
|
|
||||||
|
createShortcut = path.resolve 'script', 'create-shortcut.cmd'
|
||||||
|
args = ['/c', createShortcut, path.join(installDir, 'atom.exe'), 'Atom']
|
||||||
|
spawn {cmd: 'cmd', args}, done
|
||||||
|
else
|
||||||
|
rm installDir
|
||||||
|
mkdir path.dirname(installDir)
|
||||||
|
cp shellAppDir, installDir
|
||||||
|
@ -41,7 +41,7 @@ module.exports = (grunt) ->
|
|||||||
|
|
||||||
strings =
|
strings =
|
||||||
CompanyName: 'GitHub, Inc.'
|
CompanyName: 'GitHub, Inc.'
|
||||||
FileDescription: 'The hackable, collaborative editor'
|
FileDescription: 'The hackable editor'
|
||||||
LegalCopyright: 'Copyright (C) 2013 GitHub, Inc. All rights reserved'
|
LegalCopyright: 'Copyright (C) 2013 GitHub, Inc. All rights reserved'
|
||||||
ProductName: 'Atom'
|
ProductName: 'Atom'
|
||||||
ProductVersion: version
|
ProductVersion: version
|
||||||
|
@ -14,12 +14,26 @@ overview of the main editor API.
|
|||||||
Check out the [Atom][Atom] class docs to see what globals are available and
|
Check out the [Atom][Atom] class docs to see what globals are available and
|
||||||
what they provide.
|
what they provide.
|
||||||
|
|
||||||
You can also require many of these classes in your packages via:
|
You can also require many of these classes in your package via:
|
||||||
|
|
||||||
```coffee
|
```coffee
|
||||||
{EditorView} = require 'atom'
|
{EditorView} = require 'atom'
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The classes available from `require 'atom'` are:
|
||||||
|
* [BufferedProcess][BufferedProcess]
|
||||||
|
* [BufferedNodeProcess][BufferedNodeProcess]
|
||||||
|
* [Directory][Directory]
|
||||||
|
* [EditorView][EditorView]
|
||||||
|
* [File][File]
|
||||||
|
* [Git][Git]
|
||||||
|
* [Point][Point]
|
||||||
|
* [Range][Range]
|
||||||
|
* [ScrollView][ScrollView]
|
||||||
|
* [SelectList][SelectList]
|
||||||
|
* [View][View]
|
||||||
|
* [WorkspaceView][WorkspaceView]
|
||||||
|
|
||||||
### How do I create a package?
|
### How do I create a package?
|
||||||
|
|
||||||
You probably want to read the [creating a package][creating-a-package]
|
You probably want to read the [creating a package][creating-a-package]
|
||||||
@ -31,7 +45,18 @@ Atom ships with node 0.11.10 and the comprehensive node API docs are available
|
|||||||
[here][node-docs].
|
[here][node-docs].
|
||||||
|
|
||||||
[Atom]: ../classes/Atom.html
|
[Atom]: ../classes/Atom.html
|
||||||
|
[BufferedProcess]: ../classes/BufferedProcess.html
|
||||||
|
[BufferedNodeProcess]: ../classes/BufferedNodeProcess.html
|
||||||
|
[Directory]: ../classes/Directory.html
|
||||||
[Editor]: ../classes/Editor.html
|
[Editor]: ../classes/Editor.html
|
||||||
[EditorView]: ../classes/EditorView.html
|
[EditorView]: ../classes/EditorView.html
|
||||||
|
[File]: ../classes/File.html
|
||||||
|
[Git]: ../classes/Git.html
|
||||||
|
[Point]: ../classes/Point.html
|
||||||
|
[Range]: ../classes/Range.html
|
||||||
|
[ScrollView]: ../classes/ScrollView.html
|
||||||
|
[SelectList]: ../classes/SelectList.html
|
||||||
|
[View]: ../classes/View.html
|
||||||
|
[WorkspaceView]: ../classes/WorkspaceView.html
|
||||||
[creating-a-package]: https://www.atom.io/docs/latest/creating-a-package
|
[creating-a-package]: https://www.atom.io/docs/latest/creating-a-package
|
||||||
[node-docs]: http://nodejs.org/docs/v0.11.10/api
|
[node-docs]: http://nodejs.org/docs/v0.11.10/api
|
||||||
|
76
docs/advanced/configuration.md
Normal file
76
docs/advanced/configuration.md
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
## Configuration API
|
||||||
|
|
||||||
|
### Reading Config Settings
|
||||||
|
|
||||||
|
If you are writing a package that you want to make configurable, you'll need to
|
||||||
|
read config settings via the `atom.config` global. You can read the current
|
||||||
|
value of a namespaced config key with `atom.config.get`:
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
# read a value with `config.get`
|
||||||
|
@showInvisibles() if atom.config.get "editor.showInvisibles"
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can use the `::observeConfig` to track changes from any view object.
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
class MyView extends View
|
||||||
|
initialize: ->
|
||||||
|
@observeConfig 'editor.fontSize', () =>
|
||||||
|
@adjustFontSize()
|
||||||
|
```
|
||||||
|
|
||||||
|
The `::observeConfig` method will call the given callback immediately with the
|
||||||
|
current value for the specified key path, and it will also call it in the future
|
||||||
|
whenever the value of that key path changes.
|
||||||
|
|
||||||
|
Subscriptions made with `observeConfig` are automatically canceled when the
|
||||||
|
view is removed. You can cancel config subscriptions manually via the
|
||||||
|
`unobserveConfig` method.
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
view1.unobserveConfig() # unobserve all properties
|
||||||
|
```
|
||||||
|
|
||||||
|
You can add the ability to observe config values to non-view classes by
|
||||||
|
extending their prototype with the `ConfigObserver` mixin:
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
{ConfigObserver} = require 'atom'
|
||||||
|
|
||||||
|
class MyClass
|
||||||
|
ConfigObserver.includeInto(this)
|
||||||
|
|
||||||
|
constructor: ->
|
||||||
|
@observeConfig 'editor.showInvisibles', -> # ...
|
||||||
|
|
||||||
|
destroy: ->
|
||||||
|
@unobserveConfig()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Writing Config Settings
|
||||||
|
|
||||||
|
The `atom.config` database is populated on startup from `~/.atom/config.cson`,
|
||||||
|
but you can programmatically write to it with `atom.config.set`:
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
# basic key update
|
||||||
|
atom.config.set("core.showInvisibles", true)
|
||||||
|
```
|
||||||
|
|
||||||
|
You should never mutate the value of a config key, because that would circumvent
|
||||||
|
the notification of observers. You can however use methods like `pushAtKeyPath`,
|
||||||
|
`unshiftAtKeyPath`, and `removeAtKeyPath` to manipulate mutable config values.
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
atom.config.pushAtKeyPath("core.disabledPackages", "wrap-guide")
|
||||||
|
atom.config.removeAtKeyPath("core.disabledPackages", "terminal")
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use `setDefaults`, which will assign default values for keys that
|
||||||
|
are always overridden by values assigned with `set`. Defaults are not written
|
||||||
|
out to the the `config.json` file to prevent it from becoming cluttered.
|
||||||
|
|
||||||
|
```coffeescript
|
||||||
|
atom.config.setDefaults("editor", fontSize: 18, showInvisibles: true)
|
||||||
|
```
|
34
docs/advanced/globals.md
Normal file
34
docs/advanced/globals.md
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
# Globals
|
||||||
|
|
||||||
|
Atom exposes several services through singleton objects accessible via the
|
||||||
|
`atom` global:
|
||||||
|
|
||||||
|
* atom
|
||||||
|
* workspace:
|
||||||
|
Manipulate and query the state of the user interface for the current
|
||||||
|
window. Open editors, manipulate panes.
|
||||||
|
* workspaceView:
|
||||||
|
Similar to workspace, but provides access to the root of all views in the
|
||||||
|
current window.
|
||||||
|
* project:
|
||||||
|
Access the directory associated with the current window. Load editors,
|
||||||
|
perform project-wide searches, register custom openers for special file
|
||||||
|
types.
|
||||||
|
* config:
|
||||||
|
Read, write, and observe user configuration settings.
|
||||||
|
* keymap:
|
||||||
|
Add and query the currently active keybindings.
|
||||||
|
* deserializers:
|
||||||
|
Deserialize instances from their state objects and register deserializers.
|
||||||
|
* packages:
|
||||||
|
Activate, deactivate, and query user packages.
|
||||||
|
* themes:
|
||||||
|
Activate, deactivate, and query user themes.
|
||||||
|
* contextMenu:
|
||||||
|
Register context menus.
|
||||||
|
* menu:
|
||||||
|
Register application menus.
|
||||||
|
* pasteboard:
|
||||||
|
Read from and write to the system pasteboard.
|
||||||
|
* syntax:
|
||||||
|
Assign and query syntactically-scoped properties.
|
123
docs/advanced/keymaps.md
Normal file
123
docs/advanced/keymaps.md
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
# Keymaps In-Depth
|
||||||
|
|
||||||
|
## Structure of a Keymap File
|
||||||
|
|
||||||
|
Keymap files are encoded as JSON or CSON files containing nested hashes. They
|
||||||
|
work much like stylesheets, but instead of applying style properties to elements
|
||||||
|
matching the selector, they specify the meaning of keystrokes on elements
|
||||||
|
matching the selector. Here is an example of some bindings that apply when
|
||||||
|
keystrokes pass through elements with the class `.editor`:
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
'.editor':
|
||||||
|
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||||
|
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||||
|
'ctrl-A': 'editor:select-to-first-character-of-line'
|
||||||
|
'ctrl-shift-e': 'editor:select-to-end-of-line'
|
||||||
|
'cmd-left': 'editor:move-to-first-character-of-line'
|
||||||
|
|
||||||
|
'.editor:not(.mini)'
|
||||||
|
'cmd-alt-[': 'editor:fold-current-row'
|
||||||
|
'cmd-alt-]': 'editor:unfold-current-row'
|
||||||
|
```
|
||||||
|
|
||||||
|
Beneath the first selector are several bindings, mapping specific *keystroke
|
||||||
|
patterns* to *commands*. When an element with the `.editor` class is focused and
|
||||||
|
`cmd-delete` is pressed, an custom DOM event called
|
||||||
|
`editor:backspace-to-beginning-of-line` is emitted on the `.editor` element.
|
||||||
|
|
||||||
|
The second selector group also targets editors, but only if they don't have the
|
||||||
|
`.mini` class. In this example, the commands for code folding don't really make
|
||||||
|
sense on mini-editors, so the selector restricts them to regular editors.
|
||||||
|
|
||||||
|
### Keystroke Patterns
|
||||||
|
|
||||||
|
Keystroke patterns express one or more keystrokes combined with optional
|
||||||
|
modifier keys. For example: `ctrl-w v`, or `cmd-shift-up`. A keystroke is
|
||||||
|
composed of the following symbols, separated by a `-`. A multi-keystroke pattern
|
||||||
|
can be expressed as keystroke patterns separated by spaces.
|
||||||
|
|
||||||
|
|
||||||
|
| Type | Examples
|
||||||
|
| --------------------|----------------------------
|
||||||
|
| Character literals | `a` `4` `$`
|
||||||
|
| Modifier keys | `cmd` `ctrl` `alt` `shift`
|
||||||
|
| Special keys | `enter` `escape` `backspace` `delete` `tab` `home` `end` `pageup` `pagedown` `left` `right` `up` `down`
|
||||||
|
|
||||||
|
### Commands
|
||||||
|
|
||||||
|
Commands are custom DOM events that are triggered when a keystroke matches a
|
||||||
|
binding. This allows user interface code to listen for named commands without
|
||||||
|
specifying the specific keybinding that triggers it. For example, the following
|
||||||
|
code sets up {EditorView} to listen for commands to move the cursor to the first
|
||||||
|
character of the current line:
|
||||||
|
|
||||||
|
```coffee
|
||||||
|
class EditorView
|
||||||
|
listenForEvents: ->
|
||||||
|
@command 'editor:move-to-first-character-of-line', =>
|
||||||
|
@editor.moveCursorToFirstCharacterOfLine()
|
||||||
|
```
|
||||||
|
|
||||||
|
The `::command` method is basically an enhanced version of jQuery's `::on`
|
||||||
|
method that listens for a custom DOM event and adds some metadata to the DOM,
|
||||||
|
which is read by the command palette.
|
||||||
|
|
||||||
|
When you are looking to bind new keys, it is often useful to use the command
|
||||||
|
palette (`ctrl-shift-p`) to discover what commands are being listened for in a
|
||||||
|
given focus context. Commands are "humanized" following a simple algorithm, so a
|
||||||
|
command like `editor:fold-current-row` would appear as "Editor: Fold Current
|
||||||
|
Row".
|
||||||
|
|
||||||
|
### Specificity and Cascade Order
|
||||||
|
|
||||||
|
As is the case with CSS applying styles, when multiple bindings match for a
|
||||||
|
single element, the conflict is resolved by choosing the most *specific*
|
||||||
|
selector. If two matching selectors have the same specificity, the binding
|
||||||
|
for the selector appearing later in the cascade takes precedence.
|
||||||
|
|
||||||
|
Currently, there's no way to specify selector ordering within a single keymap,
|
||||||
|
because JSON objects do not preserve order. We eventually plan to introduce a
|
||||||
|
custom CSS-like file format for keymaps that allows for ordering within a single
|
||||||
|
file. For now, we've opted to handle cases where selector ordering is critical
|
||||||
|
by breaking the keymap into two separate files, such as `snippets-1.cson` and
|
||||||
|
`snippets-2.cson`.
|
||||||
|
|
||||||
|
## Overloading Key Bindings
|
||||||
|
|
||||||
|
Occasionally, it makes sense to layer multiple actions on top of the same key
|
||||||
|
binding. An example of this is the snippets package. Snippets are inserted by
|
||||||
|
typing a snippet prefix such as `for` and then pressing `tab`. Every time `tab`
|
||||||
|
is pressed, we want to execute code attempting to expand a snippet if one exists
|
||||||
|
for the text preceding the cursor. If a snippet *doesn't* exist, we want `tab`
|
||||||
|
to actually insert whitespace.
|
||||||
|
|
||||||
|
To achieve this, the snippets package makes use of the `.abortKeyBinding()`
|
||||||
|
method on the event object representing the `snippets:expand` command.
|
||||||
|
|
||||||
|
```coffee-script
|
||||||
|
# pseudo-code
|
||||||
|
editor.command 'snippets:expand', (e) =>
|
||||||
|
if @cursorFollowsValidPrefix()
|
||||||
|
@expandSnippet()
|
||||||
|
else
|
||||||
|
e.abortKeyBinding()
|
||||||
|
```
|
||||||
|
|
||||||
|
When the event handler observes that the cursor does not follow a valid prefix,
|
||||||
|
it calls `e.abortKeyBinding()`, telling the keymap system to continue searching
|
||||||
|
for another matching binding.
|
||||||
|
|
||||||
|
## Step-by-Step: How Keydown Events are Mapped to Commands
|
||||||
|
|
||||||
|
* A keydown event occurs on a *focused* element.
|
||||||
|
* Starting at the focused element, the keymap walks upward towards the root of
|
||||||
|
the document, searching for the most specific CSS selector that matches the
|
||||||
|
current DOM element and also contains a keystroke pattern matching the keydown
|
||||||
|
event.
|
||||||
|
* When a matching keystroke pattern is found, the search is terminated and the
|
||||||
|
pattern's corresponding command is triggered on the current element.
|
||||||
|
* If `.abortKeyBinding()` is called on the triggered event object, the search
|
||||||
|
is resumed, triggering a binding on the next-most-specific CSS selector for
|
||||||
|
the same element or continuing upward to parent elements.
|
||||||
|
* If no bindings are found, the event is handled by Chromium normally.
|
@ -154,7 +154,7 @@ loaded in alphabetical order. An optional `keymaps` array in your _package.json_
|
|||||||
can specify which keymaps to load and in what order.
|
can specify which keymaps to load and in what order.
|
||||||
|
|
||||||
|
|
||||||
Keybindings are executed by determining which element the keypress occured on. In
|
Keybindings are executed by determining which element the keypress occurred on. In
|
||||||
the example above, `changer:magic` command is executed when pressing `ctrl-V` on
|
the example above, `changer:magic` command is executed when pressing `ctrl-V` on
|
||||||
the `.tree-view-scroller` element.
|
the `.tree-view-scroller` element.
|
||||||
|
|
||||||
@ -381,7 +381,7 @@ Additional libraries can be found by browsing Atom's *node_modules* folder.
|
|||||||
[apm]: https://github.com/atom/apm
|
[apm]: https://github.com/atom/apm
|
||||||
[git-tag]: http://git-scm.com/book/en/Git-Basics-Tagging
|
[git-tag]: http://git-scm.com/book/en/Git-Basics-Tagging
|
||||||
[wrap-guide]: https://github.com/atom/wrap-guide/
|
[wrap-guide]: https://github.com/atom/wrap-guide/
|
||||||
[keymaps]: internals/keymaps.md
|
[keymaps]: advanced/keymaps.md
|
||||||
[theme-variables]: theme-variables.md
|
[theme-variables]: theme-variables.md
|
||||||
[tm-tokens]: http://manual.macromates.com/en/language_grammars.html
|
[tm-tokens]: http://manual.macromates.com/en/language_grammars.html
|
||||||
[spacepen]: https://github.com/nathansobo/space-pen
|
[spacepen]: https://github.com/nathansobo/space-pen
|
||||||
|
@ -19,13 +19,11 @@ bindings][key-bindings] section.
|
|||||||
|
|
||||||
### Working With Files
|
### Working With Files
|
||||||
|
|
||||||
Atom windows are scoped to the directory they're opened from. If you launch Atom
|
Atom windows are scoped to a single directory on disk. If you launch Atom from
|
||||||
from the command line everything will be relative to the current directory. This
|
the command line via the `atom` command and don't specify a path, Atom opens a
|
||||||
means that the tree view on the left will only show files contained within that
|
window for the current working directory. The current window's directory will be
|
||||||
directory.
|
visible as the root of the tree view at the left, and also serve as the context
|
||||||
|
for all file-related operations.
|
||||||
This can be a useful way to organize multiple projects, as each project will be
|
|
||||||
contained within its own window.
|
|
||||||
|
|
||||||
#### Finding Files
|
#### Finding Files
|
||||||
|
|
||||||
@ -34,20 +32,17 @@ begin typing the name of the file you're looking for. If you are looking for a
|
|||||||
file that is already open press `cmd-b` to bring up a searchable list of open
|
file that is already open press `cmd-b` to bring up a searchable list of open
|
||||||
files.
|
files.
|
||||||
|
|
||||||
You can also use the tree view to navigate to a file. To open or move focus to
|
You can also use the tree view to navigate to a file. To open and focus the
|
||||||
the tree view, press `cmd-\`. You can then navigate to a file using the arrow
|
the tree view, press `ctrl-0`. The tree view can be toggled open and closed with
|
||||||
keys and select it with `return`.
|
`cmd-\`.
|
||||||
|
|
||||||
#### Adding, Moving, Deleting Files
|
#### Adding, Moving, Deleting Files
|
||||||
|
|
||||||
Currently, all file modification is performed via the tree view. To add a file,
|
Currently, all file modification is performed via the tree view. Add, move, or
|
||||||
select a directory in the tree view and press `a`. Then type the name of the
|
delete a file by right-clicking in the tree view and selecting the desired
|
||||||
file. Any intermediate directories you type will be created automatically if
|
operation from the context menu. You can also perform these operations from the
|
||||||
needed.
|
keyboard by selecting a file or directory and using `a` to add, `m` to move, and
|
||||||
|
`delete` to delete.
|
||||||
To move or rename a file or directory, select it in the tree view and press `m`.
|
|
||||||
|
|
||||||
To delete a file, select it in the tree view and press `delete`.
|
|
||||||
|
|
||||||
### Searching
|
### Searching
|
||||||
|
|
||||||
@ -58,35 +53,43 @@ To search within a buffer use `cmd-f`. To search the entire project use
|
|||||||
|
|
||||||
#### Navigating By Symbols
|
#### Navigating By Symbols
|
||||||
|
|
||||||
If you want to jump to a method press `cmd-r`. It opens a list of all symbols
|
To jump to a symbol such as a method definition, press `cmd-r`. This opens a
|
||||||
in the current file.
|
list of all symbols in the current file, which you can fuzzy filter similarly to
|
||||||
|
`cmd-t`.
|
||||||
|
|
||||||
To search for symbols across your project use `cmd-shift-r`, but you'll need to
|
To search for symbols across your project, use `cmd-shift-r`. First you'll need
|
||||||
make sure you have a ctags installed and a tags file generated for your project.
|
to make sure you have ctags installed and a tags file generated for your
|
||||||
Also, if you're editing CoffeeScript, it's a good idea to update your `~/.ctags`
|
project. Also, if you're editing CoffeeScript, it's a good idea to update your
|
||||||
file to understand the language. Here is [a good example][ctags].
|
`~/.ctags` file to understand the language. Here is [a good example][ctags].
|
||||||
|
|
||||||
### Split Panes
|
### Split Panes
|
||||||
|
|
||||||
You can split any editor pane horizontally or vertically by using `cmd-k right` or
|
You can split any editor pane horizontally or vertically by using `cmd-k right`
|
||||||
`cmd-k down`. Once you have a split pane, you can move focus between them with
|
or `cmd-k down`. Once you have a split pane, you can move focus between them
|
||||||
`cmd-k cmd-right` or `cmd-k cmd-down`. To close a pane, close all tabs inside it.
|
with `cmd-k cmd-right` or `cmd-k cmd-down`. To close a pane, close all its
|
||||||
|
editors with `meta-w`, then press `meta-w` one more time to close the pane. You
|
||||||
|
can configure panes to auto-close with empty in the preferences.
|
||||||
|
|
||||||
### Folding
|
### Folding
|
||||||
|
|
||||||
You can fold everything with `alt-cmd-{` and unfold everything with
|
You can fold blocks of code by clicking the arrows that appear when you hover
|
||||||
`alt-cmd-}`. Or, you can fold / unfold by a single level with `alt-cmd-[` and
|
your mouse cursor over the gutter. You can also fold and unfold from the
|
||||||
`alt-cmd-]`.
|
keyboard with `alt-cmd-[` and `alt-cmd-]`. To fold everything, use
|
||||||
|
`alt-cmd-shift-{` and to unfold everything use `alt-cmd-shift-}`. You can also
|
||||||
|
fold at a specific indentation level with `cmd-k cmd-N` where N is the
|
||||||
|
indentation depth.
|
||||||
|
|
||||||
### Soft-Wrap
|
### Soft-Wrap
|
||||||
|
|
||||||
If you want to toggle soft wrap, trigger the command from the command palette.
|
If you want to toggle soft wrap, trigger the command from the command palette.
|
||||||
Press `cmd-shift-P` to open the palette, then type "wrap" to find the correct
|
Press `cmd-shift-P` to open the palette, then type "wrap" to find the correct
|
||||||
command.
|
command. By default, lines will wrap based on the size of the editor. If you
|
||||||
|
prefer to wrap at a specific line length, toggle "Wrap at preferred line length"
|
||||||
|
in preferences.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Press `cmd-,` to display the a settings pane. This serves as the primary
|
Press `cmd-,` to display the preferences pane. This serves as the primary
|
||||||
interface for adjusting config settings, installing packages and changing
|
interface for adjusting config settings, installing packages and changing
|
||||||
themes.
|
themes.
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
### Advanced Topics
|
### Advanced Topics
|
||||||
|
|
||||||
* [Configuration](internals/configuration.md)
|
* [Configuration](advanced/configuration.md)
|
||||||
* [Keymaps](internals/keymaps.md)
|
* [Keymaps](advanced/keymaps.md)
|
||||||
* [Serialization](internals/serialization.md)
|
* [Serialization](advanced/serialization.md)
|
||||||
* [View System](internals/view-system.md)
|
* [View System](advanced/view-system.md)
|
||||||
|
@ -1,61 +0,0 @@
|
|||||||
## Configuration API
|
|
||||||
|
|
||||||
### Reading Config Settings
|
|
||||||
|
|
||||||
If you are writing a package that you want to make configurable, you'll need to
|
|
||||||
read config settings. You can read a value from `config` with `config.get`:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
# read a value with `config.get`
|
|
||||||
@showInvisibles() if config.get "edtior.showInvisibles"
|
|
||||||
```
|
|
||||||
|
|
||||||
Or you can use `observeConfig` to track changes from a view object.
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
class MyView extends View
|
|
||||||
initialize: ->
|
|
||||||
@observeConfig 'editor.fontSize', () =>
|
|
||||||
@adjustFontSize()
|
|
||||||
```
|
|
||||||
|
|
||||||
The `observeConfig` method will call the given callback immediately with the
|
|
||||||
current value for the specified key path, and it will also call it in the future
|
|
||||||
whenever the value of that key path changes.
|
|
||||||
|
|
||||||
Subscriptions made with `observeConfig` are automatically canceled when the
|
|
||||||
view is removed. You can cancel config subscriptions manually via the
|
|
||||||
`unobserveConfig` method.
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
view1.unobserveConfig() # unobserve all properties
|
|
||||||
```
|
|
||||||
|
|
||||||
You can add the ability to observe config values to non-view classes by
|
|
||||||
extending their prototype with the `ConfigObserver` mixin:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
ConfigObserver = require 'config-observer'
|
|
||||||
_.extend MyClass.prototype, ConfigObserver
|
|
||||||
```
|
|
||||||
|
|
||||||
### Writing Config Settings
|
|
||||||
|
|
||||||
As discussed above, the config database is automatically populated from
|
|
||||||
`config.cson` when Atom is started, but you can programmatically write to it in
|
|
||||||
the following way:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
# basic key update
|
|
||||||
config.set("core.showInvisibles", true)
|
|
||||||
|
|
||||||
config.pushAtKeyPath("core.disabledPackages", "wrap-guide")
|
|
||||||
```
|
|
||||||
|
|
||||||
You can also use `setDefaults`, which will assign default values for keys that
|
|
||||||
are always overridden by values assigned with `set`. Defaults are not written out
|
|
||||||
to the the `config.json` file to prevent it from becoming cluttered.
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
config.setDefaults("editor", fontSize: 18, showInvisibles: true)
|
|
||||||
```
|
|
@ -1,69 +0,0 @@
|
|||||||
## Keymaps In-Depth
|
|
||||||
|
|
||||||
### Structure of a Keymap File
|
|
||||||
|
|
||||||
Keymap files are encoded as JSON or CSON files containing nested hashes. The
|
|
||||||
top-level keys of a keymap are **CSS 3 selectors**, which specify a particular
|
|
||||||
context in Atom's interface. Common selectors are `.editor`, which scopes
|
|
||||||
bindings to just work when an editor is focused, and `body`, which scopes
|
|
||||||
bindings globally.
|
|
||||||
|
|
||||||
Beneath the selectors are hashes mapping **keystroke patterns** to
|
|
||||||
**semantic events**. A keystroke pattern looks like the following examples.
|
|
||||||
Note that the last example describes multiple keystrokes in succession:
|
|
||||||
|
|
||||||
- `p`
|
|
||||||
- `2`
|
|
||||||
- `ctrl-p`
|
|
||||||
- `ctrl-alt-cmd-p`
|
|
||||||
- `tab`
|
|
||||||
- `escape`
|
|
||||||
- `enter`
|
|
||||||
- `ctrl-w w`
|
|
||||||
|
|
||||||
A semantic event is the name of the custom event that will be triggered on the
|
|
||||||
target of the keydown event when a key binding matches. You can use the command
|
|
||||||
palette (bound to `cmd-shift-P`), to get a list of relevant events and their bindings
|
|
||||||
in any focused context in Atom.
|
|
||||||
|
|
||||||
### Rules for Mapping A Keydown Event to A Semantic Event
|
|
||||||
|
|
||||||
A keymap's job is to translate a physical keystroke event (like `cmd-D`) into a
|
|
||||||
semantic event (like `editor:duplicate-line`). Whenever a keydown event occurs
|
|
||||||
on a focused element, it bubbles up the DOM as usual. As soon as an element on
|
|
||||||
the bubble path matches a key binding for the keystroke, the binding's semantic
|
|
||||||
event is triggered on the original target of the keydown event. Just as with
|
|
||||||
CSS, if multiple selectors match an element, the most specific selector is
|
|
||||||
favored. If two selectors have the same specificity, the selector that occurs
|
|
||||||
latest in the cascade is favored.
|
|
||||||
|
|
||||||
Currently, there's no way to specify selector ordering within a single keymap,
|
|
||||||
because JSON hashes do not preserve order. Rather than making the format more
|
|
||||||
awkward in order to preserve order, we've opted to handle cases where order is
|
|
||||||
critical by breaking the keymap into two separate files, such as
|
|
||||||
`snippets-1.cson` and `snippets-2.cson`.
|
|
||||||
|
|
||||||
### Overloading Key Bindings
|
|
||||||
|
|
||||||
Occasionally, it makes sense to layer multiple actions on top of the same key
|
|
||||||
binding. An example of this is the snippets package. You expand a snippet by
|
|
||||||
pressing `tab` immediately following a snippet's prefix. But if the cursor is
|
|
||||||
not following a valid snippet prefix, then we want tab to perform its normal
|
|
||||||
action (probably inserting a tab character or the appropriate number of spaces).
|
|
||||||
|
|
||||||
To achieve this, the snippets package makes use of the `abortKeyBinding` method
|
|
||||||
on the event object that's triggered by the binding for `tab`.
|
|
||||||
|
|
||||||
```coffee-script
|
|
||||||
# pseudo-code
|
|
||||||
editor.command 'snippets:expand', (e) =>
|
|
||||||
if @cursorFollowsValidPrefix()
|
|
||||||
@expandSnippet()
|
|
||||||
else
|
|
||||||
e.abortKeyBinding()
|
|
||||||
```
|
|
||||||
|
|
||||||
When the event handler observes that the cursor does not follow a valid prefix,
|
|
||||||
it calls `e.abortKeyBinding()`, which tells the keymap system to continue
|
|
||||||
searching up the cascade for another matching binding. In this case, the default
|
|
||||||
implementation of `tab` ends up getting triggered.
|
|
@ -1,70 +0,0 @@
|
|||||||
**Polish the user experience**
|
|
||||||
|
|
||||||
First and foremost, Atom is a **product**. Atom needs to feel familiar and
|
|
||||||
inviting. This includes a solid introductory experience and parity with the most
|
|
||||||
important features of Sublime Text.
|
|
||||||
|
|
||||||
* First launch UI and flow (actions below should be easily discoverable)
|
|
||||||
* Create a new file
|
|
||||||
* Open a project and edit an existing file
|
|
||||||
* Install a package
|
|
||||||
* Change settings (adjust theme, change key bindings, set config options)
|
|
||||||
* How to use command P
|
|
||||||
* Use collaboration internally
|
|
||||||
* How and where to edit keyBinding should be obvious to new users
|
|
||||||
* Finish find and replace in buffer/project
|
|
||||||
* Atom should start < 300ms
|
|
||||||
* Match Sublime's multiple selection functionality (#523)
|
|
||||||
* Fix softwrap bugs
|
|
||||||
* Menus & Context menus
|
|
||||||
* Track usage/engagement of our users (make this opted in?)
|
|
||||||
* Windows support
|
|
||||||
* Reliably and securely auto-update and list what's new
|
|
||||||
* Secure access to the keychain (don't give every package access to the keychain)
|
|
||||||
* Secure access to GitHub (each package can ask to have it's own oauth token)
|
|
||||||
* Don't crash when opening/editing large (> 10Mb) files
|
|
||||||
* Send js and native crash reports to a remote server
|
|
||||||
|
|
||||||
**Lay solid groundwork for a package and theme ecosystem**
|
|
||||||
|
|
||||||
Extensibility is one of Atom's key value propositions, so a smooth experience
|
|
||||||
for creating and maintaining packages is just as important as the user
|
|
||||||
experience. The package development, dependency and publishing workflow needs to
|
|
||||||
be solid. We also want to have a mechanism for clearly communicating with
|
|
||||||
package authors about breaking API changes.
|
|
||||||
|
|
||||||
* Finish APM backend (integrate with GitHub Releases)
|
|
||||||
* Streamline Dev workflow
|
|
||||||
* `apm create` - create package scaffolding
|
|
||||||
* `apm test` - so users can run focused package tests
|
|
||||||
* `apm publish` - should integrate release best practices (ie npm version)
|
|
||||||
* Determine which classes and methods should be included in the public API
|
|
||||||
* Users can find/install/update/fork existing packages and themes
|
|
||||||
|
|
||||||
**Tighten up the view layer**
|
|
||||||
Our current approach to the view layer need some improvement. We want to
|
|
||||||
actively promote the use of the M-V-VM design pattern, provide some declarative
|
|
||||||
event binding mechanisms in the view layer, and improve the performance of the
|
|
||||||
typical package specs. We don't want the current approach to be used as an
|
|
||||||
example in a bunch of new packages, so it's important to improve it now.
|
|
||||||
|
|
||||||
* Add marker view API
|
|
||||||
|
|
||||||
**Get atom.io online with some exciting articles and documentation**
|
|
||||||
We'd love to send our private alpha candidates to a nice site with information
|
|
||||||
about what Atom is, the philosophies and technologies behind it, and guidance
|
|
||||||
for how to get started.
|
|
||||||
|
|
||||||
* Design and create www.atom.io
|
|
||||||
* Guides
|
|
||||||
* Theme & Package creation guide
|
|
||||||
* Full API per release tag
|
|
||||||
* Changelog per release
|
|
||||||
* Explanation of features
|
|
||||||
* Explain Semver and general plans for the future (reassure developers we care about them)
|
|
||||||
* General Values/Goals
|
|
||||||
* Make docs accessible from Atom
|
|
||||||
* Community/contribution guidelines
|
|
||||||
* Is all communication to be done through issues?
|
|
||||||
* When should you publish a plugin?
|
|
||||||
* Do we need to vet plugins from a security perspective?
|
|
@ -1,16 +0,0 @@
|
|||||||
## Proposed Timeline
|
|
||||||
|
|
||||||
1. **October 30st** - Internal launch - persuade as many githubbers to switch as
|
|
||||||
possible.
|
|
||||||
|
|
||||||
1. Triage bugs and identify what needs to be fixed before private alpha. Maybe
|
|
||||||
talk to @chrissiebrodigan about doing a UX study.
|
|
||||||
|
|
||||||
1. **November 22st** - Private alpha launch
|
|
||||||
|
|
||||||
1. Trickle out invites as people ask/we need more testers.
|
|
||||||
|
|
||||||
1. If our usage metrics/engagement metrics decrease, stop, identify the issue
|
|
||||||
and fix it before continuing.
|
|
||||||
|
|
||||||
1. Launch
|
|
@ -1,335 +1,145 @@
|
|||||||
# Creating Your First Package
|
# Create Your First Package
|
||||||
|
|
||||||
Let's take a look at creating your first package.
|
This tutorial will guide you though creating a simple command that replaces the
|
||||||
|
selected text with [ascii art](http://en.wikipedia.org/wiki/ASCII_art). When you
|
||||||
|
run our new command with the word "cool" selected, it will be replaced with:
|
||||||
|
|
||||||
To get started, hit `cmd-shift-P`, and start typing "Generate Package" to generate
|
```
|
||||||
a package. Once you select the "Generate Package" command, it'll ask you for a
|
/\_ \
|
||||||
name for your new package. Let's call ours _changer_.
|
___ ___ ___\//\ \
|
||||||
|
/'___\ / __`\ / __`\\ \ \
|
||||||
Atom will pop open a new window, showing the _changer_ package with a default set of
|
/\ \__//\ \L\ \/\ \L\ \\_\ \_
|
||||||
folders and files created for us. Hit `cmd-shift-P` and start typing "Changer." You'll
|
\ \____\ \____/\ \____//\____\
|
||||||
see a new `Changer:Toggle` command which, if selected, pops up a greeting. So far,
|
\/____/\/___/ \/___/ \/____/
|
||||||
so good!
|
|
||||||
|
|
||||||
In order to demonstrate the capabilities of Atom and its API, our Changer plugin
|
|
||||||
is going to do two things:
|
|
||||||
|
|
||||||
1. It'll show only modified files in the file tree
|
|
||||||
2. It'll append a new pane to the editor with some information about the modified
|
|
||||||
files
|
|
||||||
|
|
||||||
Let's get started!
|
|
||||||
|
|
||||||
## Changing Keybindings and Commands
|
|
||||||
|
|
||||||
Since Changer is primarily concerned with the file tree, let's write a
|
|
||||||
key binding that works only when the tree is focused. Instead of using the
|
|
||||||
default `toggle`, our keybinding executes a new command called `magic`.
|
|
||||||
|
|
||||||
_keymaps/changer.cson_ should change to look like this:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
'.tree-view':
|
|
||||||
'ctrl-V': 'changer:magic'
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Notice that the keybinding is called `ctrl-V` — that's actually `ctrl-shift-v`.
|
The final package can be viewed at
|
||||||
You can use capital letters to denote using `shift` for your binding.
|
[https://github.com/atom/ascii-art](https://github.com/atom/ascii-art).
|
||||||
|
|
||||||
`.tree-view` represents the parent container for the tree view.
|
To begin, press `cmd-shift-P` to bring up the [Command
|
||||||
Keybindings only work within the context of where they're entered. In this case,
|
Palette](https://github.com/atom/command-palette). Type "generate package" and
|
||||||
hitting `ctrl-V` anywhere other than tree won't do anything. Obviously, you can
|
select the "Package Generator: Generate Package" command. Now we need to name
|
||||||
bind to any part of the editor using element, id, or class names. For example,
|
the package. Let's call it _ascii-art_.
|
||||||
you can map to `body` if you want to scope to anywhere in Atom, or just `.editor`
|
|
||||||
for the editor portion.
|
|
||||||
|
|
||||||
To bind keybindings to a command, we'll need to do a bit of association in our
|
Atom will open a new window with the contents of our new _ascii-art_ package
|
||||||
CoffeeScript code using the `atom.workspaceView.command` method. This method takes a command
|
displayed in the Tree View. Because this window is opened **after** the package
|
||||||
name and executes a callback function. Open up _lib/changer-view.coffee_, and
|
is created, the ASCII Art package will be loaded and available in our new
|
||||||
change `atom.workspaceView.command "changer:toggle"` to look like this:
|
window. To verify this, toggle the Command Palette (`cmd-shift-P`) and type
|
||||||
|
"ASCII Art" you'll see a new `ASCII Art: Toggle` command. When triggered, this
|
||||||
|
command displays a default message.
|
||||||
|
|
||||||
|
Now let's edit the package files to make our ascii art package do something
|
||||||
|
interesting. Since this package doesn't need any UI, we can remove all
|
||||||
|
view-related code. Start by opening up _lib/ascii-art.coffee_. Remove all view
|
||||||
|
code, so the file looks like this:
|
||||||
|
|
||||||
```coffeescript
|
```coffeescript
|
||||||
atom.workspaceView.command "changer:magic", => @magic()
|
module.exports =
|
||||||
|
activate: ->
|
||||||
```
|
```
|
||||||
|
|
||||||
It's common practice to namespace your commands with your package name, separated
|
## Create a Command
|
||||||
with a colon (`:`). Make sure to rename your `toggle` method to `magic` as well.
|
|
||||||
|
|
||||||
Every time you reload the Atom editor, changes to your package code will be reevaluated,
|
Now let's add a command. We recommend that you namespace your commands with the
|
||||||
just as if you were writing a script for the browser. Reload the editor, click on
|
package name followed by a `:`, so we'll call our command `ascii-art:convert`.
|
||||||
the tree, hit your keybinding, and...nothing happens! What the heck?!
|
Register the command in _lib/ascii-art.coffee_:
|
||||||
|
|
||||||
Open up the _package.json_ file, and find the property called `activationEvents`.
|
```coffeescript
|
||||||
Basically, this key tells Atom to not load a package until it hears a certain event.
|
module.exports =
|
||||||
Change the event to `changer:magic` and reload the editor:
|
activate: ->
|
||||||
|
atom.workspaceView.command "ascii-art:convert", => @convert()
|
||||||
|
|
||||||
|
convert: ->
|
||||||
|
# This assumes the active pane item is an editor
|
||||||
|
editor = atom.workspace.activePaneItem
|
||||||
|
editor.insertText('Hello, World!')
|
||||||
|
```
|
||||||
|
|
||||||
|
The `atom.workspaceView.command` method takes a command name and a callback. The
|
||||||
|
callback executes when the command is triggered. In this case, when the command
|
||||||
|
is triggered the callback will call the `convert` method and insert 'Hello,
|
||||||
|
World!'.
|
||||||
|
|
||||||
|
## Reload the Package
|
||||||
|
|
||||||
|
Before we can trigger `ascii-art:convert`, we need to load the latest code for
|
||||||
|
our package by reloading the window. Run the command `window:reload` from the
|
||||||
|
command palette or by pressing `ctrl-alt-cmd-l`.
|
||||||
|
|
||||||
|
## Trigger the Command
|
||||||
|
|
||||||
|
Now open the command panel and search for the `ascii-art:convert` command. But
|
||||||
|
its not there! To fix this open _package.json_ and find the property called
|
||||||
|
`activationEvents`. Activation Events speed up load time by allowing an Atom to
|
||||||
|
delay a package's activation until it's needed. So add the `ascii-art:convert`
|
||||||
|
to the activationEvents array:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"activationEvents": ["changer:magic"]
|
"activationEvents": ["ascii-art:convert"],
|
||||||
```
|
```
|
||||||
|
|
||||||
Hitting the key binding on the tree now works!
|
First, run reload the window by running the command `window:reload`. Now when
|
||||||
|
you run the `ascii-art:convert` command it will output 'Hello, World!'
|
||||||
|
|
||||||
## Working with Styles
|
## Add A Key Binding
|
||||||
|
|
||||||
The next step is to hide elements in the tree that aren't modified. To do that,
|
Now let's add a key binding to trigger the `ascii-art:convert` command. Open
|
||||||
we'll first try and get a list of files that have not changed.
|
_keymaps/ascii-art.cson_ and add a key binding linking `ctrl-alt-a` to the
|
||||||
|
`ascii-art:convert` command. When finished, the file will look like this:
|
||||||
All packages are able to use jQuery in their code. In fact, there's [a list of
|
|
||||||
the bundled libraries Atom provides by default][bundled-libs].
|
|
||||||
|
|
||||||
We bring in jQuery by requiring the `atom` package and binding it to the `$` variable:
|
|
||||||
|
|
||||||
```coffeescript
|
```coffeescript
|
||||||
{$, View} = require 'atom'
|
'.editor':
|
||||||
|
'cmd-alt-a': 'ascii-art:convert'
|
||||||
```
|
```
|
||||||
|
|
||||||
Now, we can define the `magic` method to query the tree to get us a list of every
|
Notice `.editor` on the first line. Just like CSS, keymap selectors *scope* key
|
||||||
file that _wasn't_ modified:
|
bindings so they only apply to specific elements. In this case, our binding is
|
||||||
|
only active for elements matching the `.editor` selector. If the Tree View has
|
||||||
|
focus, pressing `cmd-alt-a` won't trigger the `ascii-art:convert` command. But
|
||||||
|
if the editor has focus, the `ascii-art:convert` method *will* be triggered.
|
||||||
|
More information on key bindings can be found in the
|
||||||
|
[keymaps](advanced/keymaps.html) documentation.
|
||||||
|
|
||||||
|
Now reload the window and verify that the key binding works! You can also verify
|
||||||
|
that it **doesn't** work when the Tree View is focused.
|
||||||
|
|
||||||
|
## Add the ASCII Art
|
||||||
|
|
||||||
|
Now we need to convert the selected text to ascii art. To do this we will use
|
||||||
|
the [figlet](https://npmjs.org/package/figlet) [node](http://nodejs.org/) module
|
||||||
|
from [npm](https://npmjs.org/). Open _package.json_ and add the latest version of
|
||||||
|
figlet to the dependencies:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"dependencies": {
|
||||||
|
"figlet": "1.0.8"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
After saving the file run the command 'update-package-dependencies:update' from
|
||||||
|
the Command Palette. This will install the packages node module dependencies,
|
||||||
|
only figlet in this case. You will need to run
|
||||||
|
'update-package-dependencies:update' whenever you update the dependencies field
|
||||||
|
in your _package.json_ file.
|
||||||
|
|
||||||
|
Now require the figlet node module in _lib/ascii-art.coffee_ and instead of
|
||||||
|
inserting 'Hello, World!' convert the selected text to ascii art!
|
||||||
|
|
||||||
```coffeescript
|
```coffeescript
|
||||||
magic: ->
|
convert: ->
|
||||||
$('ol.entries li').each (i, el) ->
|
# This assumes the active pane item is an editor
|
||||||
if !$(el).hasClass("status-modified")
|
editor = atom.workspace.activePaneItem
|
||||||
console.log el
|
selection = editor.getSelection()
|
||||||
|
|
||||||
|
figlet = require 'figlet'
|
||||||
|
figlet selection.getText(), {font: "Larry 3D 2"}, (error, asciiArt) ->
|
||||||
|
if error
|
||||||
|
console.error(error)
|
||||||
|
else
|
||||||
|
selection.insertText("\n#{asciiArt}\n")
|
||||||
```
|
```
|
||||||
|
|
||||||
You can access the dev console by hitting `alt-cmd-i`. Here, you'll see all the
|
|
||||||
statements from `console` calls. When we execute the `changer:magic` command, the
|
|
||||||
browser console lists items that are not being modified (_i.e._, those without the
|
|
||||||
`status-modified` class). Let's add a class to each of these elements called `hide-me`:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
magic: ->
|
|
||||||
$('ol.entries li').each (i, el) ->
|
|
||||||
if !$(el).hasClass("status-modified")
|
|
||||||
$(el).addClass("hide-me")
|
|
||||||
```
|
|
||||||
|
|
||||||
With our newly added class, we can manipulate the visibility of the elements
|
|
||||||
with a simple stylesheet. Open up _changer.css_ in the _stylesheets_ directory,
|
|
||||||
and add a single entry:
|
|
||||||
|
|
||||||
```css
|
|
||||||
ol.entries .hide-me {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Refresh Atom, and run the `changer` command. You'll see all the non-changed
|
|
||||||
files disappear from the tree. Success!
|
|
||||||
|
|
||||||
![Changer_File_View]
|
|
||||||
|
|
||||||
There are a number of ways you can get the list back; let's just naively iterate
|
|
||||||
over the same elements and remove the class:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
magic: ->
|
|
||||||
$('ol.entries li').each (i, el) ->
|
|
||||||
if !$(el).hasClass("status-modified")
|
|
||||||
if !$(el).hasClass("hide-me")
|
|
||||||
$(el).addClass("hide-me")
|
|
||||||
else
|
|
||||||
$(el).removeClass("hide-me")
|
|
||||||
```
|
|
||||||
|
|
||||||
## Creating a New Panel
|
|
||||||
|
|
||||||
The next goal of this package is to append a panel to the Atom editor that lists
|
|
||||||
some information about the modified files.
|
|
||||||
|
|
||||||
To do that, we're going to first open up [the style guide][styleguide]. The Style
|
|
||||||
Guide lists every type of UI element that can be created by an Atom package. Aside
|
|
||||||
from helping you avoid writing fresh code from scratch, it ensures that packages
|
|
||||||
have the same look and feel no matter how they're built.
|
|
||||||
|
|
||||||
Every package that extends from the `View` class can provide an optional class
|
|
||||||
method called `content`. The `content` method constructs the DOM that your
|
|
||||||
package uses as its UI. The principals of `content` are built entirely on
|
|
||||||
[SpacePen][space-pen], which we'll touch upon only briefly here.
|
|
||||||
|
|
||||||
Our display will simply be an unordered list of the file names, and their
|
|
||||||
modified times. We'll append this list to a panel on the bottom of the editor. A
|
|
||||||
basic `panel` element inside a `tool-panel` will work well for us. Let's start by carving out a
|
|
||||||
`div` to hold the filenames:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
@content: ->
|
|
||||||
@div class: "changer tool-panel panel-bottom", =>
|
|
||||||
@div class: "panel", =>
|
|
||||||
@div class: "panel-heading", "Modified Files"
|
|
||||||
@div class: "panel-body padded", outlet: 'modifiedFilesContainer', =>
|
|
||||||
@ul class: 'modified-files-list', outlet: 'modifiedFilesList', =>
|
|
||||||
@li 'Modified File Test'
|
|
||||||
@li 'Modified File Test'
|
|
||||||
```
|
|
||||||
|
|
||||||
You can add any HTML attribute you like. `outlet` names the variable your
|
|
||||||
package can use to manipulate the element directly. The fat arrow (`=>`)
|
|
||||||
indicates that the next DOM set are nested children.
|
|
||||||
|
|
||||||
Once again, you can style `li` elements using your stylesheets. Let's test that
|
|
||||||
out by adding these lines to the _changer.css_ file:
|
|
||||||
|
|
||||||
```css
|
|
||||||
ul.modified-files-list {
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
We'll add one more line to the end of the `magic` method to make this pane
|
|
||||||
appear:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
atom.workspaceView.prependToBottom(this)
|
|
||||||
```
|
|
||||||
|
|
||||||
If you refresh Atom and hit the key command, you'll see a box appear right
|
|
||||||
underneath the editor:
|
|
||||||
|
|
||||||
![Changer_Panel_Append]
|
|
||||||
|
|
||||||
As you might have guessed, `atom.workspaceView.prependToBottom` tells Atom to
|
|
||||||
prepend `this` item (_i.e._, whatever is defined by`@content`). If we had called
|
|
||||||
`atom.workspaceView.appendToBottom`, the pane would be attached below the status
|
|
||||||
bar.
|
|
||||||
|
|
||||||
Before we populate this panel for real, let's apply some logic to toggle the
|
|
||||||
pane off and on, just like we did with the tree view. Replace the
|
|
||||||
`atom.workspaceView.prependToBottom` call with this code:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
# toggles the pane
|
|
||||||
if @hasParent()
|
|
||||||
@remove()
|
|
||||||
else
|
|
||||||
atom.workspaceView.prependToBottom(this)
|
|
||||||
```
|
|
||||||
|
|
||||||
There are about a hundred different ways to toggle a pane on and off, and this
|
|
||||||
might not be the most efficient one. If you know your package needs to be
|
|
||||||
toggled on and off more freely, it might be better to draw the interface during the
|
|
||||||
initialization, then immediately call `hide()` on the element to remove it from
|
|
||||||
the view. You can then swap between `show()` and `hide()`, and instead of
|
|
||||||
forcing Atom to add and remove the element as we're doing here, it'll just set a
|
|
||||||
CSS property to control your package's visibility.
|
|
||||||
|
|
||||||
Refresh Atom, hit the key combo, and watch your test list appear and disappear.
|
|
||||||
|
|
||||||
## Calling Node.js Code
|
|
||||||
|
|
||||||
Since Atom is built on top of [Node.js][node], you can call any of its libraries,
|
|
||||||
including other modules that your package requires.
|
|
||||||
|
|
||||||
We'll iterate through our resulting tree, and construct the path to our modified
|
|
||||||
file based on its depth in the tree. We'll use Node to handle path joining for
|
|
||||||
directories.
|
|
||||||
|
|
||||||
Add the following Node module to the top of your file:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
path = require 'path'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, add these lines to your `magic` method, _before_ your pane drawing code:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
modifiedFiles = []
|
|
||||||
# for each single entry...
|
|
||||||
$('ol.entries li.file.status-modified span.name').each (i, el) ->
|
|
||||||
filePath = []
|
|
||||||
# ...grab its name...
|
|
||||||
filePath.unshift($(el).text())
|
|
||||||
|
|
||||||
# ... then find its parent directories, and grab their names
|
|
||||||
parents = $(el).parents('.directory.status-modified')
|
|
||||||
parents.each (i, el) ->
|
|
||||||
filePath.unshift($(el).find('div.header span.name').eq(0).text())
|
|
||||||
|
|
||||||
modifiedFilePath = path.join(atom.project.rootDirectory.path, filePath.join(path.sep))
|
|
||||||
modifiedFiles.push modifiedFilePath
|
|
||||||
```
|
|
||||||
|
|
||||||
`modifiedFiles` is an array containing a list of our modified files. We're also
|
|
||||||
using the node.js [`path` library][path] to get the proper directory separator
|
|
||||||
for our system.
|
|
||||||
|
|
||||||
Remove the two `@li` elements we added in `@content`, so that we can
|
|
||||||
populate our `modifiedFilesList` with real information. We'll do that by
|
|
||||||
iterating over `modifiedFiles`, accessing a file's last modified time, and
|
|
||||||
appending it to `modifiedFilesList`:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
# toggles the pane
|
|
||||||
if @hasParent()
|
|
||||||
@remove()
|
|
||||||
else
|
|
||||||
for file in modifiedFiles
|
|
||||||
stat = fs.lstatSync(file)
|
|
||||||
mtime = stat.mtime
|
|
||||||
@modifiedFilesList.append("<li>#{file} - Modified at #{mtime}")
|
|
||||||
atom.workspaceView.prependToBottom(this)
|
|
||||||
```
|
|
||||||
|
|
||||||
When you toggle the modified files list, your pane is now populated with the
|
|
||||||
filenames and modified times of files in your project:
|
|
||||||
|
|
||||||
![Changer_Panel_Timestamps]
|
|
||||||
|
|
||||||
You might notice that subsequent calls to this command reduplicate information.
|
|
||||||
We could provide an elegant way of rechecking files already in the list, but for
|
|
||||||
this demonstration, we'll just clear the `modifiedFilesList` each time it's closed:
|
|
||||||
|
|
||||||
```coffeescript
|
|
||||||
# toggles the pane
|
|
||||||
if @hasParent()
|
|
||||||
@modifiedFilesList.empty() # added this to clear the list on close
|
|
||||||
@remove()
|
|
||||||
else
|
|
||||||
for file in modifiedFiles
|
|
||||||
stat = fs.lstatSync(file)
|
|
||||||
mtime = stat.mtime
|
|
||||||
@modifiedFilesList.append("<li>#{file} - Modified at #{mtime}")
|
|
||||||
atom.workspaceView.prependToBottom(this)
|
|
||||||
```
|
|
||||||
|
|
||||||
## Coloring UI Elements
|
|
||||||
|
|
||||||
For packages that create new UI elements, adhering to the style guide is just one
|
|
||||||
part to keeping visual consistency. Packages dealing with color, fonts, padding,
|
|
||||||
margins, and other visual cues should rely on [Theme Variables][theme-vars], instead
|
|
||||||
of developing individual styles. Theme variables are variables defined by Atom
|
|
||||||
for use in packages and themes. They're only available in [`LESS`](http://lesscss.org/)
|
|
||||||
stylesheets.
|
|
||||||
|
|
||||||
For our package, let's remove the style defined by `ul.modified-files-list` in
|
|
||||||
_changer.css_. Create a new file under the _stylesheets_ directory called _text-colors.less_.
|
|
||||||
Here, we'll import the _ui-variables.less_ file, and define some Atom-specific
|
|
||||||
styles:
|
|
||||||
|
|
||||||
```less
|
|
||||||
@import "ui-variables";
|
|
||||||
|
|
||||||
ul.modified-files-list {
|
|
||||||
color: @text-color;
|
|
||||||
background-color: @background-color-info;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Using theme variables ensures that packages look great alongside any theme.
|
|
||||||
|
|
||||||
## Further reading
|
## Further reading
|
||||||
|
|
||||||
For more information on the mechanics of packages, check out
|
For more information on the mechanics of packages, check out [Creating a
|
||||||
[Creating a Package][creating-a-package].
|
Package](creating-a-package.html)
|
||||||
|
|
||||||
[bundled-libs]: creating-a-package.html#included-libraries
|
|
||||||
[styleguide]: https://github.com/atom/styleguide
|
|
||||||
[space-pen]: https://github.com/atom/space-pen
|
|
||||||
[node]: http://nodejs.org/
|
|
||||||
[path]: http://nodejs.org/docs/latest/api/path.html
|
|
||||||
[changer_file_view]: https://f.cloud.github.com/assets/69169/1441187/d7a7cb46-41a7-11e3-8128-d93f70a5d5c1.png
|
|
||||||
[changer_panel_append]: https://f.cloud.github.com/assets/69169/1441189/db0c74da-41a7-11e3-8286-b82dd9190c34.png
|
|
||||||
[changer_panel_timestamps]: https://f.cloud.github.com/assets/69169/1441190/dcc8eeb6-41a7-11e3-830f-1f1b33072fcd.png
|
|
||||||
[theme-vars]: theme-variables.html
|
|
||||||
[creating-a-package]: creating-a-package.html
|
|
||||||
|
15
dot-atom/snippets.cson
Normal file
15
dot-atom/snippets.cson
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Your snippets
|
||||||
|
#
|
||||||
|
# Atom snippets allow you to enter a simple prefix in the editor and hit tab to
|
||||||
|
# expand the prefix into a larger code block with templated values.
|
||||||
|
#
|
||||||
|
# You can create a new snippet in this file by typing `snip` and then hitting
|
||||||
|
# tab.
|
||||||
|
#
|
||||||
|
# An example CoffeeScript snippet to expand log to console.log:
|
||||||
|
#
|
||||||
|
# '.source.coffee':
|
||||||
|
# 'Console log':
|
||||||
|
# 'prefix': 'log'
|
||||||
|
# 'body': 'console.log $1'
|
||||||
|
#
|
@ -1,44 +0,0 @@
|
|||||||
".source.coffee":
|
|
||||||
"Describe block":
|
|
||||||
prefix: "de"
|
|
||||||
body: """
|
|
||||||
describe "${1:description}", ->
|
|
||||||
${2:body}
|
|
||||||
"""
|
|
||||||
"It block":
|
|
||||||
prefix: "i"
|
|
||||||
body: """
|
|
||||||
it "$1", ->
|
|
||||||
$2
|
|
||||||
"""
|
|
||||||
"Before each":
|
|
||||||
prefix: "be"
|
|
||||||
body: """
|
|
||||||
beforeEach ->
|
|
||||||
$1
|
|
||||||
"""
|
|
||||||
"After each":
|
|
||||||
prefix: "af"
|
|
||||||
body: """
|
|
||||||
afterEach ->
|
|
||||||
$1
|
|
||||||
"""
|
|
||||||
"Expectation":
|
|
||||||
prefix: "ex"
|
|
||||||
body: "expect($1).to$2"
|
|
||||||
"Console log":
|
|
||||||
prefix: "log"
|
|
||||||
body: "console.log $1"
|
|
||||||
"Range array":
|
|
||||||
prefix: "ra"
|
|
||||||
body: "[[$1, $2], [$3, $4]]"
|
|
||||||
"Point array":
|
|
||||||
prefix: "pt"
|
|
||||||
body: "[$1, $2]"
|
|
||||||
|
|
||||||
"Key-value pair":
|
|
||||||
prefix: ":"
|
|
||||||
body: '${1:"${2:key}"}: ${3:value}'
|
|
||||||
"Create Jasmine spy":
|
|
||||||
prefix: "spy"
|
|
||||||
body: 'jasmine.createSpy("${1:description}")$2'
|
|
@ -8,6 +8,7 @@ module.exports =
|
|||||||
File: require '../src/file'
|
File: require '../src/file'
|
||||||
fs: require 'fs-plus'
|
fs: require 'fs-plus'
|
||||||
Git: require '../src/git'
|
Git: require '../src/git'
|
||||||
|
ConfigObserver: require '../src/config-observer'
|
||||||
Point: Point
|
Point: Point
|
||||||
Range: Range
|
Range: Range
|
||||||
|
|
||||||
|
@ -24,9 +24,6 @@
|
|||||||
'ctrl-shift-up': 'editor:add-selection-above'
|
'ctrl-shift-up': 'editor:add-selection-above'
|
||||||
'ctrl-shift-down': 'editor:add-selection-below'
|
'ctrl-shift-down': 'editor:add-selection-below'
|
||||||
|
|
||||||
'.tool-panel':
|
|
||||||
'escape': 'core:close'
|
|
||||||
|
|
||||||
'.tool-panel.panel-left, .tool-panel.panel-right':
|
'.tool-panel.panel-left, .tool-panel.panel-right':
|
||||||
'escape': 'tool-panel:unfocus'
|
'escape': 'tool-panel:unfocus'
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
'.platform-darwin':
|
'body':
|
||||||
# Apple specific
|
# Apple specific
|
||||||
'cmd-q': 'application:quit'
|
'cmd-q': 'application:quit'
|
||||||
'cmd-h': 'application:hide'
|
'cmd-h': 'application:hide'
|
||||||
@ -87,7 +87,7 @@
|
|||||||
'cmd-8': 'pane:show-item-8'
|
'cmd-8': 'pane:show-item-8'
|
||||||
'cmd-9': 'pane:show-item-9'
|
'cmd-9': 'pane:show-item-9'
|
||||||
|
|
||||||
'.platform-darwin .editor':
|
'.editor':
|
||||||
# Apple Specific
|
# Apple Specific
|
||||||
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
|
'cmd-backspace': 'editor:backspace-to-beginning-of-line'
|
||||||
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
'cmd-delete': 'editor:backspace-to-beginning-of-line'
|
||||||
@ -113,7 +113,7 @@
|
|||||||
'cmd-k cmd-l': 'editor:lower-case'
|
'cmd-k cmd-l': 'editor:lower-case'
|
||||||
'cmd-l': 'editor:select-line'
|
'cmd-l': 'editor:select-line'
|
||||||
|
|
||||||
'body.platform-darwin .editor:not(.mini)':
|
'.workspace .editor:not(.mini)':
|
||||||
# Atom specific
|
# Atom specific
|
||||||
'alt-cmd-z': 'editor:checkout-head-revision'
|
'alt-cmd-z': 'editor:checkout-head-revision'
|
||||||
'cmd-<': 'editor:scroll-to-cursor'
|
'cmd-<': 'editor:scroll-to-cursor'
|
||||||
@ -148,7 +148,7 @@
|
|||||||
'cmd-k cmd-9': 'editor:fold-at-indent-level-9'
|
'cmd-k cmd-9': 'editor:fold-at-indent-level-9'
|
||||||
|
|
||||||
# allow standard input fields to work correctly
|
# allow standard input fields to work correctly
|
||||||
'body.platform-darwin .native-key-bindings':
|
'body .native-key-bindings':
|
||||||
'cmd-z': 'native!'
|
'cmd-z': 'native!'
|
||||||
'cmd-Z': 'native!'
|
'cmd-Z': 'native!'
|
||||||
'cmd-x': 'native!'
|
'cmd-x': 'native!'
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
'.platform-win32':
|
'body':
|
||||||
# Atom Specific
|
# Atom Specific
|
||||||
'enter': 'core:confirm'
|
'enter': 'core:confirm'
|
||||||
'escape': 'core:cancel'
|
'escape': 'core:cancel'
|
||||||
@ -50,7 +50,7 @@
|
|||||||
'ctrl-k ctrl-left': 'window:focus-previous-pane'
|
'ctrl-k ctrl-left': 'window:focus-previous-pane'
|
||||||
'ctrl-k ctrl-right': 'window:focus-next-pane'
|
'ctrl-k ctrl-right': 'window:focus-next-pane'
|
||||||
|
|
||||||
'.platform-win32 .editor':
|
'.workspace .editor':
|
||||||
# Windows specific
|
# Windows specific
|
||||||
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
'ctrl-delete': 'editor:backspace-to-beginning-of-word'
|
||||||
|
|
||||||
@ -60,7 +60,7 @@
|
|||||||
'ctrl-k ctrl-u': 'editor:upper-case'
|
'ctrl-k ctrl-u': 'editor:upper-case'
|
||||||
'ctrl-k ctrl-l': 'editor:lower-case'
|
'ctrl-k ctrl-l': 'editor:lower-case'
|
||||||
|
|
||||||
'.platform-win32 .editor:not(.mini)':
|
'.workspace .editor:not(.mini)':
|
||||||
# Atom specific
|
# Atom specific
|
||||||
'alt-ctrl-z': 'editor:checkout-head-revision'
|
'alt-ctrl-z': 'editor:checkout-head-revision'
|
||||||
'ctrl-<': 'editor:scroll-to-cursor'
|
'ctrl-<': 'editor:scroll-to-cursor'
|
||||||
@ -94,7 +94,7 @@
|
|||||||
'ctrl-k ctrl-9': 'editor:fold-at-indent-level-9'
|
'ctrl-k ctrl-9': 'editor:fold-at-indent-level-9'
|
||||||
|
|
||||||
# allow standard input fields to work correctly
|
# allow standard input fields to work correctly
|
||||||
'.platform-win32 input:not(.hidden-input), .platform-win32 .native-key-bindings':
|
'body .native-key-bindings':
|
||||||
'ctrl-z': 'native!'
|
'ctrl-z': 'native!'
|
||||||
'ctrl-Z': 'native!'
|
'ctrl-Z': 'native!'
|
||||||
'ctrl-x': 'native!'
|
'ctrl-x': 'native!'
|
||||||
|
@ -9,8 +9,11 @@
|
|||||||
{ label: 'Preferences...', command: 'application:show-settings' }
|
{ label: 'Preferences...', command: 'application:show-settings' }
|
||||||
{ label: 'Open Your Config', command: 'application:open-your-config' }
|
{ label: 'Open Your Config', command: 'application:open-your-config' }
|
||||||
{ label: 'Open Your Keymap', command: 'application:open-your-keymap' }
|
{ label: 'Open Your Keymap', command: 'application:open-your-keymap' }
|
||||||
|
{ label: 'Open Your Snippets', command: 'application:open-your-snippets' }
|
||||||
{ label: 'Open Your Stylesheet', command: 'application:open-your-stylesheet' }
|
{ label: 'Open Your Stylesheet', command: 'application:open-your-stylesheet' }
|
||||||
{ type: 'separator' }
|
{ type: 'separator' }
|
||||||
|
{ label: 'Install Shell Commands', command: 'window:install-shell-commands' }
|
||||||
|
{ type: 'separator' }
|
||||||
{ label: 'Hide Atom', command: 'application:hide' }
|
{ label: 'Hide Atom', command: 'application:hide' }
|
||||||
{ label: 'Hide Others', command: 'application:hide-other-applications' }
|
{ label: 'Hide Others', command: 'application:hide-other-applications' }
|
||||||
{ label: 'Show All', command: 'application:unhide-all-applications' }
|
{ label: 'Show All', command: 'application:unhide-all-applications' }
|
||||||
|
23
package.json
23
package.json
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "atom",
|
"name": "atom",
|
||||||
"productName": "Atom",
|
"productName": "Atom",
|
||||||
"version": "0.48.0",
|
"version": "0.49.0",
|
||||||
"main": "./src/browser/main.js",
|
"main": "./src/browser/main.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -16,7 +16,7 @@
|
|||||||
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"atomShellVersion": "0.8.5",
|
"atomShellVersion": "0.8.7",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": "0.2.6",
|
"async": "0.2.6",
|
||||||
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
"bootstrap": "git://github.com/atom/bootstrap.git#6af81906189f1747fd6c93479e3d998ebe041372",
|
||||||
@ -28,15 +28,15 @@
|
|||||||
"first-mate": "1.x",
|
"first-mate": "1.x",
|
||||||
"fs-plus": "1.x",
|
"fs-plus": "1.x",
|
||||||
"fstream": "0.1.24",
|
"fstream": "0.1.24",
|
||||||
"fuzzaldrin": "0.6.0",
|
"fuzzaldrin": "0.7.0",
|
||||||
"git-utils": "0.33.1",
|
"git-utils": "0.34.0",
|
||||||
"guid": "0.0.10",
|
"guid": "0.0.10",
|
||||||
"jasmine-tagged": "0.3.0",
|
"jasmine-tagged": "0.3.0",
|
||||||
"mkdirp": "0.3.5",
|
"mkdirp": "0.3.5",
|
||||||
"keytar": "0.15.1",
|
"keytar": "0.15.1",
|
||||||
"less-cache": "0.11.0",
|
"less-cache": "0.11.0",
|
||||||
"mixto": "1.x",
|
"mixto": "1.x",
|
||||||
"nslog": "0.3.0",
|
"nslog": "0.4.0",
|
||||||
"oniguruma": "1.x",
|
"oniguruma": "1.x",
|
||||||
"optimist": "0.4.0",
|
"optimist": "0.4.0",
|
||||||
"pathwatcher": "0.14.2",
|
"pathwatcher": "0.14.2",
|
||||||
@ -75,7 +75,7 @@
|
|||||||
"editor-stats": "0.12.0",
|
"editor-stats": "0.12.0",
|
||||||
"exception-reporting": "0.12.0",
|
"exception-reporting": "0.12.0",
|
||||||
"feedback": "0.22.0",
|
"feedback": "0.22.0",
|
||||||
"find-and-replace": "0.79.0",
|
"find-and-replace": "0.80.0",
|
||||||
"fuzzy-finder": "0.31.0",
|
"fuzzy-finder": "0.31.0",
|
||||||
"gists": "0.15.0",
|
"gists": "0.15.0",
|
||||||
"git-diff": "0.23.0",
|
"git-diff": "0.23.0",
|
||||||
@ -86,27 +86,28 @@
|
|||||||
"keybinding-resolver": "0.9.0",
|
"keybinding-resolver": "0.9.0",
|
||||||
"link": "0.15.0",
|
"link": "0.15.0",
|
||||||
"markdown-preview": "0.25.1",
|
"markdown-preview": "0.25.1",
|
||||||
"metrics": "0.21.0",
|
"metrics": "0.24.0",
|
||||||
"package-generator": "0.24.0",
|
"package-generator": "0.24.0",
|
||||||
"release-notes": "0.17.0",
|
"release-notes": "0.17.0",
|
||||||
"settings-view": "0.57.0",
|
"settings-view": "0.57.0",
|
||||||
"snippets": "0.20.0",
|
"snippets": "0.22.0",
|
||||||
"spell-check": "0.20.0",
|
"spell-check": "0.20.0",
|
||||||
"status-bar": "0.32.0",
|
"status-bar": "0.32.0",
|
||||||
"styleguide": "0.21.0",
|
"styleguide": "0.21.0",
|
||||||
"symbols-view": "0.29.0",
|
"symbols-view": "0.29.0",
|
||||||
"tabs": "0.18.0",
|
"tabs": "0.18.0",
|
||||||
"terminal": "0.26.0",
|
"terminal": "0.27.0",
|
||||||
"timecop": "0.13.0",
|
"timecop": "0.13.0",
|
||||||
"to-the-hubs": "0.17.0",
|
"to-the-hubs": "0.18.0",
|
||||||
"tree-view": "0.65.0",
|
"tree-view": "0.65.0",
|
||||||
|
"update-package-dependencies": "0.2.0",
|
||||||
"visual-bell": "0.6.0",
|
"visual-bell": "0.6.0",
|
||||||
"welcome": "0.4.0",
|
"welcome": "0.4.0",
|
||||||
"whitespace": "0.10.0",
|
"whitespace": "0.10.0",
|
||||||
"wrap-guide": "0.12.0",
|
"wrap-guide": "0.12.0",
|
||||||
"language-c": "0.2.0",
|
"language-c": "0.2.0",
|
||||||
"language-clojure": "0.1.0",
|
"language-clojure": "0.1.0",
|
||||||
"language-coffee-script": "0.4.0",
|
"language-coffee-script": "0.6.0",
|
||||||
"language-css": "0.2.0",
|
"language-css": "0.2.0",
|
||||||
"language-gfm": "0.12.0",
|
"language-gfm": "0.12.0",
|
||||||
"language-git": "0.3.0",
|
"language-git": "0.3.0",
|
||||||
|
18
script/copy-folder.cmd
Normal file
18
script/copy-folder.cmd
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set USAGE=Usage: %0 source destination
|
||||||
|
|
||||||
|
if [%1] == [] (
|
||||||
|
echo %USAGE%
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
if [%2] == [] (
|
||||||
|
echo %USAGE%
|
||||||
|
exit 2
|
||||||
|
)
|
||||||
|
|
||||||
|
:: rm -rf %2
|
||||||
|
if exist %2 rmdir %2 /s /q
|
||||||
|
|
||||||
|
:: cp -rf %1 %2
|
||||||
|
xcopy %1 %2 /e /h /c /i /y /r
|
23
script/create-shortcut.cmd
Normal file
23
script/create-shortcut.cmd
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set USAGE=Usage: %0 source name-on-desktop
|
||||||
|
|
||||||
|
if [%1] == [] (
|
||||||
|
echo %USAGE%
|
||||||
|
exit 1
|
||||||
|
)
|
||||||
|
if [%2] == [] (
|
||||||
|
echo %USAGE%
|
||||||
|
exit 2
|
||||||
|
)
|
||||||
|
|
||||||
|
set SCRIPT="%TEMP%\%RANDOM%-%RANDOM%-%RANDOM%-%RANDOM%.vbs"
|
||||||
|
|
||||||
|
echo Set oWS = WScript.CreateObject("WScript.Shell") >> %SCRIPT%
|
||||||
|
echo sLinkFile = "%USERPROFILE%\Desktop\%2.lnk" >> %SCRIPT%
|
||||||
|
echo Set oLink = oWS.CreateShortcut(sLinkFile) >> %SCRIPT%
|
||||||
|
echo oLink.TargetPath = %1 >> %SCRIPT%
|
||||||
|
echo oLink.Save >> %SCRIPT%
|
||||||
|
|
||||||
|
cscript /nologo %SCRIPT%
|
||||||
|
del %SCRIPT%
|
@ -2,8 +2,8 @@
|
|||||||
var cp = require('./utils/child-process-wrapper.js');
|
var cp = require('./utils/child-process-wrapper.js');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
|
||||||
// node build/node_modules/grunt-cli/bin/grunt "$@"
|
// node build/node_modules/.bin/grunt "$@"
|
||||||
var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', 'grunt-cli', 'bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
var gruntPath = path.resolve(__dirname, '..', 'build', 'node_modules', '.bin', 'grunt') + (process.platform === 'win32' ? '.cmd' : '');
|
||||||
var args = [gruntPath, '--gruntfile', path.resolve('build', 'Gruntfile.coffee')];
|
var args = ['--gruntfile', path.resolve('build', 'Gruntfile.coffee')];
|
||||||
args = args.concat(process.argv.slice(2));
|
args = args.concat(process.argv.slice(2));
|
||||||
cp.safeSpawn(process.execPath, args, process.exit);
|
cp.safeSpawn(gruntPath, args, process.exit);
|
||||||
|
@ -3,9 +3,8 @@
|
|||||||
path = require 'path'
|
path = require 'path'
|
||||||
CommandInstaller = require '../src/command-installer'
|
CommandInstaller = require '../src/command-installer'
|
||||||
|
|
||||||
callback = (error, sourcePath, destinationPath) ->
|
callback = (error) ->
|
||||||
unless error?
|
console.warn error.message if error?
|
||||||
console.log "#{sourcePath} intalled to #{destinationPath}"
|
|
||||||
|
|
||||||
CommandInstaller.installAtomCommand(path.resolve(__dirname, '..'), callback)
|
CommandInstaller.installAtomCommand(path.resolve(__dirname, '..'), callback)
|
||||||
CommandInstaller.installApmCommand(path.resolve(__dirname, '..'), callback)
|
CommandInstaller.installApmCommand(path.resolve(__dirname, '..'), callback)
|
||||||
|
@ -24,7 +24,7 @@ fs.createReadStream(fontSrc).pipe(fs.createWriteStream(fontDest))
|
|||||||
|
|
||||||
# Update Octicon UTF codes
|
# Update Octicon UTF codes
|
||||||
glyphsSrc = path.join(pathToOcticons, 'data', 'glyphs.yml')
|
glyphsSrc = path.join(pathToOcticons, 'data', 'glyphs.yml')
|
||||||
octiconUtfDest = path.join atomDir, 'static', 'octicon-utf-codes.less'
|
octiconUtfDest = path.join atomDir, 'static', 'variables', 'octicon-utf-codes.less'
|
||||||
output = []
|
output = []
|
||||||
for {css, code} in YAML.load(fs.readFileSync(glyphsSrc).toString())
|
for {css, code} in YAML.load(fs.readFileSync(glyphsSrc).toString())
|
||||||
output.push "@#{css}: \"\\#{code}\";"
|
output.push "@#{css}: \"\\#{code}\";"
|
||||||
|
@ -4,33 +4,31 @@ temp = require 'temp'
|
|||||||
installer = require '../src/command-installer'
|
installer = require '../src/command-installer'
|
||||||
|
|
||||||
describe "install(commandPath, callback)", ->
|
describe "install(commandPath, callback)", ->
|
||||||
directory = path.join(temp.dir, 'install-atom-command', 'atom')
|
commandFilePath = temp.openSync("atom-command").path
|
||||||
commandPath = path.join(directory, 'source')
|
commandName = path.basename(commandFilePath)
|
||||||
destinationPath = path.join(directory, 'bin', 'source')
|
installationPath = temp.mkdirSync("atom-bin")
|
||||||
|
installationFilePath = path.join(installationPath, commandName)
|
||||||
|
|
||||||
beforeEach ->
|
beforeEach ->
|
||||||
spyOn(installer, 'findInstallDirectory').andCallFake (callback) ->
|
spyOn(installer, 'getInstallDirectory').andReturn installationPath
|
||||||
callback(directory)
|
|
||||||
|
|
||||||
fs.removeSync(directory) if fs.existsSync(directory)
|
|
||||||
|
|
||||||
describe "on #darwin", ->
|
describe "on #darwin", ->
|
||||||
it "symlinks the command and makes it executable", ->
|
it "symlinks the command and makes it executable", ->
|
||||||
fs.writeFileSync(commandPath, 'test')
|
expect(fs.isFileSync(commandFilePath)).toBeTruthy()
|
||||||
expect(fs.isFileSync(commandPath)).toBeTruthy()
|
expect(fs.isExecutableSync(commandFilePath)).toBeFalsy()
|
||||||
expect(fs.isExecutableSync(commandPath)).toBeFalsy()
|
expect(fs.isFileSync(installationFilePath)).toBeFalsy()
|
||||||
expect(fs.isFileSync(destinationPath)).toBeFalsy()
|
|
||||||
|
|
||||||
installDone = false
|
installDone = false
|
||||||
installError = null
|
installError = null
|
||||||
installer.install commandPath, (error) ->
|
installer.install commandFilePath, (error) ->
|
||||||
installDone = true
|
installDone = true
|
||||||
installError = error
|
installError = error
|
||||||
|
|
||||||
waitsFor -> installDone
|
waitsFor ->
|
||||||
|
installDone
|
||||||
|
|
||||||
runs ->
|
runs ->
|
||||||
expect(installError).toBeNull()
|
expect(installError).toBeNull()
|
||||||
expect(fs.isFileSync(destinationPath)).toBeTruthy()
|
expect(fs.isFileSync(installationFilePath)).toBeTruthy()
|
||||||
expect(fs.realpathSync(destinationPath)).toBe fs.realpathSync(commandPath)
|
expect(fs.realpathSync(installationFilePath)).toBe fs.realpathSync(commandFilePath)
|
||||||
expect(fs.isExecutableSync(destinationPath)).toBeTruthy()
|
expect(fs.isExecutableSync(installationFilePath)).toBeTruthy()
|
||||||
|
@ -218,7 +218,7 @@ describe "Config", ->
|
|||||||
runs ->
|
runs ->
|
||||||
expect(fs.existsSync(atom.config.configDirPath)).toBeTruthy()
|
expect(fs.existsSync(atom.config.configDirPath)).toBeTruthy()
|
||||||
expect(fs.existsSync(path.join(atom.config.configDirPath, 'packages'))).toBeTruthy()
|
expect(fs.existsSync(path.join(atom.config.configDirPath, 'packages'))).toBeTruthy()
|
||||||
expect(fs.existsSync(path.join(atom.config.configDirPath, 'snippets'))).toBeTruthy()
|
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'snippets.cson'))).toBeTruthy()
|
||||||
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'config.cson'))).toBeTruthy()
|
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'config.cson'))).toBeTruthy()
|
||||||
|
|
||||||
describe ".loadUserConfig()", ->
|
describe ".loadUserConfig()", ->
|
||||||
|
@ -63,7 +63,7 @@ describe 'File', ->
|
|||||||
afterEach ->
|
afterEach ->
|
||||||
if fs.existsSync(newPath)
|
if fs.existsSync(newPath)
|
||||||
fs.removeSync(newPath)
|
fs.removeSync(newPath)
|
||||||
waitsFor "remove event", (done) -> file.on 'removed', done
|
waitsFor "remove event", 30000, (done) -> file.on 'removed', done
|
||||||
|
|
||||||
it "it updates its path", ->
|
it "it updates its path", ->
|
||||||
jasmine.unspy(window, "setTimeout")
|
jasmine.unspy(window, "setTimeout")
|
||||||
|
@ -354,6 +354,27 @@ describe "Keymap", ->
|
|||||||
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
bindings = keymap.keyBindingsForCommandMatchingElement('cultivate', el)
|
||||||
expect(bindings).toHaveLength 0
|
expect(bindings).toHaveLength 0
|
||||||
|
|
||||||
|
describe "loading platform specific keybindings", ->
|
||||||
|
customKeymap = null
|
||||||
|
|
||||||
|
beforeEach ->
|
||||||
|
resourcePath = temp.mkdirSync('atom')
|
||||||
|
customKeymap = new Keymap({configDirPath, resourcePath})
|
||||||
|
|
||||||
|
afterEach ->
|
||||||
|
customKeymap.destroy()
|
||||||
|
|
||||||
|
it "doesn't load keybindings from other platforms", ->
|
||||||
|
win32FilePath = path.join(resourcePath, "keymaps", "win32.cson")
|
||||||
|
darwinFilePath = path.join(resourcePath, "keymaps", "darwin.cson")
|
||||||
|
fs.writeFileSync(win32FilePath, '"body": "ctrl-l": "core:win32-move-left"')
|
||||||
|
fs.writeFileSync(darwinFilePath, '"body": "ctrl-l": "core:darwin-move-left"')
|
||||||
|
|
||||||
|
customKeymap.loadBundledKeymaps()
|
||||||
|
keyBindings = customKeymap.keyBindingsForKeystroke('ctrl-l')
|
||||||
|
expect(keyBindings).toHaveLength 1
|
||||||
|
expect(keyBindings[0].command).toBe "core:#{process.platform}-move-left"
|
||||||
|
|
||||||
describe "when the user keymap file is changed", ->
|
describe "when the user keymap file is changed", ->
|
||||||
it "is reloaded", ->
|
it "is reloaded", ->
|
||||||
keymapFilePath = path.join(configDirPath, "keymap.cson")
|
keymapFilePath = path.join(configDirPath, "keymap.cson")
|
||||||
|
@ -34,7 +34,7 @@ WindowEventHandler = require './window-event-handler'
|
|||||||
# * `atom.themes` - A {ThemeManager} instance
|
# * `atom.themes` - A {ThemeManager} instance
|
||||||
module.exports =
|
module.exports =
|
||||||
class Atom extends Model
|
class Atom extends Model
|
||||||
# Public: Load or create the Atom environment in the given mode
|
# Public: Load or create the Atom environment in the given mode.
|
||||||
#
|
#
|
||||||
# - mode: Pass 'editor' or 'spec' depending on the kind of environment you
|
# - mode: Pass 'editor' or 'spec' depending on the kind of environment you
|
||||||
# want to build.
|
# want to build.
|
||||||
@ -249,10 +249,12 @@ class Atom extends Model
|
|||||||
|
|
||||||
# Private: Call this method when establishing a real application window.
|
# Private: Call this method when establishing a real application window.
|
||||||
startEditorWindow: ->
|
startEditorWindow: ->
|
||||||
if process.platform is 'darwin'
|
CommandInstaller = require './command-installer'
|
||||||
CommandInstaller = require './command-installer'
|
resourcePath = atom.getLoadSettings().resourcePath
|
||||||
CommandInstaller.installAtomCommand()
|
CommandInstaller.installAtomCommand resourcePath, (error) ->
|
||||||
CommandInstaller.installApmCommand()
|
console.warn error.message if error?
|
||||||
|
CommandInstaller.installApmCommand resourcePath, (error) ->
|
||||||
|
console.warn error.message if error?
|
||||||
|
|
||||||
@restoreWindowDimensions()
|
@restoreWindowDimensions()
|
||||||
@config.load()
|
@config.load()
|
||||||
|
@ -15,7 +15,11 @@ url = require 'url'
|
|||||||
{EventEmitter} = require 'events'
|
{EventEmitter} = require 'events'
|
||||||
_ = require 'underscore-plus'
|
_ = require 'underscore-plus'
|
||||||
|
|
||||||
socketPath = path.join(os.tmpdir(), 'atom.sock')
|
socketPath =
|
||||||
|
if process.platform is 'win32'
|
||||||
|
'\\\\.\\pipe\\atom-sock'
|
||||||
|
else
|
||||||
|
path.join(os.tmpdir(), 'atom.sock')
|
||||||
|
|
||||||
# Private: The application's singleton class.
|
# Private: The application's singleton class.
|
||||||
#
|
#
|
||||||
@ -35,14 +39,10 @@ class AtomApplication
|
|||||||
# take a few seconds to trigger 'error' event, it could be a bug of node
|
# take a few seconds to trigger 'error' event, it could be a bug of node
|
||||||
# or atom-shell, before it's fixed we check the existence of socketPath to
|
# or atom-shell, before it's fixed we check the existence of socketPath to
|
||||||
# speedup startup.
|
# speedup startup.
|
||||||
if (not fs.existsSync socketPath) or options.test
|
if (process.platform isnt 'win32' and not fs.existsSync socketPath) or options.test
|
||||||
createAtomApplication()
|
createAtomApplication()
|
||||||
return
|
return
|
||||||
|
|
||||||
# The net.connect is slow in atom-shell for now, use this workaround until
|
|
||||||
# atom/atom-shell#159 is fixed.
|
|
||||||
process.activateUvLoop()
|
|
||||||
|
|
||||||
client = net.connect {path: socketPath}, ->
|
client = net.connect {path: socketPath}, ->
|
||||||
client.write JSON.stringify(options), ->
|
client.write JSON.stringify(options), ->
|
||||||
client.end()
|
client.end()
|
||||||
@ -103,7 +103,8 @@ class AtomApplication
|
|||||||
# the other launches will just pass their information to this server and then
|
# the other launches will just pass their information to this server and then
|
||||||
# close immediately.
|
# close immediately.
|
||||||
listenForArgumentsFromNewProcess: ->
|
listenForArgumentsFromNewProcess: ->
|
||||||
fs.unlinkSync socketPath if fs.existsSync(socketPath)
|
if process.platform isnt 'win32' and fs.existsSync(socketPath)
|
||||||
|
fs.unlinkSync socketPath
|
||||||
server = net.createServer (connection) =>
|
server = net.createServer (connection) =>
|
||||||
connection.on 'data', (data) =>
|
connection.on 'data', (data) =>
|
||||||
@openWithOptions(JSON.parse(data))
|
@openWithOptions(JSON.parse(data))
|
||||||
@ -148,15 +149,18 @@ class AtomApplication
|
|||||||
@on 'application:report-issue', -> shell.openExternal('https://github.com/atom/atom/issues/new')
|
@on 'application:report-issue', -> shell.openExternal('https://github.com/atom/atom/issues/new')
|
||||||
|
|
||||||
@openPathOnEvent('application:show-settings', 'atom://config')
|
@openPathOnEvent('application:show-settings', 'atom://config')
|
||||||
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
|
|
||||||
@openPathOnEvent('application:open-your-keymap', 'atom://.atom/keymap')
|
|
||||||
@openPathOnEvent('application:open-your-config', 'atom://.atom/config')
|
@openPathOnEvent('application:open-your-config', 'atom://.atom/config')
|
||||||
|
@openPathOnEvent('application:open-your-keymap', 'atom://.atom/keymap')
|
||||||
|
@openPathOnEvent('application:open-your-snippets', 'atom://.atom/snippets')
|
||||||
|
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
|
||||||
|
|
||||||
app.on 'window-all-closed', ->
|
app.on 'window-all-closed', ->
|
||||||
app.quit() if process.platform is 'win32'
|
app.quit() if process.platform is 'win32'
|
||||||
|
|
||||||
app.on 'will-quit', =>
|
app.on 'will-quit', =>
|
||||||
fs.unlinkSync socketPath if fs.existsSync(socketPath) # Clean the socket file when quit normally.
|
# Clean the socket file when quit normally.
|
||||||
|
if process.platform isnt 'win32' and fs.existsSync(socketPath)
|
||||||
|
fs.unlinkSync socketPath
|
||||||
|
|
||||||
app.on 'open-file', (event, pathToOpen) =>
|
app.on 'open-file', (event, pathToOpen) =>
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
@ -74,6 +74,8 @@ class AtomWindow
|
|||||||
global.atomApplication.removeWindow(this)
|
global.atomApplication.removeWindow(this)
|
||||||
|
|
||||||
@browserWindow.on 'unresponsive', =>
|
@browserWindow.on 'unresponsive', =>
|
||||||
|
return if @isSpec
|
||||||
|
|
||||||
chosen = dialog.showMessageBox @browserWindow,
|
chosen = dialog.showMessageBox @browserWindow,
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
buttons: ['Close', 'Keep Waiting']
|
buttons: ['Close', 'Keep Waiting']
|
||||||
|
@ -7,16 +7,14 @@ fs = require 'fs'
|
|||||||
module = require 'module'
|
module = require 'module'
|
||||||
path = require 'path'
|
path = require 'path'
|
||||||
optimist = require 'optimist'
|
optimist = require 'optimist'
|
||||||
# TODO: NSLog is missing .lib on windows
|
nslog = require 'nslog'
|
||||||
nslog = require 'nslog' unless process.platform is 'win32'
|
|
||||||
dialog = require 'dialog'
|
dialog = require 'dialog'
|
||||||
|
|
||||||
console.log = (args...) ->
|
console.log = (args...) ->
|
||||||
# TODO: Make NSLog work as expected
|
# TODO: Make NSLog work as expected
|
||||||
output = args.map((arg) -> JSON.stringify(arg)).join(" ")
|
output = args.map((arg) -> JSON.stringify(arg)).join(" ")
|
||||||
if process.platform == 'darwin'
|
nslog(output)
|
||||||
nslog(output)
|
if process.platform isnt 'darwin'
|
||||||
else
|
|
||||||
fs.writeFileSync('debug.log', output, flag: 'a')
|
fs.writeFileSync('debug.log', output, flag: 'a')
|
||||||
|
|
||||||
process.on 'uncaughtException', (error={}) ->
|
process.on 'uncaughtException', (error={}) ->
|
||||||
|
@ -6,6 +6,12 @@ path = require 'path'
|
|||||||
#
|
#
|
||||||
# This may seem unnecessary but on Windows we have to have separate executables
|
# 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.
|
# for each script without this since Windows doesn't support shebang strings.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {BufferedNodeProcess} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class BufferedNodeProcess extends BufferedProcess
|
class BufferedNodeProcess extends BufferedProcess
|
||||||
# Executes the given Node script.
|
# Executes the given Node script.
|
||||||
|
@ -1,6 +1,12 @@
|
|||||||
ChildProcess = require 'child_process'
|
ChildProcess = require 'child_process'
|
||||||
|
|
||||||
# Public: A wrapper which provides line buffering for Node's ChildProcess.
|
# Public: A wrapper which provides line buffering for Node's ChildProcess.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {BufferedProcess} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class BufferedProcess
|
class BufferedProcess
|
||||||
process: null
|
process: null
|
||||||
|
@ -22,7 +22,10 @@ getCachedJavaScript = (cachePath) ->
|
|||||||
fs.readFileSync(cachePath, 'utf8') if stat.isFile()
|
fs.readFileSync(cachePath, 'utf8') if stat.isFile()
|
||||||
|
|
||||||
compileCoffeeScript = (coffee, filePath, cachePath) ->
|
compileCoffeeScript = (coffee, filePath, cachePath) ->
|
||||||
js = CoffeeScript.compile(coffee, filename: filePath)
|
{js,v3SourceMap} = CoffeeScript.compile(coffee, filename: filePath, sourceMap: true)
|
||||||
|
# Include source map in the web page environment.
|
||||||
|
if btoa? and JSON? and unescape? and encodeURIComponent?
|
||||||
|
js = "#{js}\n//# sourceMappingURL=data:application/json;base64,#{btoa unescape encodeURIComponent v3SourceMap}\n//# sourceURL=#{filePath}"
|
||||||
try
|
try
|
||||||
mkdir(path.dirname(cachePath))
|
mkdir(path.dirname(cachePath))
|
||||||
fs.writeFileSync(cachePath, js)
|
fs.writeFileSync(cachePath, js)
|
||||||
|
@ -23,46 +23,32 @@ unlinkCommand = (destinationPath, callback) ->
|
|||||||
callback()
|
callback()
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
findInstallDirectory: (callback) ->
|
getInstallDirectory: ->
|
||||||
directories = ['/opt/boxen', '/opt/github', '/usr/local']
|
"/usr/local/bin"
|
||||||
async.detect(directories, fs.isDirectory, callback)
|
|
||||||
|
|
||||||
install: (commandPath, commandName, callback) ->
|
install: (commandPath, callback) ->
|
||||||
if not commandName? or _.isFunction(commandName)
|
return unless process.platform is 'darwin'
|
||||||
callback = commandName
|
|
||||||
commandName = path.basename(commandPath, path.extname(commandPath))
|
|
||||||
|
|
||||||
installCallback = (error, sourcePath, destinationPath) ->
|
commandName = path.basename(commandPath, path.extname(commandPath))
|
||||||
if error?
|
directory = @getInstallDirectory()
|
||||||
console.warn "Failed to install `#{commandName}` binary", error
|
if fs.existsSync(directory)
|
||||||
callback?(error, sourcePath, destinationPath)
|
destinationPath = path.join(directory, commandName)
|
||||||
|
unlinkCommand destinationPath, (error) =>
|
||||||
@findInstallDirectory (directory) ->
|
if error?
|
||||||
if directory?
|
error = new Error "Could not remove file at #{destinationPath}." if error
|
||||||
destinationPath = path.join(directory, 'bin', commandName)
|
callback?(error)
|
||||||
unlinkCommand destinationPath, (error) ->
|
else
|
||||||
if error?
|
symlinkCommand commandPath, destinationPath, (error) =>
|
||||||
installCallback(error)
|
error = new Error "Failed to symlink #{commandPath} to #{destinationPath}." if error
|
||||||
else
|
callback?(error)
|
||||||
symlinkCommand commandPath, destinationPath, (error) ->
|
else
|
||||||
installCallback(error, commandPath, destinationPath)
|
error = new Error "Directory '#{directory} doesn't exist."
|
||||||
else
|
callback?(error)
|
||||||
installCallback(new Error("No destination directory exists to install"))
|
|
||||||
|
|
||||||
installAtomCommand: (resourcePath, callback) ->
|
installAtomCommand: (resourcePath, callback) ->
|
||||||
if _.isFunction(resourcePath)
|
|
||||||
callback = resourcePath
|
|
||||||
resourcePath = null
|
|
||||||
|
|
||||||
resourcePath ?= atom.getLoadSettings().resourcePath
|
|
||||||
commandPath = path.join(resourcePath, 'atom.sh')
|
commandPath = path.join(resourcePath, 'atom.sh')
|
||||||
@install(commandPath, callback)
|
@install commandPath, callback
|
||||||
|
|
||||||
installApmCommand: (resourcePath, callback) ->
|
installApmCommand: (resourcePath, callback) ->
|
||||||
if _.isFunction(resourcePath)
|
|
||||||
callback = resourcePath
|
|
||||||
resourcePath = null
|
|
||||||
|
|
||||||
resourcePath ?= atom.getLoadSettings().resourcePath
|
|
||||||
commandPath = path.join(resourcePath, 'apm', 'node_modules', '.bin', 'apm')
|
commandPath = path.join(resourcePath, 'apm', 'node_modules', '.bin', 'apm')
|
||||||
@install(commandPath, callback)
|
@install commandPath, callback
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
|
Mixin = require 'mixto'
|
||||||
|
|
||||||
module.exports =
|
module.exports =
|
||||||
|
class ConfigObserver extends Mixin
|
||||||
observeConfig: (keyPath, args...) ->
|
observeConfig: (keyPath, args...) ->
|
||||||
@configSubscriptions ?= {}
|
@configSubscriptions ?= {}
|
||||||
@configSubscriptions[keyPath] = atom.config.observe(keyPath, args...)
|
@configSubscriptions[keyPath] = atom.config.observe(keyPath, args...)
|
||||||
|
@ -7,7 +7,13 @@ pathWatcher = require 'pathwatcher'
|
|||||||
|
|
||||||
File = require './file'
|
File = require './file'
|
||||||
|
|
||||||
# Public: Represents a directory using {File}s
|
# Public: Represents a directory using {File}s.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {Directory} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class Directory
|
class Directory
|
||||||
Emitter.includeInto(this)
|
Emitter.includeInto(this)
|
||||||
|
@ -15,7 +15,7 @@ ConfigObserver = require './config-observer'
|
|||||||
module.exports =
|
module.exports =
|
||||||
class DisplayBuffer extends Model
|
class DisplayBuffer extends Model
|
||||||
Serializable.includeInto(this)
|
Serializable.includeInto(this)
|
||||||
_.extend @prototype, ConfigObserver
|
ConfigObserver.includeInto(this)
|
||||||
|
|
||||||
@properties
|
@properties
|
||||||
softWrap: null
|
softWrap: null
|
||||||
@ -297,8 +297,12 @@ class DisplayBuffer extends Model
|
|||||||
[startScreenRow, endScreenRow] = @rowMap.screenRowRangeForBufferRow(row)
|
[startScreenRow, endScreenRow] = @rowMap.screenRowRangeForBufferRow(row)
|
||||||
for screenRow in [startScreenRow...endScreenRow]
|
for screenRow in [startScreenRow...endScreenRow]
|
||||||
unless screenLine = @screenLines[screenRow]
|
unless screenLine = @screenLines[screenRow]
|
||||||
throw new Error("No screen line exists for screen row #{screenRow}, converted from buffer position (#{row}, #{column})")
|
throw new Error """
|
||||||
|
No screen line exists for screen row #{screenRow}, converted from buffer position (#{row}, #{column})
|
||||||
|
Soft wrap enabled: #{@getSoftWrap()}
|
||||||
|
Fold count: #{@findFoldMarkers().length}
|
||||||
|
Last buffer row: #{@getLastRow()}
|
||||||
|
"""
|
||||||
maxBufferColumn = screenLine.getMaxBufferColumn()
|
maxBufferColumn = screenLine.getMaxBufferColumn()
|
||||||
if screenLine.isSoftWrapped() and column > maxBufferColumn
|
if screenLine.isSoftWrapped() and column > maxBufferColumn
|
||||||
continue
|
continue
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{View, $, $$$} = require './space-pen-extensions'
|
{View, $, $$$} = require './space-pen-extensions'
|
||||||
TextBuffer = require './text-buffer'
|
TextBuffer = require './text-buffer'
|
||||||
Gutter = require './gutter'
|
GutterView = require './gutter-view'
|
||||||
{Point, Range} = require 'text-buffer'
|
{Point, Range} = require 'text-buffer'
|
||||||
Editor = require './editor'
|
Editor = require './editor'
|
||||||
CursorView = require './cursor-view'
|
CursorView = require './cursor-view'
|
||||||
@ -16,6 +16,12 @@ LongLineLength = 1000
|
|||||||
# Public: Represents the entire visual pane in Atom.
|
# Public: Represents the entire visual pane in Atom.
|
||||||
#
|
#
|
||||||
# The EditorView manages the {Editor}, which manages the file buffers.
|
# The EditorView manages the {Editor}, which manages the file buffers.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {EditorView} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class EditorView extends View
|
class EditorView extends View
|
||||||
@characterWidthCache: {}
|
@characterWidthCache: {}
|
||||||
@ -41,7 +47,7 @@ class EditorView extends View
|
|||||||
attributes = { class: @classes(params), tabindex: -1 }
|
attributes = { class: @classes(params), tabindex: -1 }
|
||||||
_.extend(attributes, params.attributes) if params.attributes
|
_.extend(attributes, params.attributes) if params.attributes
|
||||||
@div attributes, =>
|
@div attributes, =>
|
||||||
@subview 'gutter', new Gutter
|
@subview 'gutter', new GutterView
|
||||||
@div class: 'scroll-view', outlet: 'scrollView', =>
|
@div class: 'scroll-view', outlet: 'scrollView', =>
|
||||||
@div class: 'overlayer', outlet: 'overlayer'
|
@div class: 'overlayer', outlet: 'overlayer'
|
||||||
@div class: 'lines', outlet: 'renderedLines'
|
@div class: 'lines', outlet: 'renderedLines'
|
||||||
@ -405,7 +411,7 @@ class EditorView extends View
|
|||||||
|
|
||||||
selectedText = null
|
selectedText = null
|
||||||
@hiddenInput.on 'compositionstart', =>
|
@hiddenInput.on 'compositionstart', =>
|
||||||
selectedText = @getSelectedText()
|
selectedText = @editor.getSelectedText()
|
||||||
@hiddenInput.css('width', '100%')
|
@hiddenInput.css('width', '100%')
|
||||||
@hiddenInput.on 'compositionupdate', (e) =>
|
@hiddenInput.on 'compositionupdate', (e) =>
|
||||||
@editor.insertText(e.originalEvent.data, {select: true, undo: 'skip'})
|
@editor.insertText(e.originalEvent.data, {select: true, undo: 'skip'})
|
||||||
|
@ -202,8 +202,8 @@ class Editor extends Model
|
|||||||
# Deprecated: Use the ::scrollLeft property directly
|
# Deprecated: Use the ::scrollLeft property directly
|
||||||
getScrollLeft: -> @scrollLeft
|
getScrollLeft: -> @scrollLeft
|
||||||
|
|
||||||
# Set the number of characters that can be displayed horizontally in the
|
# Public: Set the number of characters that can be displayed horizontally in
|
||||||
# editor that contains this edit session.
|
# the editor.
|
||||||
#
|
#
|
||||||
# editorWidthInChars - A {Number} of characters
|
# editorWidthInChars - A {Number} of characters
|
||||||
setEditorWidthInChars: (editorWidthInChars) ->
|
setEditorWidthInChars: (editorWidthInChars) ->
|
||||||
@ -765,27 +765,27 @@ class Editor extends Model
|
|||||||
findMarkers: (attributes) ->
|
findMarkers: (attributes) ->
|
||||||
@displayBuffer.findMarkers(attributes)
|
@displayBuffer.findMarkers(attributes)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.markScreenRange}
|
# Public: {Delegates to: DisplayBuffer.markScreenRange}
|
||||||
markScreenRange: (args...) ->
|
markScreenRange: (args...) ->
|
||||||
@displayBuffer.markScreenRange(args...)
|
@displayBuffer.markScreenRange(args...)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.markBufferRange}
|
# Public: {Delegates to: DisplayBuffer.markBufferRange}
|
||||||
markBufferRange: (args...) ->
|
markBufferRange: (args...) ->
|
||||||
@displayBuffer.markBufferRange(args...)
|
@displayBuffer.markBufferRange(args...)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.markScreenPosition}
|
# Public: {Delegates to: DisplayBuffer.markScreenPosition}
|
||||||
markScreenPosition: (args...) ->
|
markScreenPosition: (args...) ->
|
||||||
@displayBuffer.markScreenPosition(args...)
|
@displayBuffer.markScreenPosition(args...)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.markBufferPosition}
|
# Public: {Delegates to: DisplayBuffer.markBufferPosition}
|
||||||
markBufferPosition: (args...) ->
|
markBufferPosition: (args...) ->
|
||||||
@displayBuffer.markBufferPosition(args...)
|
@displayBuffer.markBufferPosition(args...)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.destroyMarker}
|
# Public: {Delegates to: DisplayBuffer.destroyMarker}
|
||||||
destroyMarker: (args...) ->
|
destroyMarker: (args...) ->
|
||||||
@displayBuffer.destroyMarker(args...)
|
@displayBuffer.destroyMarker(args...)
|
||||||
|
|
||||||
# {Delegates to: DisplayBuffer.getMarkerCount}
|
# Public: {Delegates to: DisplayBuffer.getMarkerCount}
|
||||||
getMarkerCount: ->
|
getMarkerCount: ->
|
||||||
@buffer.getMarkerCount()
|
@buffer.getMarkerCount()
|
||||||
|
|
||||||
|
@ -10,6 +10,12 @@ fs = require 'fs-plus'
|
|||||||
#
|
#
|
||||||
# You should probably create a {Directory} and access the {File} objects that
|
# You should probably create a {Directory} and access the {File} objects that
|
||||||
# it creates, rather than instantiating the {File} class directly.
|
# it creates, rather than instantiating the {File} class directly.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {File} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class File
|
class File
|
||||||
Emitter.includeInto(this)
|
Emitter.includeInto(this)
|
||||||
|
@ -7,7 +7,8 @@ GitUtils = require 'git-utils'
|
|||||||
# Public: Represents the underlying git operations performed by Atom.
|
# Public: Represents the underlying git operations performed by Atom.
|
||||||
#
|
#
|
||||||
# This class shouldn't be instantiated directly but instead by accessing the
|
# This class shouldn't be instantiated directly but instead by accessing the
|
||||||
# `atom.project` global and calling `getRepo()`.
|
# `atom.project` global and calling `getRepo()`. Note that this will only be
|
||||||
|
# available when the project is backed by a Git repository.
|
||||||
#
|
#
|
||||||
# ## Example
|
# ## Example
|
||||||
#
|
#
|
||||||
@ -15,6 +16,12 @@ GitUtils = require 'git-utils'
|
|||||||
# git = atom.project.getRepo()
|
# git = atom.project.getRepo()
|
||||||
# console.log git.getOriginUrl()
|
# console.log git.getOriginUrl()
|
||||||
# ```
|
# ```
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {Git} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class Git
|
class Git
|
||||||
Emitter.includeInto(this)
|
Emitter.includeInto(this)
|
||||||
@ -250,12 +257,7 @@ class Git
|
|||||||
# Public: Returns the upstream branch for the current HEAD, or null if there
|
# Public: Returns the upstream branch for the current HEAD, or null if there
|
||||||
# is no upstream branch for the current HEAD.
|
# is no upstream branch for the current HEAD.
|
||||||
#
|
#
|
||||||
# Examples
|
# Returns a String branch name such as `refs/remotes/origin/master`
|
||||||
#
|
|
||||||
# getUpstreamBranch()
|
|
||||||
# # => "refs/remotes/origin/master"
|
|
||||||
#
|
|
||||||
# Returns a String.
|
|
||||||
getUpstreamBranch: -> @getRepo().getUpstreamBranch()
|
getUpstreamBranch: -> @getRepo().getUpstreamBranch()
|
||||||
|
|
||||||
# Public: Returns the current SHA for the given reference.
|
# Public: Returns the current SHA for the given reference.
|
||||||
|
@ -6,7 +6,7 @@ _ = require 'underscore-plus'
|
|||||||
#
|
#
|
||||||
# The gutter also indicates if rows are folded.
|
# The gutter also indicates if rows are folded.
|
||||||
module.exports =
|
module.exports =
|
||||||
class Gutter extends View
|
class GutterView extends View
|
||||||
|
|
||||||
### Internal ###
|
### Internal ###
|
||||||
|
|
||||||
@ -234,11 +234,11 @@ class Gutter extends View
|
|||||||
lastBufferRow = null
|
lastBufferRow = null
|
||||||
for bufferRow in editor.bufferRowsForScreenRows(startScreenRow, endScreenRow) when bufferRow isnt lastBufferRow
|
for bufferRow in editor.bufferRowsForScreenRows(startScreenRow, endScreenRow) when bufferRow isnt lastBufferRow
|
||||||
lastBufferRow = bufferRow
|
lastBufferRow = bufferRow
|
||||||
lineNumberElement = @getLineNumberElement(bufferRow)[0]
|
if lineNumberElement = @getLineNumberElement(bufferRow)[0]
|
||||||
if editor.isFoldableAtBufferRow(bufferRow)
|
if editor.isFoldableAtBufferRow(bufferRow)
|
||||||
lineNumberElement.classList.add('foldable')
|
lineNumberElement.classList.add('foldable')
|
||||||
else
|
else
|
||||||
lineNumberElement.classList.remove('foldable')
|
lineNumberElement.classList.remove('foldable')
|
||||||
|
|
||||||
removeLineHighlights: ->
|
removeLineHighlights: ->
|
||||||
return unless @highlightedLineNumbers
|
return unless @highlightedLineNumbers
|
@ -142,7 +142,12 @@ class Keymap
|
|||||||
@userKeymapFile.on 'contents-changed moved removed', => @loadUserKeymap()
|
@userKeymapFile.on 'contents-changed moved removed', => @loadUserKeymap()
|
||||||
|
|
||||||
loadDirectory: (directoryPath) ->
|
loadDirectory: (directoryPath) ->
|
||||||
@load(filePath) for filePath in fs.listSync(directoryPath, ['.cson', '.json'])
|
platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32']
|
||||||
|
otherPlatforms = platforms.filter (name) -> name != process.platform
|
||||||
|
|
||||||
|
for filePath in fs.listSync(directoryPath, ['.cson', '.json'])
|
||||||
|
continue if path.basename(filePath, path.extname(filePath)) in otherPlatforms
|
||||||
|
@load(filePath)
|
||||||
|
|
||||||
load: (path) ->
|
load: (path) ->
|
||||||
@add(path, CSON.readFileSync(path))
|
@add(path, CSON.readFileSync(path))
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
clipboard = require 'clipboard'
|
clipboard = require 'clipboard'
|
||||||
crypto = require 'crypto'
|
crypto = require 'crypto'
|
||||||
|
|
||||||
# Internal: Represents the clipboard used for copying and pasting in Atom.
|
# Public: Represents the clipboard used for copying and pasting in Atom.
|
||||||
|
#
|
||||||
|
# A pasteboard instance is always available under the `atom.pasteboard` global.
|
||||||
module.exports =
|
module.exports =
|
||||||
class Pasteboard
|
class Pasteboard
|
||||||
signatureForMetadata: null
|
signatureForMetadata: null
|
||||||
@ -14,18 +16,19 @@ class Pasteboard
|
|||||||
md5: (text) ->
|
md5: (text) ->
|
||||||
crypto.createHash('md5').update(text, 'utf8').digest('hex')
|
crypto.createHash('md5').update(text, 'utf8').digest('hex')
|
||||||
|
|
||||||
# Saves from the clipboard.
|
# Public: Write the given text to the clipboard.
|
||||||
#
|
#
|
||||||
# text - A {String} to store
|
# text - A {String} to store.
|
||||||
# metadata - An object of additional info to associate with the text
|
# metadata - An {Object} of additional info to associate with the text.
|
||||||
write: (text, metadata) ->
|
write: (text, metadata) ->
|
||||||
@signatureForMetadata = @md5(text)
|
@signatureForMetadata = @md5(text)
|
||||||
@metadata = metadata
|
@metadata = metadata
|
||||||
clipboard.writeText(text)
|
clipboard.writeText(text)
|
||||||
|
|
||||||
# Loads from the clipboard.
|
# Public: Read the text from the clipboard.
|
||||||
#
|
#
|
||||||
# Returns an {Array}. The first index is the saved text, and the second is any metadata associated with the text.
|
# Returns an {Array}. The first element is the saved text and the second is
|
||||||
|
# any metadata associated with the text.
|
||||||
read: ->
|
read: ->
|
||||||
text = clipboard.readText()
|
text = clipboard.readText()
|
||||||
value = [text]
|
value = [text]
|
||||||
|
@ -16,8 +16,7 @@ Git = require './git'
|
|||||||
|
|
||||||
# Public: Represents a project that's opened in Atom.
|
# Public: Represents a project that's opened in Atom.
|
||||||
#
|
#
|
||||||
# Ultimately, a project is a git directory that's been opened. It's a collection
|
# There is always a project available under the `atom.project` global.
|
||||||
# of directories and files that you can operate on.
|
|
||||||
module.exports =
|
module.exports =
|
||||||
class Project extends Model
|
class Project extends Model
|
||||||
atom.deserializers.add(this)
|
atom.deserializers.add(this)
|
||||||
|
@ -5,9 +5,11 @@
|
|||||||
# This `View` subclass listens to events such as `page-up`, `page-down`,
|
# This `View` subclass listens to events such as `page-up`, `page-down`,
|
||||||
# `move-to-top`, and `move-to-bottom`.
|
# `move-to-top`, and `move-to-bottom`.
|
||||||
#
|
#
|
||||||
# FIXME: I don't actually understand if this is useful or not. I think it is
|
# ## Requiring in packages
|
||||||
# a base of package widgets but I don't really understand how the core events
|
#
|
||||||
# work.
|
# ```coffee
|
||||||
|
# {ScrollView} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class ScrollView extends View
|
class ScrollView extends View
|
||||||
|
|
||||||
|
@ -4,6 +4,12 @@ fuzzyFilter = require('fuzzaldrin').filter
|
|||||||
|
|
||||||
# Public: Provides a widget for users to make a selection from a list of
|
# Public: Provides a widget for users to make a selection from a list of
|
||||||
# choices.
|
# choices.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {SelectList} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class SelectList extends View
|
class SelectList extends View
|
||||||
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
_ = require 'underscore-plus'
|
_ = require 'underscore-plus'
|
||||||
spacePen = require 'space-pen'
|
spacePen = require 'space-pen'
|
||||||
ConfigObserver = require './config-observer'
|
|
||||||
{Subscriber} = require 'emissary'
|
{Subscriber} = require 'emissary'
|
||||||
|
ConfigObserver = require './config-observer'
|
||||||
|
|
||||||
_.extend spacePen.View.prototype, ConfigObserver
|
ConfigObserver.includeInto(spacePen.View)
|
||||||
Subscriber.includeInto(spacePen.View)
|
Subscriber.includeInto(spacePen.View)
|
||||||
|
|
||||||
jQuery = spacePen.jQuery
|
jQuery = spacePen.jQuery
|
||||||
|
@ -6,7 +6,12 @@ _ = require 'underscore-plus'
|
|||||||
{$, $$} = require './space-pen-extensions'
|
{$, $$} = require './space-pen-extensions'
|
||||||
Token = require './token'
|
Token = require './token'
|
||||||
|
|
||||||
### Public ###
|
# Public: Syntax class holding the grammars used for tokenizing.
|
||||||
|
#
|
||||||
|
# The Syntax class also contains properties for things such as the
|
||||||
|
# language-specific comment regexes.
|
||||||
|
#
|
||||||
|
# There is always a syntax object available under the `atom.syntax` global.
|
||||||
module.exports =
|
module.exports =
|
||||||
class Syntax extends GrammarRegistry
|
class Syntax extends GrammarRegistry
|
||||||
Subscriber.includeInto(this)
|
Subscriber.includeInto(this)
|
||||||
@ -49,6 +54,18 @@ class Syntax extends GrammarRegistry
|
|||||||
@scopedProperties = []
|
@scopedProperties = []
|
||||||
@scopedPropertiesIndex = 0
|
@scopedPropertiesIndex = 0
|
||||||
|
|
||||||
|
# Public: Get a property for the given scope and key path.
|
||||||
|
#
|
||||||
|
# ## Example
|
||||||
|
# ```coffee
|
||||||
|
# comment = atom.syntax.getProperty(['.source.ruby'], 'editor.commentStart')
|
||||||
|
# console.log(comment) # '# '
|
||||||
|
# ```
|
||||||
|
#
|
||||||
|
# * scope: An {Array} of {String} scopes.
|
||||||
|
# * keyPath: A {String} key path.
|
||||||
|
#
|
||||||
|
# Returns a {String} property value or undefined.
|
||||||
getProperty: (scope, keyPath) ->
|
getProperty: (scope, keyPath) ->
|
||||||
for object in @propertiesForScope(scope, keyPath)
|
for object in @propertiesForScope(scope, keyPath)
|
||||||
value = _.valueForKeyPath(object, keyPath)
|
value = _.valueForKeyPath(object, keyPath)
|
||||||
|
@ -12,6 +12,12 @@ child_process = require 'child_process'
|
|||||||
# * task:warn - Emitted when console.warn is called within the task.
|
# * task:warn - Emitted when console.warn is called within the task.
|
||||||
# * task:error - Emitted when console.error is called within the task.
|
# * task:error - Emitted when console.error is called within the task.
|
||||||
# * task:completed - Emitted when the task has succeeded or failed.
|
# * task:completed - Emitted when the task has succeeded or failed.
|
||||||
|
#
|
||||||
|
# ## Requiring in packages
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {Task} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class Task
|
class Task
|
||||||
Emitter.includeInto(this)
|
Emitter.includeInto(this)
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
### Internal ###
|
|
||||||
|
|
||||||
isHighSurrogate = (string, index) ->
|
isHighSurrogate = (string, index) ->
|
||||||
0xD800 <= string.charCodeAt(index) <= 0xDBFF
|
0xD800 <= string.charCodeAt(index) <= 0xDBFF
|
||||||
|
|
||||||
isLowSurrogate = (string, index) ->
|
isLowSurrogate = (string, index) ->
|
||||||
0xDC00 <= string.charCodeAt(index) <= 0xDFFF
|
0xDC00 <= string.charCodeAt(index) <= 0xDFFF
|
||||||
|
|
||||||
### Public ###
|
|
||||||
|
|
||||||
# Is the character at the given index the start of a high/low surrogate pair?
|
# Is the character at the given index the start of a high/low surrogate pair?
|
||||||
#
|
#
|
||||||
# string - The {String} to check for a surrogate pair.
|
# string - The {String} to check for a surrogate pair.
|
||||||
|
@ -8,9 +8,9 @@ fs = require 'fs-plus'
|
|||||||
AtomPackage = require './atom-package'
|
AtomPackage = require './atom-package'
|
||||||
File = require './file'
|
File = require './file'
|
||||||
|
|
||||||
# Private: Handles discovering and loading available themes.
|
# Public: Handles loading and activating available themes.
|
||||||
#
|
#
|
||||||
# Themes are a subset of packages
|
# A ThemeManager instance is always available under the `atom.themes` global.
|
||||||
module.exports =
|
module.exports =
|
||||||
class ThemeManager
|
class ThemeManager
|
||||||
Emitter.includeInto(this)
|
Emitter.includeInto(this)
|
||||||
@ -19,27 +19,26 @@ class ThemeManager
|
|||||||
@lessCache = null
|
@lessCache = null
|
||||||
@packageManager.registerPackageActivator(this, ['theme'])
|
@packageManager.registerPackageActivator(this, ['theme'])
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
getAvailableNames: ->
|
getAvailableNames: ->
|
||||||
# TODO: Maybe should change to list all the available themes out there?
|
# TODO: Maybe should change to list all the available themes out there?
|
||||||
@getLoadedNames()
|
@getLoadedNames()
|
||||||
|
|
||||||
|
# Public: Get an array of all the loaded theme names.
|
||||||
getLoadedNames: ->
|
getLoadedNames: ->
|
||||||
theme.name for theme in @getLoadedThemes()
|
theme.name for theme in @getLoadedThemes()
|
||||||
|
|
||||||
# Internal-only:
|
# Public: Get an array of all the active theme names.
|
||||||
getActiveNames: ->
|
getActiveNames: ->
|
||||||
theme.name for theme in @getActiveThemes()
|
theme.name for theme in @getActiveThemes()
|
||||||
|
|
||||||
# Internal-only:
|
# Public: Get an array of all the active themes.
|
||||||
getActiveThemes: ->
|
getActiveThemes: ->
|
||||||
pack for pack in @packageManager.getActivePackages() when pack.isTheme()
|
pack for pack in @packageManager.getActivePackages() when pack.isTheme()
|
||||||
|
|
||||||
# Internal-only:
|
# Public: Get an array of all the loaded themes.
|
||||||
getLoadedThemes: ->
|
getLoadedThemes: ->
|
||||||
pack for pack in @packageManager.getLoadedPackages() when pack.isTheme()
|
pack for pack in @packageManager.getLoadedPackages() when pack.isTheme()
|
||||||
|
|
||||||
# Internal-only: adhere to the PackageActivator interface
|
|
||||||
activatePackages: (themePackages) -> @activateThemes()
|
activatePackages: (themePackages) -> @activateThemes()
|
||||||
|
|
||||||
# Private: Get the enabled theme names from the config.
|
# Private: Get the enabled theme names from the config.
|
||||||
@ -53,7 +52,6 @@ class ThemeManager
|
|||||||
# the first/top theme to override later themes in the stack.
|
# the first/top theme to override later themes in the stack.
|
||||||
themeNames.reverse()
|
themeNames.reverse()
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
activateThemes: ->
|
activateThemes: ->
|
||||||
# atom.config.observe runs the callback once, then on subsequent changes.
|
# atom.config.observe runs the callback once, then on subsequent changes.
|
||||||
atom.config.observe 'core.themes', =>
|
atom.config.observe 'core.themes', =>
|
||||||
@ -69,13 +67,11 @@ class ThemeManager
|
|||||||
|
|
||||||
@emit('reloaded')
|
@emit('reloaded')
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
deactivateThemes: ->
|
deactivateThemes: ->
|
||||||
@unwatchUserStylesheet()
|
@unwatchUserStylesheet()
|
||||||
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
|
@packageManager.deactivatePackage(pack.name) for pack in @getActiveThemes()
|
||||||
null
|
null
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
refreshLessCache: ->
|
refreshLessCache: ->
|
||||||
@lessCache?.setImportPaths(@getImportPaths())
|
@lessCache?.setImportPaths(@getImportPaths())
|
||||||
|
|
||||||
@ -85,7 +81,6 @@ class ThemeManager
|
|||||||
setEnabledThemes: (enabledThemeNames) ->
|
setEnabledThemes: (enabledThemeNames) ->
|
||||||
atom.config.set('core.themes', enabledThemeNames)
|
atom.config.set('core.themes', enabledThemeNames)
|
||||||
|
|
||||||
# Public:
|
|
||||||
getImportPaths: ->
|
getImportPaths: ->
|
||||||
activeThemes = @getActiveThemes()
|
activeThemes = @getActiveThemes()
|
||||||
if activeThemes.length > 0
|
if activeThemes.length > 0
|
||||||
@ -98,7 +93,7 @@ class ThemeManager
|
|||||||
|
|
||||||
themePath for themePath in themePaths when fs.isDirectorySync(themePath)
|
themePath for themePath in themePaths when fs.isDirectorySync(themePath)
|
||||||
|
|
||||||
# Public:
|
# Public: Returns the {String} path to the user's stylesheet under ~/.atom
|
||||||
getUserStylesheetPath: ->
|
getUserStylesheetPath: ->
|
||||||
stylesheetPath = fs.resolve(path.join(@configDirPath, 'user'), ['css', 'less'])
|
stylesheetPath = fs.resolve(path.join(@configDirPath, 'user'), ['css', 'less'])
|
||||||
if fs.isFileSync(stylesheetPath)
|
if fs.isFileSync(stylesheetPath)
|
||||||
@ -106,13 +101,11 @@ class ThemeManager
|
|||||||
else
|
else
|
||||||
path.join(@configDirPath, 'user.less')
|
path.join(@configDirPath, 'user.less')
|
||||||
|
|
||||||
#Private:
|
|
||||||
unwatchUserStylesheet: ->
|
unwatchUserStylesheet: ->
|
||||||
@userStylesheetFile?.off()
|
@userStylesheetFile?.off()
|
||||||
@userStylesheetFile = null
|
@userStylesheetFile = null
|
||||||
@removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
|
@removeStylesheet(@userStylesheetPath) if @userStylesheetPath?
|
||||||
|
|
||||||
# Private:
|
|
||||||
loadUserStylesheet: ->
|
loadUserStylesheet: ->
|
||||||
@unwatchUserStylesheet()
|
@unwatchUserStylesheet()
|
||||||
userStylesheetPath = @getUserStylesheetPath()
|
userStylesheetPath = @getUserStylesheetPath()
|
||||||
@ -125,34 +118,32 @@ class ThemeManager
|
|||||||
userStylesheetContents = @loadStylesheet(userStylesheetPath)
|
userStylesheetContents = @loadStylesheet(userStylesheetPath)
|
||||||
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
|
@applyStylesheet(userStylesheetPath, userStylesheetContents, 'userTheme')
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
loadBaseStylesheets: ->
|
loadBaseStylesheets: ->
|
||||||
@requireStylesheet('bootstrap/less/bootstrap')
|
@requireStylesheet('bootstrap/less/bootstrap')
|
||||||
@reloadBaseStylesheets()
|
@reloadBaseStylesheets()
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
reloadBaseStylesheets: ->
|
reloadBaseStylesheets: ->
|
||||||
@requireStylesheet('../static/atom')
|
@requireStylesheet('../static/atom')
|
||||||
if nativeStylesheetPath = fs.resolveOnLoadPath(process.platform, ['css', 'less'])
|
if nativeStylesheetPath = fs.resolveOnLoadPath(process.platform, ['css', 'less'])
|
||||||
@requireStylesheet(nativeStylesheetPath)
|
@requireStylesheet(nativeStylesheetPath)
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
stylesheetElementForId: (id, htmlElement=$('html')) ->
|
stylesheetElementForId: (id, htmlElement=$('html')) ->
|
||||||
htmlElement.find("""head style[id="#{id}"]""")
|
htmlElement.find("""head style[id="#{id}"]""")
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
resolveStylesheet: (stylesheetPath) ->
|
resolveStylesheet: (stylesheetPath) ->
|
||||||
if path.extname(stylesheetPath).length > 0
|
if path.extname(stylesheetPath).length > 0
|
||||||
fs.resolveOnLoadPath(stylesheetPath)
|
fs.resolveOnLoadPath(stylesheetPath)
|
||||||
else
|
else
|
||||||
fs.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
|
fs.resolveOnLoadPath(stylesheetPath, ['css', 'less'])
|
||||||
|
|
||||||
# Public: resolves and applies the stylesheet specified by the path.
|
# Public: Resolve and apply the stylesheet specified by the path.
|
||||||
#
|
#
|
||||||
# * stylesheetPath: String. Can be an absolute path or the name of a CSS or
|
# This supports both CSS and LESS stylsheets.
|
||||||
# LESS file in the stylesheets path.
|
|
||||||
#
|
#
|
||||||
# Returns the absolute path to the stylesheet
|
# * stylesheetPath: A {String} path to the stylesheet that can be an absolute
|
||||||
|
# path or a relative path that will be resolved against the load path.
|
||||||
|
#
|
||||||
|
# Returns the absolute path to the required stylesheet.
|
||||||
requireStylesheet: (stylesheetPath, ttype = 'bundled', htmlElement) ->
|
requireStylesheet: (stylesheetPath, ttype = 'bundled', htmlElement) ->
|
||||||
if fullPath = @resolveStylesheet(stylesheetPath)
|
if fullPath = @resolveStylesheet(stylesheetPath)
|
||||||
content = @loadStylesheet(fullPath)
|
content = @loadStylesheet(fullPath)
|
||||||
@ -162,14 +153,12 @@ class ThemeManager
|
|||||||
|
|
||||||
fullPath
|
fullPath
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
loadStylesheet: (stylesheetPath) ->
|
loadStylesheet: (stylesheetPath) ->
|
||||||
if path.extname(stylesheetPath) is '.less'
|
if path.extname(stylesheetPath) is '.less'
|
||||||
@loadLessStylesheet(stylesheetPath)
|
@loadLessStylesheet(stylesheetPath)
|
||||||
else
|
else
|
||||||
fs.readFileSync(stylesheetPath, 'utf8')
|
fs.readFileSync(stylesheetPath, 'utf8')
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
loadLessStylesheet: (lessStylesheetPath) ->
|
loadLessStylesheet: (lessStylesheetPath) ->
|
||||||
unless @lessCache?
|
unless @lessCache?
|
||||||
LessCompileCache = require './less-compile-cache'
|
LessCompileCache = require './less-compile-cache'
|
||||||
@ -184,16 +173,13 @@ class ThemeManager
|
|||||||
#{e.message}
|
#{e.message}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
stringToId: (string) ->
|
stringToId: (string) ->
|
||||||
string.replace(/\\/g, '/')
|
string.replace(/\\/g, '/')
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
removeStylesheet: (stylesheetPath) ->
|
removeStylesheet: (stylesheetPath) ->
|
||||||
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
|
fullPath = @resolveStylesheet(stylesheetPath) ? stylesheetPath
|
||||||
@stylesheetElementForId(@stringToId(fullPath)).remove()
|
@stylesheetElementForId(@stringToId(fullPath)).remove()
|
||||||
|
|
||||||
# Internal-only:
|
|
||||||
applyStylesheet: (path, text, ttype = 'bundled', htmlElement=$('html')) ->
|
applyStylesheet: (path, text, ttype = 'bundled', htmlElement=$('html')) ->
|
||||||
styleElement = @stylesheetElementForId(@stringToId(path), htmlElement)
|
styleElement = @stylesheetElementForId(@stringToId(path), htmlElement)
|
||||||
if styleElement.length
|
if styleElement.length
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
# Public: Measure how long a function takes to run.
|
# Public: Measure how long a function takes to run.
|
||||||
#
|
#
|
||||||
# * description:
|
# * description:
|
||||||
# A String description that will be logged to the console.
|
# A {String} description that will be logged to the console.
|
||||||
# * fn:
|
# * fn:
|
||||||
# A Function to measure the duration of.
|
# A {Function} to measure the duration of.
|
||||||
#
|
#
|
||||||
# Returns the value returned by the given function.
|
# Returns the value returned by the given function.
|
||||||
window.measure = (description, fn) ->
|
window.measure = (description, fn) ->
|
||||||
@ -16,10 +16,10 @@ window.measure = (description, fn) ->
|
|||||||
# Public: Create a dev tools profile for a function.
|
# Public: Create a dev tools profile for a function.
|
||||||
#
|
#
|
||||||
# * description:
|
# * description:
|
||||||
# A String descrption that will be available in the Profiles tab of the dev
|
# A {String} descrption that will be available in the Profiles tab of the dev
|
||||||
# tools.
|
# tools.
|
||||||
# * fn:
|
# * fn:
|
||||||
# A Function to profile.
|
# A {Function} to profile.
|
||||||
#
|
#
|
||||||
# Return the value returned by the given function.
|
# Return the value returned by the given function.
|
||||||
window.profile = (description, fn) ->
|
window.profile = (description, fn) ->
|
||||||
|
@ -6,6 +6,7 @@ Delegator = require 'delegato'
|
|||||||
{$, $$, View} = require './space-pen-extensions'
|
{$, $$, View} = require './space-pen-extensions'
|
||||||
fs = require 'fs-plus'
|
fs = require 'fs-plus'
|
||||||
Workspace = require './workspace'
|
Workspace = require './workspace'
|
||||||
|
CommandInstaller = require './command-installer'
|
||||||
EditorView = require './editor-view'
|
EditorView = require './editor-view'
|
||||||
PaneView = require './pane-view'
|
PaneView = require './pane-view'
|
||||||
PaneColumnView = require './pane-column-view'
|
PaneColumnView = require './pane-column-view'
|
||||||
@ -37,6 +38,11 @@ Editor = require './editor'
|
|||||||
# * `application:bring-all-windows-to-front` - Brings all {AtomWindow}s to the
|
# * `application:bring-all-windows-to-front` - Brings all {AtomWindow}s to the
|
||||||
# the front.
|
# the front.
|
||||||
#
|
#
|
||||||
|
# ## Requiring in package specs
|
||||||
|
#
|
||||||
|
# ```coffee
|
||||||
|
# {WorkspaceView} = require 'atom'
|
||||||
|
# ```
|
||||||
module.exports =
|
module.exports =
|
||||||
class WorkspaceView extends View
|
class WorkspaceView extends View
|
||||||
Delegator.includeInto(this)
|
Delegator.includeInto(this)
|
||||||
@ -101,8 +107,11 @@ class WorkspaceView extends View
|
|||||||
@command 'application:bring-all-windows-to-front', -> ipc.sendChannel('command', 'application:bring-all-windows-to-front')
|
@command 'application:bring-all-windows-to-front', -> ipc.sendChannel('command', 'application:bring-all-windows-to-front')
|
||||||
@command 'application:open-your-config', -> ipc.sendChannel('command', 'application:open-your-config')
|
@command 'application:open-your-config', -> ipc.sendChannel('command', 'application:open-your-config')
|
||||||
@command 'application:open-your-keymap', -> ipc.sendChannel('command', 'application:open-your-keymap')
|
@command 'application:open-your-keymap', -> ipc.sendChannel('command', 'application:open-your-keymap')
|
||||||
|
@command 'application:open-your-snippets', -> ipc.sendChannel('command', 'application:open-your-snippets')
|
||||||
@command 'application:open-your-stylesheet', -> ipc.sendChannel('command', 'application:open-your-stylesheet')
|
@command 'application:open-your-stylesheet', -> ipc.sendChannel('command', 'application:open-your-stylesheet')
|
||||||
|
|
||||||
|
@command 'window:install-shell-commands', => @installShellCommands()
|
||||||
|
|
||||||
@command 'window:run-package-specs', => ipc.sendChannel('run-package-specs', path.join(atom.project.getPath(), 'spec'))
|
@command 'window:run-package-specs', => ipc.sendChannel('run-package-specs', path.join(atom.project.getPath(), 'spec'))
|
||||||
@command 'window:increase-font-size', => @increaseFontSize()
|
@command 'window:increase-font-size', => @increaseFontSize()
|
||||||
@command 'window:decrease-font-size', => @decreaseFontSize()
|
@command 'window:decrease-font-size', => @decreaseFontSize()
|
||||||
@ -122,6 +131,26 @@ class WorkspaceView extends View
|
|||||||
@command 'core:save', => @saveActivePaneItem()
|
@command 'core:save', => @saveActivePaneItem()
|
||||||
@command 'core:save-as', => @saveActivePaneItemAs()
|
@command 'core:save-as', => @saveActivePaneItemAs()
|
||||||
|
|
||||||
|
installShellCommands: ->
|
||||||
|
showErrorDialog = (error) ->
|
||||||
|
installDirectory = CommandInstaller.getInstallDirectory()
|
||||||
|
atom.confirm
|
||||||
|
message: error.message
|
||||||
|
detailedMessage: "Make sure #{installDirectory} exists and is writable. Run 'sudo mkdir -p #{installDirectory} && sudo chown $USER #{installDirectory}' to fix this problem."
|
||||||
|
|
||||||
|
resourcePath = atom.getLoadSettings().resourcePath
|
||||||
|
CommandInstaller.installAtomCommand resourcePath, (error) =>
|
||||||
|
if error?
|
||||||
|
showDialog(error)
|
||||||
|
else
|
||||||
|
CommandInstaller.installApmCommand resourcePath, (error) =>
|
||||||
|
if error?
|
||||||
|
showDialog(error)
|
||||||
|
else
|
||||||
|
atom.confirm
|
||||||
|
message: "Commands installed."
|
||||||
|
detailedMessage: "The shell commands `atom` and `apm` are installed."
|
||||||
|
|
||||||
# Private:
|
# Private:
|
||||||
handleFocus: (e) ->
|
handleFocus: (e) ->
|
||||||
if @getActivePane()
|
if @getActivePane()
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
.make-icon(book);
|
.make-icon(book);
|
||||||
.make-icon(bookmark);
|
.make-icon(bookmark);
|
||||||
.make-icon(broadcast);
|
.make-icon(broadcast);
|
||||||
|
.make-icon(browser);
|
||||||
.make-icon(bug);
|
.make-icon(bug);
|
||||||
.make-icon(calendar);
|
.make-icon(calendar);
|
||||||
.make-icon(check);
|
.make-icon(check);
|
||||||
@ -46,6 +47,7 @@
|
|||||||
.make-icon(comment-add);
|
.make-icon(comment-add);
|
||||||
.make-icon(comment-discussion);
|
.make-icon(comment-discussion);
|
||||||
.make-icon(credit-card);
|
.make-icon(credit-card);
|
||||||
|
.make-icon(dash);
|
||||||
.make-icon(dashboard);
|
.make-icon(dashboard);
|
||||||
.make-icon(database);
|
.make-icon(database);
|
||||||
.make-icon(device-camera);
|
.make-icon(device-camera);
|
||||||
@ -74,6 +76,7 @@
|
|||||||
.make-icon(file-symlink-file);
|
.make-icon(file-symlink-file);
|
||||||
.make-icon(file-text);
|
.make-icon(file-text);
|
||||||
.make-icon(file-zip);
|
.make-icon(file-zip);
|
||||||
|
.make-icon(fold);
|
||||||
.make-icon(gear);
|
.make-icon(gear);
|
||||||
.make-icon(gift);
|
.make-icon(gift);
|
||||||
.make-icon(gist);
|
.make-icon(gist);
|
||||||
@ -92,6 +95,7 @@
|
|||||||
.make-icon(git-pull-request-abandoned);
|
.make-icon(git-pull-request-abandoned);
|
||||||
.make-icon(globe);
|
.make-icon(globe);
|
||||||
.make-icon(graph);
|
.make-icon(graph);
|
||||||
|
.make-icon(heart);
|
||||||
.make-icon(history);
|
.make-icon(history);
|
||||||
.make-icon(home);
|
.make-icon(home);
|
||||||
.make-icon(horizontal-rule);
|
.make-icon(horizontal-rule);
|
||||||
@ -127,10 +131,14 @@
|
|||||||
.make-icon(mail);
|
.make-icon(mail);
|
||||||
.make-icon(mail-read);
|
.make-icon(mail-read);
|
||||||
.make-icon(mail-reply);
|
.make-icon(mail-reply);
|
||||||
|
.make-icon(mark-facebook);
|
||||||
.make-icon(mark-github);
|
.make-icon(mark-github);
|
||||||
.make-icon(mark-github-detail);
|
.make-icon(mark-github-detail);
|
||||||
|
.make-icon(mark-google);
|
||||||
.make-icon(mark-twitter);
|
.make-icon(mark-twitter);
|
||||||
|
.make-icon(markdown);
|
||||||
.make-icon(megaphone);
|
.make-icon(megaphone);
|
||||||
|
.make-icon(mention);
|
||||||
.make-icon(microscope);
|
.make-icon(microscope);
|
||||||
.make-icon(milestone);
|
.make-icon(milestone);
|
||||||
.make-icon(mirror-private);
|
.make-icon(mirror-private);
|
||||||
@ -142,6 +150,7 @@
|
|||||||
.make-icon(mute);
|
.make-icon(mute);
|
||||||
.make-icon(mute-video);
|
.make-icon(mute-video);
|
||||||
.make-icon(no-newline);
|
.make-icon(no-newline);
|
||||||
|
.make-icon(node-js);
|
||||||
.make-icon(octoface);
|
.make-icon(octoface);
|
||||||
.make-icon(organization);
|
.make-icon(organization);
|
||||||
.make-icon(pencil);
|
.make-icon(pencil);
|
||||||
@ -150,11 +159,16 @@
|
|||||||
.make-icon(person-follow);
|
.make-icon(person-follow);
|
||||||
.make-icon(person-remove);
|
.make-icon(person-remove);
|
||||||
.make-icon(pin);
|
.make-icon(pin);
|
||||||
|
.make-icon(playback-fast-forward);
|
||||||
|
.make-icon(playback-pause);
|
||||||
|
.make-icon(playback-play);
|
||||||
|
.make-icon(playback-rewind);
|
||||||
.make-icon(plus);
|
.make-icon(plus);
|
||||||
.make-icon(podium);
|
.make-icon(podium);
|
||||||
.make-icon(primitive-dot);
|
.make-icon(primitive-dot);
|
||||||
.make-icon(primitive-square);
|
.make-icon(primitive-square);
|
||||||
.make-icon(pulse);
|
.make-icon(pulse);
|
||||||
|
.make-icon(puzzle);
|
||||||
.make-icon(question);
|
.make-icon(question);
|
||||||
.make-icon(quote);
|
.make-icon(quote);
|
||||||
.make-icon(radio-tower);
|
.make-icon(radio-tower);
|
||||||
@ -175,18 +189,22 @@
|
|||||||
.make-icon(screen-full);
|
.make-icon(screen-full);
|
||||||
.make-icon(screen-normal);
|
.make-icon(screen-normal);
|
||||||
.make-icon(search);
|
.make-icon(search);
|
||||||
|
.make-icon(search-save);
|
||||||
.make-icon(server);
|
.make-icon(server);
|
||||||
.make-icon(settings);
|
.make-icon(settings);
|
||||||
|
.make-icon(split);
|
||||||
.make-icon(squirrel);
|
.make-icon(squirrel);
|
||||||
.make-icon(star);
|
.make-icon(star);
|
||||||
.make-icon(star-add);
|
.make-icon(star-add);
|
||||||
.make-icon(star-delete);
|
.make-icon(star-delete);
|
||||||
|
.make-icon(steps);
|
||||||
.make-icon(stop);
|
.make-icon(stop);
|
||||||
.make-icon(sync);
|
.make-icon(sync);
|
||||||
.make-icon(tag);
|
.make-icon(tag);
|
||||||
.make-icon(tag-add);
|
.make-icon(tag-add);
|
||||||
.make-icon(tag-remove);
|
.make-icon(tag-remove);
|
||||||
.make-icon(telescope);
|
.make-icon(telescope);
|
||||||
|
.make-icon(terminal);
|
||||||
.make-icon(three-bars);
|
.make-icon(three-bars);
|
||||||
.make-icon(tools);
|
.make-icon(tools);
|
||||||
.make-icon(triangle-down);
|
.make-icon(triangle-down);
|
||||||
|
Binary file not shown.
@ -14,6 +14,7 @@
|
|||||||
@book: "\f007";
|
@book: "\f007";
|
||||||
@bookmark: "\f07b";
|
@bookmark: "\f07b";
|
||||||
@broadcast: "\f048";
|
@broadcast: "\f048";
|
||||||
|
@browser: "\f0c5";
|
||||||
@bug: "\f091";
|
@bug: "\f091";
|
||||||
@calendar: "\f068";
|
@calendar: "\f068";
|
||||||
@check: "\f03a";
|
@check: "\f03a";
|
||||||
@ -33,6 +34,7 @@
|
|||||||
@comment-add: "\f06f";
|
@comment-add: "\f06f";
|
||||||
@comment-discussion: "\f04f";
|
@comment-discussion: "\f04f";
|
||||||
@credit-card: "\f045";
|
@credit-card: "\f045";
|
||||||
|
@dash: "\f0ca";
|
||||||
@dashboard: "\f07d";
|
@dashboard: "\f07d";
|
||||||
@database: "\f096";
|
@database: "\f096";
|
||||||
@device-camera: "\f056";
|
@device-camera: "\f056";
|
||||||
@ -61,6 +63,7 @@
|
|||||||
@file-symlink-file: "\f0b0";
|
@file-symlink-file: "\f0b0";
|
||||||
@file-text: "\f011";
|
@file-text: "\f011";
|
||||||
@file-zip: "\f013";
|
@file-zip: "\f013";
|
||||||
|
@fold: "\f0cc";
|
||||||
@gear: "\f02f";
|
@gear: "\f02f";
|
||||||
@gift: "\f042";
|
@gift: "\f042";
|
||||||
@gist: "\f00e";
|
@gist: "\f00e";
|
||||||
@ -79,6 +82,7 @@
|
|||||||
@git-pull-request-abandoned: "\f090";
|
@git-pull-request-abandoned: "\f090";
|
||||||
@globe: "\f0b6";
|
@globe: "\f0b6";
|
||||||
@graph: "\f043";
|
@graph: "\f043";
|
||||||
|
@heart: "\2665";
|
||||||
@history: "\f07e";
|
@history: "\f07e";
|
||||||
@home: "\f08d";
|
@home: "\f08d";
|
||||||
@horizontal-rule: "\f070";
|
@horizontal-rule: "\f070";
|
||||||
@ -114,10 +118,14 @@
|
|||||||
@mail: "\f03b";
|
@mail: "\f03b";
|
||||||
@mail-read: "\f03c";
|
@mail-read: "\f03c";
|
||||||
@mail-reply: "\f051";
|
@mail-reply: "\f051";
|
||||||
|
@mark-facebook: "\f0ce";
|
||||||
@mark-github: "\f00a";
|
@mark-github: "\f00a";
|
||||||
@mark-github-detail: "\f093";
|
@mark-github-detail: "\f093";
|
||||||
|
@mark-google: "\f0cd";
|
||||||
@mark-twitter: "\f0ae";
|
@mark-twitter: "\f0ae";
|
||||||
|
@markdown: "\f0c9";
|
||||||
@megaphone: "\f077";
|
@megaphone: "\f077";
|
||||||
|
@mention: "\f0be";
|
||||||
@microscope: "\f089";
|
@microscope: "\f089";
|
||||||
@milestone: "\f075";
|
@milestone: "\f075";
|
||||||
@mirror-private: "\f025";
|
@mirror-private: "\f025";
|
||||||
@ -129,19 +137,26 @@
|
|||||||
@mute: "\f080";
|
@mute: "\f080";
|
||||||
@mute-video: "\f0b8";
|
@mute-video: "\f0b8";
|
||||||
@no-newline: "\f09c";
|
@no-newline: "\f09c";
|
||||||
|
@node-js: "\f0c3";
|
||||||
@octoface: "\f008";
|
@octoface: "\f008";
|
||||||
@organization: "\f037";
|
@organization: "\f037";
|
||||||
|
@package: "\f0c4";
|
||||||
@pencil: "\f058";
|
@pencil: "\f058";
|
||||||
@person: "\f018";
|
@person: "\f018";
|
||||||
@person-add: "\f01a";
|
@person-add: "\f01a";
|
||||||
@person-follow: "\f01c";
|
@person-follow: "\f01c";
|
||||||
@person-remove: "\f01b";
|
@person-remove: "\f01b";
|
||||||
@pin: "\f041";
|
@pin: "\f041";
|
||||||
|
@playback-fast-forward: "\f0bd";
|
||||||
|
@playback-pause: "\f0bb";
|
||||||
|
@playback-play: "\f0bf";
|
||||||
|
@playback-rewind: "\f0bc";
|
||||||
@plus: "\f05d";
|
@plus: "\f05d";
|
||||||
@podium: "\f0af";
|
@podium: "\f0af";
|
||||||
@primitive-dot: "\f052";
|
@primitive-dot: "\f052";
|
||||||
@primitive-square: "\f053";
|
@primitive-square: "\f053";
|
||||||
@pulse: "\f085";
|
@pulse: "\f085";
|
||||||
|
@puzzle: "\f0c0";
|
||||||
@question: "\f02c";
|
@question: "\f02c";
|
||||||
@quote: "\f063";
|
@quote: "\f063";
|
||||||
@radio-tower: "\f030";
|
@radio-tower: "\f030";
|
||||||
@ -162,18 +177,22 @@
|
|||||||
@screen-full: "\f066";
|
@screen-full: "\f066";
|
||||||
@screen-normal: "\f067";
|
@screen-normal: "\f067";
|
||||||
@search: "\f02e";
|
@search: "\f02e";
|
||||||
|
@search-save: "\f0cb";
|
||||||
@server: "\f097";
|
@server: "\f097";
|
||||||
@settings: "\f07c";
|
@settings: "\f07c";
|
||||||
|
@split: "\f0c6";
|
||||||
@squirrel: "\f0b2";
|
@squirrel: "\f0b2";
|
||||||
@star: "\f02a";
|
@star: "\f02a";
|
||||||
@star-add: "\f082";
|
@star-add: "\f082";
|
||||||
@star-delete: "\f083";
|
@star-delete: "\f083";
|
||||||
|
@steps: "\f0c7";
|
||||||
@stop: "\f08f";
|
@stop: "\f08f";
|
||||||
@sync: "\f087";
|
@sync: "\f087";
|
||||||
@tag: "\f015";
|
@tag: "\f015";
|
||||||
@tag-add: "\f054";
|
@tag-add: "\f054";
|
||||||
@tag-remove: "\f055";
|
@tag-remove: "\f055";
|
||||||
@telescope: "\f088";
|
@telescope: "\f088";
|
||||||
|
@terminal: "\f0c8";
|
||||||
@three-bars: "\f05e";
|
@three-bars: "\f05e";
|
||||||
@tools: "\f031";
|
@tools: "\f031";
|
||||||
@triangle-down: "\f05b";
|
@triangle-down: "\f05b";
|
||||||
|
2
vendor/apm
vendored
2
vendor/apm
vendored
@ -1 +1 @@
|
|||||||
Subproject commit b80ef23ce8d2a1e8b4f40eb0f89c87f32dcc3415
|
Subproject commit 3f8701bfe624de844641863391c04def9cca5c86
|
Loading…
Reference in New Issue
Block a user