Merge remote-tracking branch 'origin/master' into cj-make-package-activation-consistent

Conflicts:
	package.json
	src/package-manager.coffee
	src/text-mate-package.coffee
This commit is contained in:
probablycorey
2014-02-07 16:53:24 -08:00
72 changed files with 593 additions and 877 deletions

View File

@@ -30,7 +30,7 @@ in the proper package's repository.
* Follow the [CoffeeScript](#coffeescript-styleguide),
[JavaScript](https://github.com/styleguide/javascript),
and [CSS](https://github.com/styleguide/css) styleguides
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine/)
* Include thoughtfully worded [Jasmine](http://pivotal.github.com/jasmine)
specs
* Avoid placing files in `vendor`. 3rd-party packages should be added as a
`package.json` dependency.
@@ -61,3 +61,32 @@ in the proper package's repository.
* Set parameter defaults without spaces around the equal sign
* `clear = (count=1) ->` instead of `clear = (count = 1) ->`
## Documentation Styleguide
* Use [TomDoc](http://tomdoc.org).
* Use [Markdown](https://daringfireball.net/projects/markdown).
* Reference classes with `{ClassName}` style notation.
* Reference methods with `{ClassName.methodName}` style notation.
* Delegate to comments elsewhere with `{Delegates to: ClassName.methodName}`
style notation.
### Example
```coffee
# Public: Disable the package with the given name.
#
# This method emits multiple events:
#
# * `package-will-be-disabled` - before the package is disabled.
# * `package-disabled` - after the package is disabled.
#
# name - The {String} name of the package to disable.
# options - The {Object} with disable options (default: {}):
# :trackTime - `true` to track the amount of time disabling took.
# :ignoreErrors - `true` to catch and ignore errors thrown.
# callback - The {Function} to call after the package has been disabled.
#
# Returns `undefined`.
disablePackage: (name, options, callback) ->
```

View File

@@ -7,7 +7,7 @@
},
"dependencies": {
"async": "~0.2.9",
"biscotto": "0.2.0",
"biscotto": "0.6.0",
"first-mate": "1.x",
"formidable": "~1.0.14",
"fs-plus": "1.x",

View File

@@ -21,7 +21,6 @@ module.exports = (grunt) ->
cp 'atom.sh', path.join(appDir, 'atom.sh')
cp 'package.json', path.join(appDir, 'package.json')
cp 'apm', path.join(appDir, 'apm')
packageDirectories = []
nonPackageDirectories = [
@@ -47,8 +46,12 @@ module.exports = (grunt) ->
path.join('less', 'dist')
path.join('less', 'test')
path.join('bootstrap', 'docs')
path.join('bootstrap', 'examples')
path.join('spellchecker', 'vendor')
path.join('xmldom', 'test')
path.join('jasmine-reporters', 'ext')
path.join('build', 'Release', 'obj.target')
path.join('build', 'Release', '.deps')
path.join('vendor', 'apm')
path.join('resources', 'mac')
path.join('resources', 'win')
@@ -64,6 +67,7 @@ module.exports = (grunt) ->
cp 'spec', path.join(appDir, 'spec')
cp 'src', path.join(appDir, 'src'), filter: /.+\.(cson|coffee)$/
cp 'static', path.join(appDir, 'static')
cp 'apm', path.join(appDir, 'apm'), filter: nodeModulesFilter
if process.platform is 'darwin'
grunt.file.recurse path.join('resources', 'mac'), (sourcePath, rootDirectory, subDirectory='', filename) ->

View File

@@ -112,14 +112,16 @@ namespaces: `core` and `editor`.
### Quick Personal Hacks
### user.coffee
### init.coffee
When Atom finishes loading, it will evaluate _user.coffee_ in your _~/.atom_
When Atom finishes loading, it will evaluate _init.coffee_ in your _~/.atom_
directory, giving you a chance to run arbitrary personal CoffeeScript code to
make customizations. You have full access to Atom's API from code in this file.
If customizations become extensive, consider [creating a
package][create-a-package].
This file can also be named _init.js_ and contain JavaScript code.
### styles.css
If you want to apply quick-and-dirty personal styling changes without creating

View File

@@ -1,63 +0,0 @@
## Atom Documentation Format
This document describes our documentation format, which is markdown with
a few rules.
### Philosophy
1. Method and argument names **should** clearly communicate its use.
1. Use documentation to enhance and not correct method/argument names.
#### Basic
In some cases all that's required is a single line. **Do not** feel
obligated to write more because we have a format.
```markdown
# Private: Returns the number of pixels from the top of the screen.
```
* **Each method should declare whether it's public or private by using `Public:`
or `Private:`** prefix.
* Following the colon, there should be a short description (that isn't redundant with the
method name).
* Documentation should be hard wrapped to 80 columns.
### Public vs Private
If a method is public it can be used by other classes (and possibly by
the public API). The appropriate steps should be taken to minimize the impact
when changing public methods. In some cases that might mean adding an
appropriate release note. In other cases it might mean doing the legwork to
ensure all affected packages are updated.
#### Complex
For complex methods it's necessary to explain exactly what arguments
are required and how different inputs effect the operation of the
function.
The idea is to communicate things that the API user might not know about,
so repeating information that can be gleaned from the method or argument names
is not useful.
```markdown
# Private: Determine the accelerator for a given command.
#
# * command:
# The name of the command.
# * keystrokesByCommand:
# An {Object} whose keys are commands and the values are Arrays containing
# the keystrokes.
# * options:
# + accelerators:
# Boolean to determine whether accelerators should be shown.
#
# Returns a String containing the keystroke in a format that can be interpreted
# by atom shell to provide nice icons where available.
#
# Raises an Exception if no window is available.
```
* Use curly brackets `{}` to provide links to other classes.
* Use `+` for the options list.

14
dot-atom/init.coffee Normal file
View File

@@ -0,0 +1,14 @@
# Your init script
#
# Atom will evaluate this file each time a new window is opened. It is run
# after packages are loaded/activated and after the previous editor state
# has been restored.
#
# An example hack to make opened Markdown files always be soft wrapped:
#
# path = require 'path'
#
# atom.workspaceView.eachEditorView (editorView) ->
# editor = editorView.getEditor()
# if path.extname(editor.getPath()) is '.md'
# editor.setSoftWrap(true)

View File

@@ -1,9 +1,13 @@
# User keymap
# Your keymap
#
# Atom keymaps work similarly to stylesheets. Just as stylesheets use selectors
# to apply styles to elements, Atom keymaps use selectors to associate
# keystrokes with events in specific contexts. Here's a small example, excerpted
# from Atom's built-in keymaps:
# keystrokes with events in specific contexts.
#
# You can create a new keybinding in this file by typing "key" and then hitting
# tab.
#
# Here's an example taken from Atom's built-in keymap:
#
# '.editor':
# 'enter': 'editor:newline'
@@ -11,3 +15,4 @@
# 'body':
# 'ctrl-P': 'core:move-up'
# 'ctrl-p': 'core:move-down'
#

View File

@@ -3,7 +3,7 @@
# 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
# 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:

View File

@@ -1 +0,0 @@
# For more on how to configure atom open `~/github/atom/docs/configuring-and-extending.md`

View File

@@ -4,7 +4,6 @@ module.exports =
_: require 'underscore-plus'
BufferedNodeProcess: require '../src/buffered-node-process'
BufferedProcess: require '../src/buffered-process'
ConfigObserver: require '../src/config-observer'
Directory: require '../src/directory'
File: require '../src/file'
fs: require 'fs-plus'

View File

@@ -9,6 +9,7 @@
{ type: 'separator' }
{ label: 'Preferences...', command: 'application:show-settings' }
{ label: 'Open Your Config', command: 'application:open-your-config' }
{ label: 'Open Your Init Script', command: 'application:open-your-init-script' }
{ 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' }

View File

@@ -29,7 +29,7 @@
"fs-plus": "1.x",
"fstream": "0.1.24",
"fuzzaldrin": "1.x",
"git-utils": "0.34.0",
"git-utils": "1.x",
"guid": "0.0.10",
"jasmine-tagged": "1.x",
"mkdirp": "0.3.5",
@@ -43,7 +43,7 @@
"pegjs": "0.8.0",
"property-accessors": "1.x",
"q": "1.0.x",
"scandal": "0.13.0",
"scandal": "0.14.0",
"season": "1.x",
"semver": "1.1.4",
"serializable": "1.x",
@@ -88,12 +88,12 @@
"markdown-preview": "0.25.1",
"metrics": "0.25.0",
"package-generator": "0.26.0",
"release-notes": "0.17.0",
"release-notes": "0.18.0",
"settings-view": "0.71.0",
"snippets": "0.26.0",
"spell-check": "0.22.0",
"spell-check": "0.23.0",
"status-bar": "0.32.0",
"styleguide": "0.22.0",
"styleguide": "0.23.0",
"symbols-view": "0.32.0",
"tabs": "0.19.0",
"terminal": "0.27.0",
@@ -105,39 +105,39 @@
"welcome": "0.4.0",
"whitespace": "0.11.0",
"wrap-guide": "0.13.0",
"language-c": "0.2.0",
"language-c": "0.4.0",
"language-clojure": "0.1.0",
"language-coffee-script": "0.6.0",
"language-css": "0.2.0",
"language-coffee-script": "0.7.0",
"language-css": "0.3.0",
"language-gfm": "0.13.0",
"language-git": "0.3.0",
"language-go": "0.2.0",
"language-html": "0.2.0",
"language-git": "0.4.0",
"language-go": "0.3.0",
"language-html": "0.3.0",
"language-hyperlink": "0.3.0",
"language-java": "0.2.0",
"language-javascript": "0.5.0",
"language-json": "0.2.0",
"language-less": "0.1.0",
"language-make": "0.1.0",
"language-mustache": "0.1.0",
"language-objective-c": "0.2.0",
"language-pegjs": "0.1.0",
"language-perl": "0.2.0",
"language-php": "0.3.0",
"language-property-list": "0.2.0",
"language-puppet": "0.2.0",
"language-python": "0.2.0",
"language-ruby": "0.8.0",
"language-ruby-on-rails": "0.4.0",
"language-sass": "0.3.0",
"language-shellscript": "0.2.0",
"language-source": "0.2.0",
"language-sql": "0.2.0",
"language-text": "0.2.0",
"language-todo": "0.2.0",
"language-java": "0.3.0",
"language-javascript": "0.6.0",
"language-json": "0.3.0",
"language-less": "0.2.0",
"language-make": "0.2.0",
"language-mustache": "0.2.0",
"language-objective-c": "0.3.0",
"language-pegjs": "0.2.0",
"language-perl": "0.3.0",
"language-php": "0.4.0",
"language-property-list": "0.3.0",
"language-puppet": "0.3.0",
"language-python": "0.3.0",
"language-ruby": "0.9.0",
"language-ruby-on-rails": "0.5.0",
"language-sass": "0.4.0",
"language-shellscript": "0.3.0",
"language-source": "0.3.0",
"language-sql": "0.3.0",
"language-text": "0.3.0",
"language-todo": "0.3.0",
"language-toml": "0.7.0",
"language-xml": "0.2.0",
"language-yaml": "0.1.0"
"language-xml": "0.3.0",
"language-yaml": "0.2.0"
},
"private": true,
"scripts": {

View File

@@ -6,8 +6,7 @@ sourceMaps = {}
formatStackTrace = (stackTrace) ->
return stackTrace unless stackTrace
jasminePath = require.resolve('../vendor/jasmine')
jasminePattern = new RegExp("\\(#{_.escapeRegExp(jasminePath)}:\\d+:\\d+\\)\\s*$")
jasminePattern = /^\s*at\s+.*\(?.*\/jasmine(-[^\/]*)?\.js:\d+:\d+\)?\s*$/
convertedLines = []
for line in stackTrace.split('\n')
convertedLines.push(line) unless jasminePattern.test(line)

View File

@@ -220,6 +220,8 @@ describe "Config", ->
expect(fs.existsSync(path.join(atom.config.configDirPath, 'packages'))).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, 'init.coffee'))).toBeTruthy()
expect(fs.isFileSync(path.join(atom.config.configDirPath, 'styles.css'))).toBeTruthy()
describe ".loadUserConfig()", ->
beforeEach ->

View File

@@ -21,10 +21,6 @@ module.exports.runSpecSuite = (specSuite, logFile, logErrors=true) ->
print: (str) ->
log(str)
onComplete: (runner) ->
log('\n')
timeReporter.logLongestSuites 10, (line) -> log("#{line}\n")
log('\n')
timeReporter.logLongestSpecs 10, (line) -> log("#{line}\n")
fs.closeSync(logStream) if logStream?
atom.exit(runner.results().failedCount > 0 ? 1 : 0)
else

View File

@@ -11,35 +11,6 @@ describe "SpacePen extensions", ->
parent = $$ -> @div()
parent.append(view)
describe "View.observeConfig(keyPath, callback)", ->
observeHandler = null
beforeEach ->
observeHandler = jasmine.createSpy("observeHandler")
view.observeConfig "foo.bar", observeHandler
expect(view.hasParent()).toBeTruthy()
it "observes the keyPath and cancels the subscription when `.unobserveConfig()` is called", ->
expect(observeHandler).toHaveBeenCalledWith(undefined)
observeHandler.reset()
atom.config.set("foo.bar", "hello")
expect(observeHandler).toHaveBeenCalledWith("hello", previous: undefined)
observeHandler.reset()
view.unobserveConfig()
atom.config.set("foo.bar", "goodbye")
expect(observeHandler).not.toHaveBeenCalled()
it "unobserves when the view is removed", ->
observeHandler.reset()
parent.remove()
atom.config.set("foo.bar", "hello")
expect(observeHandler).not.toHaveBeenCalled()
describe "View.subscribe(eventEmitter, eventName, callback)", ->
[emitter, eventHandler] = []

View File

@@ -7,8 +7,8 @@ Q = require 'q'
CSON = require 'season'
{Emitter} = require 'emissary'
### Internal: Loads and resolves packages. ###
# Loads and activates a package's main module and resources such as
# stylesheets, keymaps, grammar, editor properties, and menus.
module.exports =
class AtomPackage extends Package
Emitter.includeInto(this)

View File

@@ -43,11 +43,11 @@ class Atom extends Model
@loadOrCreate: (mode) ->
@deserialize(@loadState(mode)) ? new this({mode, version: @getVersion()})
# Private: Deserializes the Atom environment from a state object
# Deserializes the Atom environment from a state object
@deserialize: (state) ->
new this(state) if state?.version is @getVersion()
# Private: Loads and returns the serialized state corresponding to this window
# Loads and returns the serialized state corresponding to this window
# if it exists; otherwise returns undefined.
@loadState: (mode) ->
statePath = @getStatePath(mode)
@@ -65,7 +65,7 @@ class Atom extends Model
catch error
console.warn "Error parsing window state: #{statePath} #{error.stack}", error
# Private: Returns the path where the state for the current window will be
# Returns the path where the state for the current window will be
# located if it exists.
@getStatePath: (mode) ->
switch mode
@@ -82,19 +82,19 @@ class Atom extends Model
else
null
# Private: Get the directory path to Atom's configuration area.
# Get the directory path to Atom's configuration area.
#
# Returns the absolute path to ~/.atom
@getConfigDirPath: ->
@configDirPath ?= fs.absolute('~/.atom')
# Private: Get the path to Atom's storage directory.
# Get the path to Atom's storage directory.
#
# Returns the absolute path to ~/.atom/storage
@getStorageDirPath: ->
@storageDirPath ?= path.join(@getConfigDirPath(), 'storage')
# Private: Returns the load settings hash associated with the current window.
# Returns the load settings hash associated with the current window.
@getLoadSettings: ->
@loadSettings ?= JSON.parse(decodeURIComponent(location.search.substr(14)))
cloned = _.deepClone(@loadSettings)
@@ -105,21 +105,20 @@ class Atom extends Model
@getCurrentWindow().loadSettings.windowState = value
cloned
# Private:
@getCurrentWindow: ->
remote.getCurrentWindow()
# Private: Get the version of the Atom application.
# Get the version of the Atom application.
@getVersion: ->
@version ?= @getLoadSettings().appVersion
# Private: Determine whether the current version is an official release.
# Determine whether the current version is an official release.
@isReleasedVersion: ->
not /\w{7}/.test(@getVersion()) # Check if the release is a 7-character SHA prefix
workspaceViewParentSelector: 'body'
# Private: Call .loadOrCreate instead
# Call .loadOrCreate instead
constructor: (@state) ->
{@mode} = @state
DeserializerManager = require './deserializer-manager'
@@ -175,7 +174,6 @@ class Atom extends Model
# Deprecated: Callers should be converted to use atom.deserializers
registerRepresentationClasses: ->
# Private:
setBodyPlatformClass: ->
document.body.classList.add("platform-#{process.platform}")
@@ -211,7 +209,6 @@ class Atom extends Model
else
@center()
# Private:
restoreWindowDimensions: ->
workAreaSize = screen.getPrimaryDisplay().workAreaSize
windowDimensions = @state.windowDimensions ? {}
@@ -220,7 +217,6 @@ class Atom extends Model
windowDimensions.width ?= initialSize?.width ? Math.min(workAreaSize.width, 1024)
@setWindowDimensions(windowDimensions)
# Private:
storeWindowDimensions: ->
@state.windowDimensions = @getWindowDimensions()
@@ -230,12 +226,10 @@ class Atom extends Model
getLoadSettings: ->
@constructor.getLoadSettings()
# Private:
deserializeProject: ->
Project = require './project'
@project ?= @deserializers.deserialize(@project) ? new Project(path: @getLoadSettings().initialPath)
# Private:
deserializeWorkspaceView: ->
Workspace = require './workspace'
WorkspaceView = require './workspace-view'
@@ -243,18 +237,16 @@ class Atom extends Model
@workspaceView = new WorkspaceView(@workspace)
$(@workspaceViewParentSelector).append(@workspaceView)
# Private:
deserializePackageStates: ->
@packages.packageStates = @state.packageStates ? {}
delete @state.packageStates
# Private:
deserializeEditorWindow: ->
@deserializePackageStates()
@deserializeProject()
@deserializeWorkspaceView()
# Private: Call this method when establishing a real application window.
# Call this method when establishing a real application window.
startEditorWindow: ->
CommandInstaller = require './command-installer'
resourcePath = atom.getLoadSettings().resourcePath
@@ -283,7 +275,6 @@ class Atom extends Model
@displayWindow()
# Private:
unloadEditorWindow: ->
return if not @project and not @workspaceView
@@ -299,11 +290,9 @@ class Atom extends Model
@keymap.destroy()
@windowState = null
# Private:
loadThemes: ->
@themes.load()
# Private:
watchThemes: ->
@themes.on 'reloaded', =>
# Only reload stylesheets from non-theme packages
@@ -316,31 +305,32 @@ class Atom extends Model
# Calling this method without an options parameter will open a prompt to pick
# a file/folder to open in the new window.
#
# * options
# * pathsToOpen: A string array of paths to open
# options - An {Object} with the following keys:
# :pathsToOpen - An {Array} of {String} paths to open.
open: (options) ->
ipc.sendChannel('open', options)
# Public: Open a confirm dialog.
#
# ## Example:
# ```coffeescript
# ## Example
#
# ```coffee
# atom.confirm
# message: 'How you feeling?'
# detailedMessage: 'Be honest.'
# buttons:
# Good: -> window.alert('good to hear')
# Bad: -> window.alert('bummer')
# message: 'How you feeling?'
# detailedMessage: 'Be honest.'
# buttons:
# Good: -> window.alert('good to hear')
# Bad: -> window.alert('bummer')
# ```
#
# * options:
# + message: The string message to display.
# + detailedMessage: The string detailed message to display.
# + buttons: Either an array of strings or an object where the values
# are callbacks to invoke when clicked.
# options - An {Object} with the following keys:
# :message - The {String} message to display.
# :detailedMessage - The {String} detailed message to display.
# :buttons - Either an array of strings or an object where keys are
# button names and the values are callbacks to invoke when
# clicked.
#
# Returns the chosen index if buttons was an array or the return of the
# callback if buttons was an object.
# Returns the chosen button index {Number} if the buttons option was an array.
confirm: ({message, detailedMessage, buttons}={}) ->
buttons ?= {}
if _.isArray(buttons)
@@ -361,11 +351,9 @@ class Atom extends Model
callback = buttons[buttonLabels[chosen]]
callback?()
# Private:
showSaveDialog: (callback) ->
callback(showSaveDialogSync())
# Private:
showSaveDialogSync: (defaultPath) ->
defaultPath ?= @project?.getPath()
currentWindow = @getCurrentWindow()
@@ -398,10 +386,16 @@ class Atom extends Model
ipc.sendChannel('call-window-method', 'hide')
# Public: Set the size of current window.
#
# width - The {Number} of pixels.
# height - The {Number} of pixels.
setSize: (width, height) ->
ipc.sendChannel('call-window-method', 'setSize', width, height)
# Public: Set the position of current window.
#
# x - The {Number} of pixels.
# y - The {Number} of pixels.
setPosition: (x, y) ->
ipc.sendChannel('call-window-method', 'setPosition', x, y)
@@ -409,7 +403,7 @@ class Atom extends Model
center: ->
ipc.sendChannel('call-window-method', 'center')
# Private: Schedule the window to be shown and focused on the next tick.
# Schedule the window to be shown and focused on the next tick.
#
# This is done in a next tick to prevent a white flicker from occurring
# if called synchronously.
@@ -423,7 +417,6 @@ class Atom extends Model
close: ->
@getCurrentWindow().close()
# Private:
exit: (status) ->
app = remote.require('app')
app.exit(status)
@@ -473,7 +466,6 @@ class Atom extends Model
getConfigDirPath: ->
@constructor.getConfigDirPath()
# Private:
saveSync: ->
stateString = JSON.stringify(@state)
if statePath = @constructor.getStatePath(@mode)
@@ -491,11 +483,9 @@ class Atom extends Model
getWindowLoadTime: ->
@loadTime
# Private:
crashMainProcess: ->
remote.process.crash()
# Private:
crashRenderProcess: ->
process.crash()
@@ -504,9 +494,12 @@ class Atom extends Model
shell.beep() if @config.get('core.audioBeep')
@workspaceView.trigger 'beep'
# Private:
getUserInitScriptPath: ->
initScriptPath = fs.resolve(@getConfigDirPath(), 'init', ['js', 'coffee'])
initScriptPath ? path.join(@getConfigDirPath(), 'init.coffee')
requireUserInitScript: ->
if userInitScriptPath = fs.resolve(@getConfigDirPath(), 'user', ['js', 'coffee'])
if userInitScriptPath = @getUserInitScriptPath()
try
require userInitScriptPath
catch error
@@ -516,6 +509,9 @@ class Atom extends Model
#
# The globals will be set on the `window` object and removed after the
# require completes.
#
# id - The {String} module name or path.
# globals - An {Object} to set as globals during require (default: {})
requireWithGlobals: (id, globals={}) ->
existingGlobals = {}
for key, value of globals

View File

@@ -3,7 +3,7 @@ ipc = require 'ipc'
Menu = require 'menu'
_ = require 'underscore-plus'
# Private: Used to manage the global application menu.
# Used to manage the global application menu.
#
# It's created by {AtomApplication} upon instantiation and used to add, remove
# and maintain the state of all menu items.
@@ -29,7 +29,7 @@ class ApplicationMenu
@menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(@menu)
# Private: Flattens the given menu and submenu items into an single Array.
# Flattens the given menu and submenu items into an single Array.
#
# * menu:
# A complete menu configuration object for atom-shell's menu API.
@@ -42,7 +42,7 @@ class ApplicationMenu
items = items.concat(@flattenMenuItems(item.submenu)) if item.submenu
items
# Private: Flattens the given menu template into an single Array.
# Flattens the given menu template into an single Array.
#
# * template:
# An object describing the menu item.
@@ -64,7 +64,7 @@ class ApplicationMenu
for item in @flattenMenuItems(@menu)
item.enabled = enable if item.metadata?['windowSpecific']
# Private: Replaces VERSION with the current version.
# Replaces VERSION with the current version.
substituteVersion: (template) ->
if (item = _.find(@flattenMenuTemplate(template), (i) -> i.label == 'VERSION'))
item.label = "Version #{@version}"
@@ -79,7 +79,7 @@ class ApplicationMenu
if (item = _.find(@flattenMenuItems(@menu), (i) -> i.label == 'Check for Update'))
item.visible = visible
# Private: Default list of menu items.
# Default list of menu items.
#
# Returns an Array of menu item Objects.
getDefaultTemplate: ->
@@ -93,7 +93,7 @@ class ApplicationMenu
]
]
# Private: Combines a menu template with the appropriate keystroke.
# Combines a menu template with the appropriate keystroke.
#
# * template:
# An Object conforming to atom-shell's menu api but lacking accelerator and
@@ -113,7 +113,7 @@ class ApplicationMenu
@translateTemplate(item.submenu, keystrokesByCommand) if item.submenu
template
# Private: Determine the accelerator for a given command.
# Determine the accelerator for a given command.
#
# * command:
# The name of the command.

View File

@@ -22,7 +22,7 @@ socketPath =
else
path.join(os.tmpdir(), 'atom.sock')
# Private: The application's singleton class.
# The application's singleton class.
#
# It's the entry point into the Atom application and maintains the global state
# of the application.
@@ -77,7 +77,7 @@ class AtomApplication
@openWithOptions(options)
# Private: Opens a new window based on the options provided.
# Opens a new window based on the options provided.
openWithOptions: ({pathsToOpen, urlsToOpen, test, pidToKillWhenClosed, devMode, newWindow, specDirectory, logFile}) ->
if test
@runSpecs({exitWhenDone: true, @resourcePath, specDirectory, logFile})
@@ -98,7 +98,7 @@ class AtomApplication
@windows.push window
@applicationMenu?.enableWindowSpecificItems(true)
# Private: Creates server to listen for additional atom application launches.
# Creates server to listen for additional atom application launches.
#
# You can run the atom command multiple times, but after the first launch
# the other launches will just pass their information to this server and then
@@ -113,11 +113,11 @@ class AtomApplication
server.listen socketPath
server.on 'error', (error) -> console.error 'Application server failed', error
# Private: Configures required javascript environment flags.
# Configures required javascript environment flags.
setupJavaScriptArguments: ->
app.commandLine.appendSwitch 'js-flags', '--harmony_collections --harmony-proxies'
# Private: Enable updates unless running from a local build of Atom.
# Enable updates unless running from a local build of Atom.
setupAutoUpdater: ->
autoUpdater.setFeedUrl "https://atom.io/api/updates?version=#{@version}"
@@ -165,7 +165,7 @@ class AtomApplication
autoUpdater.checkForUpdates()
# Private: Registers basic application commands, non-idempotent.
# Registers basic application commands, non-idempotent.
handleEvents: ->
@on 'application:about', -> Menu.sendActionToFirstResponder('orderFrontStandardAboutPanel:')
@on 'application:run-all-specs', -> @runSpecs(exitWhenDone: false, resourcePath: global.devResourcePath)
@@ -189,6 +189,7 @@ class AtomApplication
@openPathOnEvent('application:show-settings', 'atom://config')
@openPathOnEvent('application:open-your-config', 'atom://.atom/config')
@openPathOnEvent('application:open-your-init-script', 'atom://.atom/init-script')
@openPathOnEvent('application:open-your-keymap', 'atom://.atom/keymap')
@openPathOnEvent('application:open-your-snippets', 'atom://.atom/snippets')
@openPathOnEvent('application:open-your-stylesheet', 'atom://.atom/stylesheet')
@@ -262,7 +263,7 @@ class AtomApplication
else
@openPath({pathToOpen})
# Private: Returns the {AtomWindow} for the given path.
# Returns the {AtomWindow} for the given path.
windowForPath: (pathToOpen) ->
for atomWindow in @windows
return atomWindow if atomWindow.containsPath(pathToOpen)
@@ -350,7 +351,7 @@ class AtomApplication
console.log("Killing process #{pid} failed: #{error.code}")
delete @pidsToOpenWindows[pid]
# Private: Open an atom:// url.
# Open an atom:// url.
#
# The host of the URL being opened is assumed to be the package name
# responsible for opening the URL. A new window will be created with
@@ -382,7 +383,7 @@ class AtomApplication
else
console.log "Opening unknown url: #{urlToOpen}"
# Private: Opens up a new {AtomWindow} to run specs within.
# Opens up a new {AtomWindow} to run specs within.
#
# * options
# + exitWhenDone:
@@ -413,7 +414,7 @@ class AtomApplication
isSpec = true
new AtomWindow({bootstrapScript, @resourcePath, isSpec})
# Private: Opens a native dialog to prompt the user for a path.
# Opens a native dialog to prompt the user for a path.
#
# Once paths are selected, they're opened in a new or existing {AtomWindow}s.
#

View File

@@ -3,7 +3,7 @@ fs = require 'fs-plus'
path = require 'path'
protocol = require 'protocol'
# Private: Handles requests with 'atom' protocol.
# Handles requests with 'atom' protocol.
#
# It's created by {AtomApplication} upon instantiation, and is used to create a
# custom resource loader by adding the 'atom' custom protocol.
@@ -18,7 +18,7 @@ class AtomProtocolHandler
@registerAtomProtocol()
# Private: Creates the 'atom' custom protocol handler.
# Creates the 'atom' custom protocol handler.
registerAtomProtocol: ->
protocol.registerProtocol 'atom', (request) =>
relativePath = path.normalize(request.url.substr(7))

View File

@@ -9,7 +9,6 @@ fs = require 'fs'
url = require 'url'
_ = require 'underscore-plus'
# Private:
module.exports =
class AtomWindow
@iconPath: path.resolve(__dirname, '..', '..', 'resources', 'atom.png')

View File

@@ -1,6 +1,5 @@
Menu = require 'menu'
# Private:
module.exports =
class ContextMenu
constructor: (template, browserWindow) ->
@@ -8,7 +7,7 @@ class ContextMenu
menu = Menu.buildFromTemplate(template)
menu.popup(browserWindow)
# Private: It's necessary to build the event handlers in this process, otherwise
# It's necessary to build the event handlers in this process, otherwise
# closures are drug across processes and failed to be garbage collected
# appropriately.
createClickHandlers: (template) ->

View File

@@ -12,30 +12,27 @@ class BufferedProcess
process: null
killed: false
# Executes the given executable.
# Public: Executes the given executable.
#
# * options
# + command:
# The path to the executable to execute.
# + args:
# The array of arguments to pass to the script (optional).
# + options:
# The options Object to pass to Node's `ChildProcess.spawn` (optional).
# + stdout:
# The callback that receives a single argument which contains the
# standard output of the script. The callback is called as data is
# received but it's buffered to ensure only complete lines are passed
# until the source stream closes. After the source stream has closed
# all remaining data is sent in a final call (optional).
# + stderr:
# The callback that receives a single argument which contains the
# standard error of the script. The callback is called as data is
# received but it's buffered to ensure only complete lines are passed
# until the source stream closes. After the source stream has closed
# all remaining data is sent in a final call (optional).
# + exit:
# The callback which receives a single argument containing the exit
# status (optional).
# options - An {Object} with the following keys:
# :command - The {String} command to execute.
# :args - The {String}} of arguments to pass to the script (optional).
# :options - The options {Object} to pass to Node's `ChildProcess.spawn`
# (optional).
# :stdout - The callback that receives a single argument which contains the
# standard output of the script. The callback is called as data is
# received but it's buffered to ensure only complete lines are
# passed until the source stream closes. After the source stream
# has closed all remaining data is sent in a final call
# (optional).
# :stderr - The callback that receives a single argument which contains the
# standard error of the script. The callback is called as data is
# received but it's buffered to ensure only complete lines are
# passed until the source stream closes. After the source stream
# has closed all remaining data is sent in a final call
# (optional).
# :exit - The callback which receives a single argument containing the exit
# status (optional).
constructor: ({command, args, options, stdout, stderr, exit}={}) ->
options ?= {}
@process = ChildProcess.spawn(command, args, options)
@@ -68,7 +65,7 @@ class BufferedProcess
processExited = true
triggerExitCallback()
# Private: Helper method to pass data line by line.
# Helper method to pass data line by line.
#
# * stream:
# The Stream to read from.
@@ -93,7 +90,7 @@ class BufferedProcess
onLines(buffered) if buffered.length > 0
onDone()
# Public: Terminates the process.
# Public: Terminate the process.
kill: ->
@killed = true
@process.kill()

View File

@@ -11,7 +11,7 @@ class Clipboard
# Creates an `md5` hash of some text.
#
# * text: A {String} to hash.
# text - A {String} to hash.
#
# Returns a hashed {String}.
md5: (text) ->
@@ -22,8 +22,8 @@ class Clipboard
# The metadata associated with the text is available by calling
# {.readWithMetadata}.
#
# * text: A {String} to store.
# * metadata: An {Object} of additional info to associate with the text.
# text - The {String} to store.
# metadata - The additional info to associate with the text.
write: (text, metadata) ->
@signatureForMetadata = @md5(text)
@metadata = metadata
@@ -38,8 +38,9 @@ class Clipboard
# Public: Read the text from the clipboard and return both the text and the
# associated metadata.
#
# Returns an {Object} with a `text` key and a `metadata` key if it has
# associated metadata.
# Returns an {Object} with the following keys:
# :text - The {String} clipboard text.
# :metadata - The metadata stored by an earlier call to {.write}.
readWithMetadata: ->
text = @read()
if @signatureForMetadata is @md5(text)

View File

@@ -1,12 +0,0 @@
Mixin = require 'mixto'
module.exports =
class ConfigObserver extends Mixin
observeConfig: (keyPath, args...) ->
@configSubscriptions ?= {}
@configSubscriptions[keyPath] = atom.config.observe(keyPath, args...)
unobserveConfig: ->
if @configSubscriptions?
subscription.off() for keyPath, subscription of @configSubscriptions
@configSubscriptions = null

View File

@@ -10,12 +10,12 @@ pathWatcher = require 'pathwatcher'
#
# An instance of this class is always available as the `atom.config` global.
#
# ### Best practices
# ## Best practices
#
# * Create your own root keypath using your package's name.
# * Don't depend on (or write to) configuration keys outside of your keypath.
#
# ### Example
# ## Example
#
# ```coffeescript
# atom.config.set('myplugin.key', 'value')
@@ -26,18 +26,14 @@ module.exports =
class Config
Emitter.includeInto(this)
defaultSettings: null
settings: null
configFileHasErrors: null
# Private: Created during initialization, available as `global.config`
# Created during initialization, available as `atom.config`
constructor: ({@configDirPath, @resourcePath}={}) ->
@defaultSettings = {}
@settings = {}
@configFileHasErrors = false
@configFilePath = fs.resolve(@configDirPath, 'config', ['json', 'cson'])
@configFilePath ?= path.join(@configDirPath, 'config.cson')
# Private:
initializeConfigDirectory: (done) ->
return if fs.existsSync(@configDirPath)
@@ -54,13 +50,11 @@ class Config
queue.push({sourcePath, destinationPath})
fs.traverseTree(templateConfigDirPath, onConfigDirFile, (path) -> true)
# Private:
load: ->
@initializeConfigDirectory()
@loadUserConfig()
@observeUserConfig()
# Private:
loadUserConfig: ->
unless fs.existsSync(@configFilePath)
fs.makeTreeSync(path.dirname(@configFilePath))
@@ -76,17 +70,14 @@ class Config
console.error "Failed to load user config '#{@configFilePath}'", e.message
console.error e.stack
# Private:
observeUserConfig: ->
@watchSubscription ?= pathWatcher.watch @configFilePath, (eventType) =>
@loadUserConfig() if eventType is 'change' and @watchSubscription?
# Private:
unobserveUserConfig: ->
@watchSubscription?.close()
@watchSubscription = null
# Private:
setDefaults: (keyPath, defaults) ->
keys = keyPath.split('.')
hash = @defaultSettings
@@ -204,6 +195,9 @@ class Config
# options - An optional {Object} containing the `callNow` key.
# callback - The {Function} that fires when the. It is given a single argument, `value`,
# which is the new value of `keyPath`.
#
# Returns an {Object} with the following keys:
# :off - A {Function} that unobserves the `keyPath` with called.
observe: (keyPath, options={}, callback) ->
if _.isFunction(options)
callback = options
@@ -229,12 +223,10 @@ class Config
unobserve: (keyPath) ->
@off("updated.#{keyPath.replace(/\./, '-')}")
# Private:
update: ->
return if @configFileHasErrors
@save()
@emit 'updated'
# Private:
save: ->
CSON.writeFileSync(@configFilePath, @settings)

View File

@@ -9,7 +9,6 @@ remote = require 'remote'
# global.
module.exports =
class ContextMenuManager
# Private:
constructor: (@devMode=false) ->
@definitions = {}
@devModeDefinitions = {}
@@ -25,11 +24,11 @@ class ContextMenuManager
# Public: Creates menu definitions from the object specified by the menu
# cson API.
#
# * name: The path of the file that contains the menu definitions.
# * object: The 'context-menu' object specified in the menu cson API.
# * options:
# + devMode - Determines whether the entries should only be shown when
# the window is in dev mode.
# name - The path of the file that contains the menu definitions.
# object - The 'context-menu' object specified in the menu cson API.
# options - An {Object} with the following keys:
# :devMode - Determines whether the entries should only be shown when
# the window is in dev mode.
#
# Returns nothing.
add: (name, object, {devMode}={}) ->
@@ -37,20 +36,20 @@ class ContextMenuManager
for label, command of items
@addBySelector(selector, {label, command}, {devMode})
# Private: Registers a command to be displayed when the relevant item is right
# Registers a command to be displayed when the relevant item is right
# clicked.
#
# * selector: The css selector for the active element which should include
# the given command in its context menu.
# * definition: The object containing keys which match the menu template API.
# * options:
# + devMode: Indicates whether this command should only appear while the
# editor is in dev mode.
# selector - The css selector for the active element which should include
# the given command in its context menu.
# definition - The object containing keys which match the menu template API.
# options - An {Object} with the following keys:
# :devMode - Indicates whether this command should only appear while the
# editor is in dev mode.
addBySelector: (selector, definition, {devMode}={}) ->
definitions = if devMode then @devModeDefinitions else @definitions
(definitions[selector] ?= []).push(definition)
# Private: Returns definitions which match the element and devMode.
# Returns definitions which match the element and devMode.
definitionsForElement: (element, {devMode}={}) ->
definitions = if devMode then @devModeDefinitions else @definitions
matchedDefinitions = []
@@ -59,14 +58,14 @@ class ContextMenuManager
matchedDefinitions
# Private: Used to generate the context menu for a specific element and it's
# Used to generate the context menu for a specific element and it's
# parents.
#
# The menu items are sorted such that menu items that match closest to the
# active element are listed first. The further down the list you go, the higher
# up the ancestor hierarchy they match.
#
# * element: The DOM element to generate the menu template for.
# element - The DOM element to generate the menu template for.
menuTemplateForMostSpecificElement: (element, {devMode}={}) ->
menuTemplate = @definitionsForElement(element, {devMode})
if element.parentElement
@@ -74,7 +73,7 @@ class ContextMenuManager
else
menuTemplate
# Private: Returns a menu template for both normal entries as well as
# Returns a menu template for both normal entries as well as
# development mode entries.
combinedMenuTemplateForElement: (element) ->
normalItems = @menuTemplateForMostSpecificElement(element)
@@ -84,7 +83,7 @@ class ContextMenuManager
menuTemplate.push({ type: 'separator' }) if normalItems.length > 0 and devItems.length > 0
menuTemplate.concat(devItems)
# Private: Executes `executeAtBuild` if defined for each menu item with
# Executes `executeAtBuild` if defined for each menu item with
# the provided event and then removes the `executeAtBuild` property from
# the menu item.
#

View File

@@ -2,7 +2,6 @@
{Point, Range} = require 'text-buffer'
_ = require 'underscore-plus'
### Internal ###
module.exports =
class CursorView extends View
@content: ->

View File

@@ -17,7 +17,7 @@ class Cursor
visible: true
needsAutoscroll: null
# Private: Instantiated by an {Editor}
# Instantiated by an {Editor}
constructor: ({@editor, @marker}) ->
@updateVisibility()
@marker.on 'changed', (e) =>
@@ -45,11 +45,9 @@ class Cursor
@emit 'destroyed'
@needsAutoscroll = true
# Private:
destroy: ->
@marker.destroy()
# Private:
changePosition: (options, fn) ->
@clearSelection()
@needsAutoscroll = options.autoscroll ? @isLastCursor()
@@ -58,12 +56,11 @@ class Cursor
# Public: Moves a cursor to a given screen position.
#
# * screenPosition:
# An {Array} of two numbers: the screen row, and the screen column.
# * options:
# + autoscroll:
# A Boolean which, if `true`, scrolls the {Editor} to wherever the
# cursor moves to.
# screenPosition - An {Array} of two numbers: the screen row, and the screen
# column.
# options - An {Object} with the following keys:
# :autoscroll - A Boolean which, if `true`, scrolls the {Editor} to wherever
# the cursor moves to.
setScreenPosition: (screenPosition, options={}) ->
@changePosition options, =>
@marker.setHeadScreenPosition(screenPosition, options)
@@ -74,12 +71,11 @@ class Cursor
# Public: Moves a cursor to a given buffer position.
#
# * bufferPosition:
# An {Array} of two numbers: the buffer row, and the buffer column.
# * options:
# + autoscroll:
# A Boolean which, if `true`, scrolls the {Editor} to wherever the
# cursor moves to.
# bufferPosition - An {Array} of two numbers: the buffer row, and the buffer
# column.
# options - An {Object} with the following keys:
# :autoscroll - A Boolean which, if `true`, scrolls the {Editor} to wherever
# the cursor moves to.
setBufferPosition: (bufferPosition, options={}) ->
@changePosition options, =>
@marker.setHeadBufferPosition(bufferPosition, options)
@@ -104,11 +100,11 @@ class Cursor
# Public: Get the RegExp used by the cursor to determine what a "word" is.
#
# * options:
# + includeNonWordCharacters:
# A Boolean indicating whether to include non-word characters in the regex.
# options: An {Object} with the following keys:
# :includeNonWordCharacters - A {Boolean} indicating whether to include
# non-word characters in the regex.
#
# Returns a RegExp.
# Returns a {RegExp}.
wordRegExp: ({includeNonWordCharacters}={})->
includeNonWordCharacters ?= true
nonWordCharacters = atom.config.get('editor.nonWordCharacters')
@@ -122,7 +118,7 @@ class Cursor
#
# "Last" is defined as the most recently added cursor.
#
# Returns a Boolean.
# Returns a {Boolean}.
isLastCursor: ->
this == @editor.getCursor()
@@ -131,7 +127,7 @@ class Cursor
# "Surrounded" here means that all characters before and after the cursor is
# whitespace.
#
# Returns a Boolean.
# Returns a {Boolean}.
isSurroundedByWhitespace: ->
{row, column} = @getBufferPosition()
range = [[row, Math.min(0, column - 1)], [row, Math.max(0, column + 1)]]
@@ -217,9 +213,9 @@ class Cursor
# Public: Moves the cursor left one screen column.
#
# * options:
# + moveToEndOfSelection:
# if true, move to the left of the selection if a selection exists.
# options - An {Object} with the following keys:
# :moveToEndOfSelection - if true, move to the left of the selection if a
# selection exists.
moveLeft: ({moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
@@ -231,9 +227,9 @@ class Cursor
# Public: Moves the cursor right one screen column.
#
# * options:
# + moveToEndOfSelection:
# if true, move to the right of the selection if a selection exists.
# options - An {Object} with the following keys:
# :moveToEndOfSelection - if true, move to the right of the selection if a
# selection exists.
moveRight: ({moveToEndOfSelection}={}) ->
range = @marker.getScreenRange()
if moveToEndOfSelection and not range.isEmpty()
@@ -313,12 +309,12 @@ class Cursor
# Public: Retrieves the buffer position of where the current word starts.
#
# * options:
# + wordRegex:
# A RegExp indicating what constitutes a "word" (default: {.wordRegExp})
# + includeNonWordCharacters:
# A Boolean indicating whether to include non-word characters in the
# default word regex. Has no effect if wordRegex is set.
# options - An {Object} with the following keys:
# :wordRegex - A {RegExp} indicating what constitutes a "word"
# (default: {.wordRegExp}).
# :includeNonWordCharacters - A {Boolean} indicating whether to include
# non-word characters in the default word regex.
# Has no effect if wordRegex is set.
#
# Returns a {Range}.
getBeginningOfCurrentWordBufferPosition: (options = {}) ->
@@ -381,12 +377,12 @@ class Cursor
# Public: Retrieves the buffer position of where the current word ends.
#
# * options:
# + wordRegex:
# A RegExp indicating what constitutes a "word" (default: {.wordRegExp})
# + includeNonWordCharacters:
# A Boolean indicating whether to include non-word characters in the
# default word regex. Has no effect if wordRegex is set.
# options - An {Object} with the following keys:
# :wordRegex - A {RegExp} indicating what constitutes a "word"
# (default: {.wordRegExp})
# :includeNonWordCharacters - A Boolean indicating whether to include
# non-word characters in the default word regex.
# Has no effect if wordRegex is set.
#
# Returns a {Range}.
getEndOfCurrentWordBufferPosition: (options = {}) ->
@@ -405,9 +401,9 @@ class Cursor
# Public: Retrieves the buffer position of where the next word starts.
#
# * options:
# + wordRegex:
# A RegExp indicating what constitutes a "word" (default: {.wordRegExp})
# options -
# :wordRegex - A {RegExp} indicating what constitutes a "word"
# (default: {.wordRegExp}).
#
# Returns a {Range}.
getBeginningOfNextWordBufferPosition: (options = {}) ->
@@ -424,9 +420,9 @@ class Cursor
# Public: Returns the buffer Range occupied by the word located under the cursor.
#
# * options:
# + wordRegex:
# A RegExp indicating what constitutes a "word" (default: {.wordRegExp})
# options -
# :wordRegex - A {RegExp} indicating what constitutes a "word"
# (default: {.wordRegExp}).
getCurrentWordBufferRange: (options={}) ->
startOptions = _.extend(_.clone(options), allowPrevious: false)
endOptions = _.extend(_.clone(options), allowNext: false)
@@ -434,9 +430,9 @@ class Cursor
# Public: Returns the buffer Range for the current line.
#
# * options:
# + includeNewline:
# A boolean which controls whether the Range should include the newline.
# options -
# :includeNewline: - A {Boolean} which controls whether the Range should
# include the newline.
getCurrentLineBufferRange: (options) ->
@editor.bufferRangeForBufferRow(@getBufferRow(), options)

View File

@@ -19,18 +19,29 @@ class DeserializerManager
@deferredDeserializers = {}
# Public: Register the given class(es) as deserializers.
add: (klasses...) ->
@deserializers[klass.name] = klass for klass in klasses
#
# classes - One or more classes to register.
add: (classes...) ->
@deserializers[klass.name] = klass for klass in classes
# Public: Add a deferred deserializer for the given class name.
#
# name - The {String} name of the deserializer.
# fn - The {Function} that creates the deserializer.
addDeferred: (name, fn) ->
@deferredDeserializers[name] = fn
# Public: Remove the given class(es) as deserializers.
remove: (klasses...) ->
delete @deserializers[klass.name] for klass in klasses
#
# classes - One or more classes to remove.
remove: (classes...) ->
delete @deserializers[name] for {name} in classes
# Public: Deserialize the state and params.
#
# state - The state {Object} to deserialize.
# params - The params {Object} to pass as the second arguments to the
# deserialize method of the deserializer.
deserialize: (state, params) ->
return unless state?
@@ -41,7 +52,9 @@ class DeserializerManager
else
console.warn "No deserializer found for", state
# Private: Get the deserializer for the state.
# Get the deserializer for the state.
#
# state - The state {Object} being deserialized.
get: (state) ->
return unless state?

View File

@@ -7,7 +7,7 @@ pathWatcher = require 'pathwatcher'
File = require './file'
# Public: Represents a directory using {File}s.
# Public: Represents a directory on disk.
#
# ## Requiring in packages
#
@@ -18,15 +18,12 @@ module.exports =
class Directory
Emitter.includeInto(this)
path: null
realPath: null
# Public: Configures a new Directory instance, no files are accessed.
#
# * path:
# A String containing the absolute path to the directory.
# + symlink:
# A Boolean indicating if the path is a symlink (defaults to false).
# path - A {String} containing the absolute path to the directory.
# symlink - A {Boolean} indicating if the path is a symlink (default: false).
constructor: (@path, @symlink=false) ->
@on 'first-contents-changed-subscription-will-be-added', =>
# Triggered by emissary, when a new contents-changed listener attaches
@@ -36,7 +33,7 @@ class Directory
# Triggered by emissary, when the last contents-changed listener detaches
@unsubscribeFromNativeChangeEvents()
# Public: Returns the basename of the directory.
# Public: Returns the {String} basename of the directory.
getBaseName: ->
path.basename(@path)
@@ -108,8 +105,8 @@ class Directory
# Public: Reads file entries in this directory from disk asynchronously.
#
# * callback: A function to call with an Error as the first argument and
# an {Array} of {File} and {Directory} objects as the second argument.
# callback - A {Function} to call with an {Error} as the 1st argument and
# an {Array} of {File} and {Directory} objects as the 2nd argument.
getEntries: (callback) ->
fs.list @path, (error, entries) ->
return callback(error) if error?
@@ -134,18 +131,16 @@ class Directory
async.eachLimit entries, 1, statEntry, ->
callback(null, directories.concat(files))
# Private:
subscribeToNativeChangeEvents: ->
unless @watchSubscription?
@watchSubscription = pathWatcher.watch @path, (eventType) =>
@emit "contents-changed" if eventType is "change"
# Private:
unsubscribeFromNativeChangeEvents: ->
if @watchSubscription?
@watchSubscription.close()
@watchSubscription = null
# Private: Does given full path start with the given prefix?
# Does given full path start with the given prefix?
isPathPrefixOf: (prefix, fullPath) ->
fullPath.indexOf(prefix) is 0 and fullPath[prefix.length] is path.sep

View File

@@ -2,7 +2,6 @@
_ = require 'underscore-plus'
{Emitter, Subscriber} = require 'emissary'
# Private:
module.exports =
class DisplayBufferMarker
Emitter.includeInto(this)
@@ -15,8 +14,6 @@ class DisplayBufferMarker
oldTailScreenPosition: null
wasValid: true
### Internal ###
constructor: ({@bufferMarker, @displayBuffer}) ->
@id = @bufferMarker.id
@oldHeadBufferPosition = @getHeadBufferPosition()
@@ -28,8 +25,6 @@ class DisplayBufferMarker
@subscribe @bufferMarker, 'destroyed', => @destroyed()
@subscribe @bufferMarker, 'changed', (event) => @notifyObservers(event)
### Public ###
copy: (attributes) ->
@displayBuffer.getMarker(@bufferMarker.copy(attributes).id)
@@ -170,8 +165,6 @@ class DisplayBufferMarker
inspect: ->
"DisplayBufferMarker(id: #{@id}, bufferRange: #{@getBufferRange()})"
### Internal ###
destroyed: ->
delete @displayBuffer.markers[@id]
@emit 'destroyed'

View File

@@ -1,5 +1,5 @@
_ = require 'underscore-plus'
{Emitter, Subscriber} = require 'emissary'
{Emitter} = require 'emissary'
guid = require 'guid'
Serializable = require 'serializable'
{Model} = require 'theorist'
@@ -9,13 +9,10 @@ RowMap = require './row-map'
Fold = require './fold'
Token = require './token'
DisplayBufferMarker = require './display-buffer-marker'
ConfigObserver = require './config-observer'
# Private:
module.exports =
class DisplayBuffer extends Model
Serializable.includeInto(this)
ConfigObserver.includeInto(this)
@properties
softWrap: null
@@ -39,10 +36,10 @@ class DisplayBuffer extends Model
@emit 'soft-wrap-changed', softWrap
@updateWrappedScreenLines()
@observeConfig 'editor.preferredLineLength', callNow: false, =>
@subscribe atom.config.observe 'editor.preferredLineLength', callNow: false, =>
@updateWrappedScreenLines() if @softWrap and atom.config.get('editor.softWrapAtPreferredLineLength')
@observeConfig 'editor.softWrapAtPreferredLineLength', callNow: false, =>
@subscribe atom.config.observe 'editor.softWrapAtPreferredLineLength', callNow: false, =>
@updateWrappedScreenLines() if @softWrap
serializeParams: ->
@@ -82,8 +79,6 @@ class DisplayBuffer extends Model
bufferDelta = 0
@emitChanged({ start, end, screenDelta, bufferDelta })
### Public ###
# Sets the visibility of the tokenized buffer.
#
# visible - A {Boolean} indicating of the tokenized buffer is shown
@@ -419,8 +414,6 @@ class DisplayBuffer extends Model
column = screenLine.clipScreenColumn(column, options)
new Point(row, column)
### Public ###
# Given a line, finds the point where it would wrap.
#
# line - The {String} to check
@@ -470,7 +463,7 @@ class DisplayBuffer extends Model
getMarkerCount: ->
@buffer.getMarkerCount()
# Constructs a new marker at the given screen range.
# Public: Constructs a new marker at the given screen range.
#
# range - The marker {Range} (representing the distance between the head and tail)
# options - Options to pass to the {Marker} constructor
@@ -480,7 +473,7 @@ class DisplayBuffer extends Model
bufferRange = @bufferRangeForScreenRange(args.shift())
@markBufferRange(bufferRange, args...)
# Constructs a new marker at the given buffer range.
# Public: Constructs a new marker at the given buffer range.
#
# range - The marker {Range} (representing the distance between the head and tail)
# options - Options to pass to the {Marker} constructor
@@ -489,7 +482,7 @@ class DisplayBuffer extends Model
markBufferRange: (args...) ->
@getMarker(@buffer.markRange(args...).id)
# Constructs a new marker at the given screen position.
# Public: Constructs a new marker at the given screen position.
#
# range - The marker {Range} (representing the distance between the head and tail)
# options - Options to pass to the {Marker} constructor
@@ -498,7 +491,7 @@ class DisplayBuffer extends Model
markScreenPosition: (screenPosition, options) ->
@markBufferPosition(@bufferPositionForScreenPosition(screenPosition), options)
# Constructs a new marker at the given buffer position.
# Public: Constructs a new marker at the given buffer position.
#
# range - The marker {Range} (representing the distance between the head and tail)
# options - Options to pass to the {Marker} constructor
@@ -507,7 +500,7 @@ class DisplayBuffer extends Model
markBufferPosition: (bufferPosition, options) ->
@getMarker(@buffer.markPosition(bufferPosition, options).id)
# Removes the marker with the given id.
# Public: Removes the marker with the given id.
#
# id - The {Number} of the ID to remove
destroyMarker: (id) ->
@@ -573,15 +566,12 @@ class DisplayBuffer extends Model
marker.unsubscribe() for marker in @getMarkers()
@tokenizedBuffer.destroy()
@unsubscribe()
@unobserveConfig()
logLines: (start=0, end=@getLastRow())->
for row in [start..end]
line = @lineForRow(row).text
console.log row, line, line.length
### Internal ###
handleTokenizedBufferChange: (tokenizedBufferChange) =>
{start, end, delta, bufferChange} = tokenizedBufferChange
@updateScreenLines(start, end + 1, delta, delayChangeEvent: bufferChange?)

View File

@@ -276,12 +276,11 @@ class EditorView extends View
# Public: Defines which characters are invisible.
#
# invisibles - An {Object} defining the invisible characters.
# The defaults are:
# eol: `\u00ac`
# space: `\u00b7`
# tab: `\u00bb`
# cr: `\u00a4`
# invisibles - An {Object} defining the invisible characters:
# :eol - The end of line invisible {String} (default: `\u00ac`).
# :space - The space invisible {String} (default: `\u00b7`).
# :tab - The tab invisible {String} (default: `\u00bb`).
# :cr - The carriage return invisible {String} (default: `\u00a4`).
setInvisibles: (@invisibles={}) ->
_.defaults @invisibles,
eol: '\u00ac'
@@ -318,12 +317,12 @@ class EditorView extends View
atom.project.getRepo()?.checkoutHead(path)
configure: ->
@observeConfig 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers)
@observeConfig 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles)
@observeConfig 'editor.showIndentGuide', (showIndentGuide) => @setShowIndentGuide(showIndentGuide)
@observeConfig 'editor.invisibles', (invisibles) => @setInvisibles(invisibles)
@observeConfig 'editor.fontSize', (fontSize) => @setFontSize(fontSize)
@observeConfig 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
@subscribe atom.config.observe 'editor.showLineNumbers', (showLineNumbers) => @gutter.setShowLineNumbers(showLineNumbers)
@subscribe atom.config.observe 'editor.showInvisibles', (showInvisibles) => @setShowInvisibles(showInvisibles)
@subscribe atom.config.observe 'editor.showIndentGuide', (showIndentGuide) => @setShowIndentGuide(showIndentGuide)
@subscribe atom.config.observe 'editor.invisibles', (invisibles) => @setInvisibles(invisibles)
@subscribe atom.config.observe 'editor.fontSize', (fontSize) => @setFontSize(fontSize)
@subscribe atom.config.observe 'editor.fontFamily', (fontFamily) => @setFontFamily(fontFamily)
handleEvents: ->
@on 'focus', =>
@@ -627,8 +626,8 @@ class EditorView extends View
# an {Object} (`{row, column}`), {Array} (`[row, column]`), or
# {Point}.
# options - A hash with the following keys:
# center - if `true`, the position is scrolled such that it's in
# the center of the editor
# :center - if `true`, the position is scrolled such that it's in
# the center of the editor
scrollToPixelPosition: (pixelPosition, options) ->
return unless @attached
@scrollVertically(pixelPosition, options)

View File

@@ -97,7 +97,6 @@ class Editor extends Model
params.registerEditor = true
params
# Private:
subscribeToBuffer: ->
@buffer.retain()
@subscribe @buffer, "path-changed", =>
@@ -111,7 +110,6 @@ class Editor extends Model
@subscribe @buffer, "destroyed", => @destroy()
@preserveCursorPositionOnBufferReload()
# Private:
subscribeToDisplayBuffer: ->
@subscribe @displayBuffer, 'marker-created', @handleMarkerCreated
@subscribe @displayBuffer, "changed", (e) => @emit 'screen-lines-changed', e
@@ -119,11 +117,9 @@ class Editor extends Model
@subscribe @displayBuffer, 'grammar-changed', => @handleGrammarChange()
@subscribe @displayBuffer, 'soft-wrap-changed', (args...) => @emit 'soft-wrap-changed', args...
# Private:
getViewClass: ->
require './editor-view'
# Private:
destroyed: ->
@unsubscribe()
selection.destroy() for selection in @getSelections()
@@ -132,7 +128,7 @@ class Editor extends Model
@languageMode.destroy()
atom.project?.removeEditor(this)
# Private: Creates an {Editor} with the same initial state
# Creates an {Editor} with the same initial state
copy: ->
tabLength = @getTabLength()
displayBuffer = @displayBuffer.copy()
@@ -242,8 +238,7 @@ class Editor extends Model
# or if its column goes beyond a line's length, this "sanitizes" the value
# to a real position.
#
# * bufferPosition:
# The {Point} to clip
# bufferPosition - The {Point} to clip.
#
# Returns the new, clipped {Point}. Note that this could be the same as
# `bufferPosition` if no clipping was performed.
@@ -255,8 +250,7 @@ class Editor extends Model
# or if its column goes beyond a line's length, this "sanitizes" the value
# to a real range.
#
# * range:
# The {Range} to clip
# range - The {Range} to clip.
#
# Returns the new, clipped {Range}. Note that this could be the same as
# `range` if no clipping was performed.
@@ -264,17 +258,14 @@ class Editor extends Model
# Public: Returns the indentation level of the given a buffer row
#
# * bufferRow:
# A Number indicating the buffer row.
# bufferRow - A {Number} indicating the buffer row.
indentationForBufferRow: (bufferRow) ->
@indentLevelForLine(@lineForBufferRow(bufferRow))
# Public: Sets the indentation level for the given buffer row.
#
# * bufferRow:
# A {Number} indicating the buffer row.
# * newLevel:
# A {Number} indicating the new indentation level.
# bufferRow - A {Number} indicating the buffer row.
# newLevel - A {Number} indicating the new indentation level.
setIndentationForBufferRow: (bufferRow, newLevel) ->
currentIndentLength = @lineForBufferRow(bufferRow).match(/^\s*/)[0].length
newIndentString = @buildIndentString(newLevel)
@@ -282,8 +273,7 @@ class Editor extends Model
# Public: Returns the indentation level of the given line of text.
#
# * line:
# A {String} in the current buffer.
# line - A {String} in the current buffer.
#
# Returns a {Number} or 0 if the text isn't found within the buffer.
indentLevelForLine: (line) ->
@@ -295,7 +285,7 @@ class Editor extends Model
else
0
# Private: Constructs the string used for tabs.
# Constructs the string used for tabs.
buildIndentString: (number) ->
if @getSoftTabs()
_.multiplyString(" ", number * @getTabLength())
@@ -326,7 +316,7 @@ class Editor extends Model
# Public: Returns a {Number} representing the number of lines in the editor.
getLineCount: -> @buffer.getLineCount()
# Private: Retrieves the current {TextBuffer}.
# Retrieves the current {TextBuffer}.
getBuffer: -> @buffer
# Public: Retrieves the current buffer's URI.
@@ -353,8 +343,8 @@ class Editor extends Model
# Public: Returns the range for the given buffer row.
#
# * row: A row {Number}.
# * options: An options hash with an `includeNewline` key.
# row - A row {Number}.
# options - An options hash with an `includeNewline` key.
#
# Returns a {Range}.
bufferRangeForBufferRow: (row, options) -> @buffer.rangeForRow(row, options)
@@ -362,7 +352,7 @@ class Editor extends Model
# Public: Returns a {String} representing the contents of the line at the
# given buffer row.
#
# * row - A {Number} representing a zero-indexed buffer row.
# row - A {Number} representing a zero-indexed buffer row.
lineForBufferRow: (row) -> @buffer.lineForRow(row)
# Public: Returns a {Number} representing the line length for the given
@@ -437,10 +427,8 @@ class Editor extends Model
# Public: Inserts text at the current cursor positions
#
# * text:
# A String representing the text to insert.
# * options:
# + A set of options equivalent to {Selection.insertText}
# text - A {String} representing the text to insert.
# options - A set of options equivalent to {Selection.insertText}.
insertText: (text, options={}) ->
options.autoIndentNewline ?= @shouldAutoIndent()
options.autoDecreaseIndent ?= @shouldAutoIndent()
@@ -467,8 +455,7 @@ class Editor extends Model
# Public: Indents the current line.
#
# * options
# + A set of options equivalent to {Selection.indent}.
# options - A set of options equivalent to {Selection.indent}.
indent: (options={})->
options.autoIndent ?= @shouldAutoIndent()
@mutateSelectedText (selection) -> selection.indent(options)
@@ -556,8 +543,7 @@ class Editor extends Model
# Public: Pastes the text in the clipboard.
#
# * options:
# + A set of options equivalent to {Selection.insertText}.
# options - A set of options equivalent to {Selection.insertText}.
pasteText: (options={}) ->
{text, metadata} = atom.clipboard.readWithMetadata()
@@ -737,11 +723,9 @@ class Editor extends Model
@setCursorScreenPosition(@getCursorScreenPosition().translate([1]))
@foldCurrentRow() if cursorRowFolded
# Private:
mutateSelectedText: (fn) ->
@transact => fn(selection) for selection in @getSelections()
# Private:
replaceSelectedText: (options={}, fn) ->
{selectWordIfEmpty} = options
@mutateSelectedText (selection) ->
@@ -826,10 +810,8 @@ class Editor extends Model
# Public: Creates a new selection at the given marker.
#
# * marker:
# The {DisplayBufferMarker} to highlight
# * options:
# + A hash of options that pertain to the {Selection} constructor.
# marker - The {DisplayBufferMarker} to highlight
# options - An {Object} that pertains to the {Selection} constructor.
#
# Returns the new {Selection}.
addSelection: (marker, options={}) ->
@@ -850,10 +832,8 @@ class Editor extends Model
# Public: Given a buffer range, this adds a new selection for it.
#
# * bufferRange:
# A {Range} in the buffer
# * options:
# + A hash of options for {.markBufferRange}
# bufferRange - A {Range} in the buffer.
# options - An options {Object} for {.markBufferRange}.
#
# Returns the new {Selection}.
addSelectionForBufferRange: (bufferRange, options={}) ->
@@ -863,20 +843,16 @@ class Editor extends Model
# Public: Given a buffer range, this removes all previous selections and
# creates a new selection for it.
#
# * bufferRange:
# A {Range} in the buffer
# * options:
# + A hash of options for {.setSelectedBufferRanges}
# bufferRange - A {Range} in the buffer.
# options - An options {Object} for {.setSelectedBufferRanges}.
setSelectedBufferRange: (bufferRange, options) ->
@setSelectedBufferRanges([bufferRange], options)
# Public: Given an array of buffer ranges, this removes all previous
# selections and creates new selections for them.
#
# * bufferRange:
# A {Range} in the buffer
# * options:
# + A hash of options for {.setSelectedBufferRanges}
# bufferRange - A {Range} in the buffer.
# options - An options {Object} for {.setSelectedBufferRanges}.
setSelectedBufferRanges: (bufferRanges, options={}) ->
throw new Error("Passed an empty array to setSelectedBufferRanges") unless bufferRanges.length
@@ -893,7 +869,7 @@ class Editor extends Model
# Public: Unselects a given selection.
#
# * selection - The {Selection} to remove.
# selection - The {Selection} to remove.
removeSelection: (selection) ->
_.remove(@selections, selection)
@@ -904,9 +880,7 @@ class Editor extends Model
@consolidateSelections()
@getSelection().clear()
# Public:
#
# Removes all but one cursor (if there are multiple cursors)
# Removes all but one cursor (if there are multiple cursors).
consolidateSelections: ->
selections = @getSelections()
if selections.length > 1
@@ -943,8 +917,7 @@ class Editor extends Model
# Public: Determines if a given buffer range is included in a {Selection}.
#
# * bufferRange:
# The {Range} you're checking against
# bufferRange - The {Range} you're checking against.
#
# Returns a {Boolean}.
selectionIntersectsBufferRange: (bufferRange) ->
@@ -953,10 +926,8 @@ class Editor extends Model
# Public: Moves every local cursor to a given screen position.
#
# * position:
# An {Array} of two numbers: the screen row, and the screen column.
# * options:
# An object with properties based on {Cursor.setScreenPosition}
# position - An {Array} of two numbers: the screen row, and the screen column.
# options - An {Object} with properties based on {Cursor.setScreenPosition}.
setCursorScreenPosition: (position, options) ->
@moveCursors (cursor) -> cursor.setScreenPosition(position, options)
@@ -975,10 +946,8 @@ class Editor extends Model
# Public: Moves every cursor to a given buffer position.
#
# * position:
# An {Array} of two numbers: the buffer row, and the buffer column.
# * options:
# + An object with properties based on {Cursor.setBufferPosition}
# position - An {Array} of two numbers: the buffer row, and the buffer column.
# options - An object with properties based on {Cursor.setBufferPosition}.
setCursorBufferPosition: (position, options) ->
@moveCursors (cursor) -> cursor.setBufferPosition(position, options)
@@ -1021,9 +990,8 @@ class Editor extends Model
# Public: Returns the word under the most recently added local {Cursor}.
#
# * options:
# + An object with properties based on
# {Cursor.getBeginningOfCurrentWordBufferPosition}.
# options - An object with properties based on
# {Cursor.getBeginningOfCurrentWordBufferPosition}.
getWordUnderCursor: (options) ->
@getTextInBufferRange(@getCursor().getCurrentWordBufferRange(options))
@@ -1091,7 +1059,6 @@ class Editor extends Model
moveCursorToNextWordBoundary: ->
@moveCursors (cursor) -> cursor.moveToNextWordBoundary()
# Internal: Executes given function on all local cursors.
moveCursors: (fn) ->
fn(cursor) for cursor in @getCursors()
@mergeCursors()
@@ -1099,8 +1066,7 @@ class Editor extends Model
# Public: Selects the text from the current cursor position to a given screen
# position.
#
# * position:
# An instance of {Point}, with a given `row` and `column`.
# position - An instance of {Point}, with a given `row` and `column`.
selectToScreenPosition: (position) ->
lastSelection = @getLastSelection()
lastSelection.selectToScreenPosition(position)
@@ -1259,8 +1225,6 @@ class Editor extends Model
@setSelectedBufferRange(range)
range
# Public:
#
# FIXME: Not sure how to describe what this does.
mergeCursors: ->
positions = []
@@ -1271,27 +1235,21 @@ class Editor extends Model
else
positions.push(position)
# Public:
#
# FIXME: Not sure how to describe what this does.
expandSelectionsForward: (fn) ->
@mergeIntersectingSelections =>
fn(selection) for selection in @getSelections()
# Public:
#
# FIXME: Not sure how to describe what this does.
expandSelectionsBackward: (fn) ->
@mergeIntersectingSelections isReversed: true, =>
fn(selection) for selection in @getSelections()
# Public:
#
# FIXME: No idea what this does.
finalizeSelections: ->
selection.finalize() for selection in @getSelections()
# Private: Merges intersecting selections. If passed a function, it executes
# Merges intersecting selections. If passed a function, it executes
# the function with merging suppressed, then merges intersecting selections
# afterward.
mergeIntersectingSelections: (args...) ->
@@ -1315,7 +1273,6 @@ class Editor extends Model
_.reduce(@getSelections(), reducer, [])
# Private:
preserveCursorPositionOnBufferReload: ->
cursorPosition = null
@subscribe @buffer, "will-reload", =>
@@ -1336,7 +1293,6 @@ class Editor extends Model
reloadGrammar: ->
@displayBuffer.reloadGrammar()
# Private:
shouldAutoIndent: ->
atom.config.get("editor.autoIndent")
@@ -1347,32 +1303,24 @@ class Editor extends Model
# undo stack remains relevant.
transact: (fn) -> @buffer.transact(fn)
# Private:
beginTransaction: -> @buffer.beginTransaction()
# Private:
commitTransaction: -> @buffer.commitTransaction()
# Private:
abortTransaction: -> @buffer.abortTransaction()
# Private:
inspect: ->
"<Editor #{@id}>"
# Private:
logScreenLines: (start, end) -> @displayBuffer.logLines(start, end)
# Private:
handleGrammarChange: ->
@unfoldAll()
@emit 'grammar-changed'
# Private:
handleMarkerCreated: (marker) =>
if marker.matchesAttributes(@getSelectionMarkerAttributes())
@addSelection(marker)
# Private:
getSelectionMarkerAttributes: ->
type: 'selection', editorId: @id, invalidate: 'never'

View File

@@ -25,16 +25,14 @@ class File
# Public: Creates a new file.
#
# * path:
# A String containing the absolute path to the file
# * symlink:
# A Boolean indicating if the path is a symlink (default: false)
# path - A {String} containing the absolute path to the file
# symlink - A {Boolean} indicating if the path is a symlink (default: false).
constructor: (@path, @symlink=false) ->
throw new Error("#{@path} is a directory") if fs.isDirectorySync(@path)
@handleEventSubscriptions()
# Private: Subscribes to file system notifications when necessary.
# Subscribes to file system notifications when necessary.
handleEventSubscriptions: ->
eventNames = ['contents-changed', 'moved', 'removed']
@@ -49,13 +47,13 @@ class File
subscriptionsEmpty = _.every eventNames, (eventName) => @getSubscriptionCount(eventName) is 0
@unsubscribeFromNativeChangeEvents() if subscriptionsEmpty
# Private: Sets the path for the file.
# Sets the path for the file.
setPath: (@path) ->
# Public: Returns the path for the file.
# Public: Returns the {String} path for the file.
getPath: -> @path
# Public: Return the filename without any directory information.
# Public: Return the {String} filename without any directory information.
getBaseName: ->
path.basename(@path)
@@ -66,7 +64,7 @@ class File
fs.writeFileSync(@getPath(), text)
@subscribeToNativeChangeEvents() if not previouslyExisted and @hasSubscriptions()
# Private: Deprecated
# Deprecated
readSync: (flushCache) ->
if not @exists()
@cachedContents = null
@@ -80,9 +78,8 @@ class File
# Public: Reads the contents of the file.
#
# * flushCache:
# A Boolean indicating whether to require a direct read or if a cached
# copy is acceptable.
# flushCache - A {Boolean} indicating whether to require a direct read or if
# a cached copy is acceptable.
#
# Returns a promise that resovles to a String.
read: (flushCache) ->
@@ -118,7 +115,6 @@ class File
exists: ->
fs.existsSync(@getPath())
# Private:
setDigest: (contents) ->
@digest = crypto.createHash('sha1').update(contents ? '').digest('hex')
@@ -126,7 +122,6 @@ class File
getDigest: ->
@digest ? @setDigest(@readSync())
# Private:
handleNativeChangeEvent: (eventType, path) ->
if eventType is "delete"
@unsubscribeFromNativeChangeEvents()
@@ -139,11 +134,9 @@ class File
@read(true).done (newContents) =>
@emit 'contents-changed' unless oldContents == newContents
# Private:
detectResurrectionAfterDelay: ->
_.delay (=> @detectResurrection()), 50
# Private:
detectResurrection: ->
if @exists()
@subscribeToNativeChangeEvents()
@@ -152,13 +145,11 @@ class File
@cachedContents = null
@emit "removed"
# Private:
subscribeToNativeChangeEvents: ->
unless @watchSubscription?
@watchSubscription = pathWatcher.watch @path, (eventType, path) =>
@handleNativeChangeEvent(eventType, path)
# Private:
unsubscribeFromNativeChangeEvents: ->
if @watchSubscription?
@watchSubscription.close()

View File

@@ -1,6 +1,6 @@
{Point, Range} = require 'text-buffer'
# Private: Represents a fold that collapses multiple buffer lines into a single
# Represents a fold that collapses multiple buffer lines into a single
# line on the screen.
#
# Their creation is managed by the {DisplayBuffer}.
@@ -10,8 +10,6 @@ class Fold
displayBuffer: null
marker: null
### Internal ###
constructor: (@displayBuffer, @marker) ->
@id = @marker.id
@displayBuffer.foldsByMarkerId[@marker.id] = this

View File

@@ -27,17 +27,19 @@ class Git
Emitter.includeInto(this)
Subscriber.includeInto(this)
# Private: Creates a new `Git` instance.
# Public: Creates a new Git instance.
#
# * path: The path to the git repository to open
# * options:
# + refreshOnWindowFocus:
# A Boolean that identifies if the windows should refresh
# path - The path to the Git repository to open.
# options - An object with the following keys (default: {}):
# :refreshOnWindowFocus - `true` to refresh the index and statuses when the
# window is focused.
#
# Returns a Git instance or null if the repository could not be opened.
@open: (path, options) ->
return null unless path
try
new Git(path, options)
catch e
catch
null
@exists: (path) ->
@@ -47,20 +49,6 @@ class Git
else
false
path: null
statuses: null
upstream: null
branch: null
statusTask: null
# Private: Creates a new `Git` object.
#
# * path: The {String} representing the path to your git working directory
# * options:
# + refreshOnWindowFocus: If `true`, {#refreshIndex} and {#refreshStatus}
# are called on focus
# + project: A project that supplies buffers that will be monitored for
# save and reload events to trigger status refreshes.
constructor: (path, options={}) ->
@repo = GitUtils.open(path)
unless @repo?
@@ -80,7 +68,7 @@ class Git
if @project?
@subscribe @project.eachBuffer (buffer) => @subscribeToBuffer(buffer)
# Private: Subscribes to buffer events.
# Subscribes to buffer events.
subscribeToBuffer: (buffer) ->
@subscribe buffer, 'saved reloaded path-changed', =>
if path = buffer.getPath()
@@ -100,29 +88,29 @@ class Git
@unsubscribe()
# Private: Returns the corresponding {Repository}
# Returns the corresponding {Repository}
getRepo: ->
unless @repo?
throw new Error("Repository has been destroyed")
@repo
# Public: Reread the index to update any values that have changed since the
# Reread the index to update any values that have changed since the
# last time the index was read.
refreshIndex: -> @getRepo().refreshIndex()
# Public: Returns the path of the repository.
# Public: Returns the {String} path of the repository.
getPath: ->
@path ?= fs.absolute(@getRepo().getPath())
# Public: Returns the working directory of the repository.
# Public: Returns the {String} working directory path of the repository.
getWorkingDirectory: -> @getRepo().getWorkingDirectory()
# Public: Returns the status of a single path in the repository.
# Public: Get the status of a single path in the repository.
#
# * path:
# A String defining a relative path
# path - A {String} repository-relative path.
#
# Returns a {Number}, FIXME representing what?
# Returns a {Number} representing the status. This value can be passed to
# {.isStatusModified} or {.isStatusNew} to get more information.
getPathStatus: (path) ->
currentPathStatus = @statuses[path] ? 0
pathStatus = @getRepo().getStatus(@relativize(path)) ? 0
@@ -134,7 +122,9 @@ class Git
@emit 'status-changed', path, pathStatus
pathStatus
# Public: Returns true if the given path is ignored.
# Public: Is the given path ignored?
#
# Returns a {Boolean}.
isPathIgnored: (path) -> @getRepo().isIgnored(@relativize(path))
# Public: Returns true if the given status indicates modification.
@@ -163,22 +153,22 @@ class Git
# `refs/remotes`. It also shortens the SHA-1 of a detached `HEAD` to 7
# characters.
#
# Returns a String.
# Returns a {String}.
getShortHead: -> @getRepo().getShortHead()
# Public: Restore the contents of a path in the working directory and index
# to the version at `HEAD`.
#
# This is essentially the same as running:
#
# ```
# git reset HEAD -- <path>
# git checkout HEAD -- <path>
# ```
#
# * path:
# The String path to checkout
# path - The {String} path to checkout.
#
# Returns a Boolean that's true if the method was successful.
# Returns a {Boolean} that's true if the method was successful.
checkoutHead: (path) ->
headCheckedOut = @getRepo().checkoutHead(@relativize(path))
@getPathStatus(path) if headCheckedOut
@@ -186,10 +176,9 @@ class Git
# Public: Checks out a branch in your repository.
#
# * reference:
# The String reference to checkout
# * create:
# A Boolean value which, if true creates the new reference if it doesn't exist.
# reference - The String reference to checkout
# create - A Boolean value which, if true creates the new reference if it
# doesn't exist.
#
# Returns a Boolean that's true if the method was successful.
checkoutReference: (reference, create) ->
@@ -200,27 +189,26 @@ class Git
# This compares the working directory contents of the path to the `HEAD`
# version.
#
# * path:
# The String path to check
# path - The {String} path to check.
#
# Returns an object with two keys, `added` and `deleted`. These will always
# be greater than 0.
# Returns an {Object} with the following keys:
# :added - The {Number} of added lines.
# :deleted - The {Number} of deleted lines.
getDiffStats: (path) -> @getRepo().getDiffStats(@relativize(path))
# Public: Identifies if a path is a submodule.
# Public: Is the given path a submodule in the repository?
#
# * path:
# The String path to check
# path - The {String} path to check.
#
# Returns a Boolean.
# Returns a {Boolean}.
isSubmodule: (path) -> @getRepo().isSubmodule(@relativize(path))
# Public: Retrieves the status of a directory.
# Public: Get the status of a directory in the repository's working directory.
#
# * path:
# The String path to check
# path - The {String} path to check.
#
# Returns a Number representing the status.
# Returns a {Number} representing the status. This value can be passed to
# {.isStatusModified} or {.isStatusNew} to get more information.
getDirectoryStatus: (directoryPath) ->
{sep} = require 'path'
directoryPath = "#{directoryPath}#{sep}"
@@ -232,16 +220,14 @@ class Git
# Public: Retrieves the line diffs comparing the `HEAD` version of the given
# path and the given text.
#
# This is similar to the commit numbers reported by `git status` when a
# remote tracking branch exists.
# path - The {String} path relative to the repository.
# text - The {String} to compare against the `HEAD` contents
#
# * path:
# The String path (relative to the repository)
# * text:
# The String to compare against the `HEAD` contents
#
# Returns an object with two keys, `ahead` and `behind`. These will always be
# greater than zero.
# Returns an {Array} of hunk {Object}s with the following keys:
# :oldStart - The line {Number} of the old hunk.
# :newStart - The line {Number} of the new hunk.
# :oldLines - The {Number} of lines in the old hunk.
# :newLines - The {Number} of lines in the new hunk
getLineDiffs: (path, text) ->
# Ignore eol of line differences on windows so that files checked in as
# LF don't report every line modified when the text contains CRLF endings.
@@ -257,7 +243,7 @@ class Git
# Public: Returns the upstream branch for the current HEAD, or null if there
# is no upstream branch for the current HEAD.
#
# Returns a String branch name such as `refs/remotes/origin/master`
# Returns a {String} branch name such as `refs/remotes/origin/master`.
getUpstreamBranch: -> @getRepo().getUpstreamBranch()
# Public: Returns the current SHA for the given reference.
@@ -265,19 +251,21 @@ class Git
# Public: Gets all the local and remote references.
#
# Returns an object with three keys: `heads`, `remotes`, and `tags`. Each key
# can be an array of strings containing the reference names.
# Returns an {Object} with the following keys:
# :heads - An {Array} of head reference names.
# :remotes - An {Array} of remote reference names.
# :tags - An {Array} of tag reference names.
getReferences: -> @getRepo().getReferences()
# Public: Returns the number of commits behind the current branch is from the
# default remote branch.
# its upstream remote branch.
getAheadBehindCount: (reference) -> @getRepo().getAheadBehindCount(reference)
# Public: Returns true if the given branch exists.
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
# Private: Refreshes the current git status in an outside process and
# asynchronously updates the relevant properties.
# Refreshes the current git status in an outside process and asynchronously
# updates the relevant properties.
refreshStatus: ->
@statusTask = Task.once require.resolve('./repository-status-handler'), @getPath(), ({statuses, upstream, branch}) =>
statusesUnchanged = _.isEqual(statuses, @statuses) and _.isEqual(upstream, @upstream) and _.isEqual(branch, @branch)

View File

@@ -2,14 +2,11 @@
{Range} = require 'text-buffer'
_ = require 'underscore-plus'
# Private: Represents the portion of the {EditorView} containing row numbers.
# Represents the portion of the {EditorView} containing row numbers.
#
# The gutter also indicates if rows are folded.
module.exports =
class GutterView extends View
### Internal ###
@content: ->
@div class: 'gutter', =>
@div outlet: 'lineNumbers', class: 'line-numbers'
@@ -51,8 +48,6 @@ class GutterView extends View
$(document).on "mousemove.gutter-#{editorView.id}", moveHandler
$(document).one "mouseup.gutter-#{editorView.id}", => $(document).off 'mousemove', moveHandler
### Public ###
# Retrieves the containing {EditorView}.
#
# Returns an {EditorView}.
@@ -138,8 +133,6 @@ class GutterView extends View
el.classList.remove(klass) if hasClass
classesRemoved
### Internal ###
updateLineNumbers: (changes, startScreenRow, endScreenRow) ->
# Check if we have something already rendered that overlaps the requested range
updateAllLines = not (startScreenRow? and endScreenRow?)
@@ -223,7 +216,7 @@ class GutterView extends View
html
# Private: Called to update the 'foldable' class of line numbers when there's
# Called to update the 'foldable' class of line numbers when there's
# a change to the display buffer that doesn't regenerate all the line numbers
# anyway.
updateFoldableClasses: (changes) ->

View File

@@ -2,8 +2,6 @@ _ = require 'underscore-plus'
fs = require 'fs-plus'
{specificity} = require 'clear-cut'
### Internal ###
module.exports =
class KeyBinding
@parser: null

View File

@@ -43,10 +43,8 @@ class Keymap
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
# that match a keystroke and element.
#
# * keystroke:
# The string representing the keys pressed (e.g. ctrl-P).
# * element:
# The DOM node that will match a {KeyBinding}'s selector.
# keystroke - The {String} representing the keys pressed (e.g. ctrl-P).
# element - The DOM node that will match a {KeyBinding}'s selector.
keyBindingsForKeystrokeMatchingElement: (keystroke, element) ->
keyBindings = @keyBindingsForKeystroke(keystroke)
@keyBindingsMatchingElement(element, keyBindings)
@@ -54,41 +52,37 @@ class Keymap
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
# that match a command.
#
# * command:
# The string representing the command (tree-view:toggle)
# * element:
# The DOM node that will match a {KeyBinding}'s selector.
# command - The {String} representing the command (tree-view:toggle).
# element - The DOM node that will match a {KeyBinding}'s selector.
keyBindingsForCommandMatchingElement: (command, element) ->
keyBindings = @keyBindingsForCommand(command)
@keyBindingsMatchingElement(element, keyBindings)
# Public: Returns an array of {KeyBinding}s that match a keystroke
# * keystroke:
# The string representing the keys pressed (e.g. ctrl-P)
#
# keystroke: The {String} representing the keys pressed (e.g. ctrl-P)
keyBindingsForKeystroke: (keystroke) ->
keystroke = KeyBinding.normalizeKeystroke(keystroke)
@keyBindings.filter (keyBinding) -> keyBinding.matches(keystroke)
# Public: Returns an array of {KeyBinding}s that match a command
# * keystroke:
# The string representing the keys pressed (e.g. ctrl-P)
#
# keystroke - The {String} representing the keys pressed (e.g. ctrl-P)
keyBindingsForCommand: (command) ->
@keyBindings.filter (keyBinding) -> keyBinding.command == command
# Public: Returns a array of {KeyBinding}s (sorted by selector specificity)
# whos selector matches the element.
#
# * element:
# The DOM node that will match a {KeyBinding}'s selector.
# element - The DOM node that will match a {KeyBinding}'s selector.
keyBindingsMatchingElement: (element, keyBindings=@keyBindings) ->
keyBindings = keyBindings.filter ({selector}) -> $(element).closest(selector).length > 0
keyBindings.sort (a, b) -> a.compare(b)
# Public: Returns a keystroke string derived from an event.
# * event:
# A DOM or jQuery event
# * previousKeystroke:
# An optional string used for multiKeystrokes
#
# event - A DOM or jQuery event.
# previousKeystroke - An optional string used for multiKeystrokes.
keystrokeStringForEvent: (event, previousKeystroke) ->
if event.originalEvent.keyIdentifier.indexOf('U+') == 0
hexCharCode = event.originalEvent.keyIdentifier[2..]

View File

@@ -3,8 +3,6 @@ _ = require 'underscore-plus'
{OnigRegExp} = require 'oniguruma'
{Emitter, Subscriber} = require 'emissary'
### Internal ###
module.exports =
class LanguageMode
Emitter.includeInto(this)
@@ -15,13 +13,9 @@ class LanguageMode
editor: null
currentGrammarScore: null
### Internal ###
destroy: ->
@unsubscribe()
### Public ###
# Sets up a `LanguageMode` for the given {Editor}.
#
# editor - The {Editor} to associate with
@@ -187,7 +181,7 @@ class LanguageMode
isFoldableAtBufferRow: (bufferRow) ->
@isFoldableCodeAtBufferRow(bufferRow) or @isFoldableCommentAtBufferRow(bufferRow)
# Private: Returns a {Boolean} indicating whether the given buffer row starts
# Returns a {Boolean} indicating whether the given buffer row starts
# a a foldable row range due to the code's indentation patterns.
isFoldableCodeAtBufferRow: (bufferRow) ->
return false if @editor.isBufferRowBlank(bufferRow) or @isLineCommentedAtBufferRow(bufferRow)
@@ -195,14 +189,14 @@ class LanguageMode
return false unless nextNonEmptyRow?
@editor.indentationForBufferRow(nextNonEmptyRow) > @editor.indentationForBufferRow(bufferRow)
# Private: Returns a {Boolean} indicating whether the given buffer row starts
# Returns a {Boolean} indicating whether the given buffer row starts
# a foldable row range due to being the start of a multi-line comment.
isFoldableCommentAtBufferRow: (bufferRow) ->
@isLineCommentedAtBufferRow(bufferRow) and
@isLineCommentedAtBufferRow(bufferRow + 1) and
not @isLineCommentedAtBufferRow(bufferRow - 1)
# Private: Returns a {Boolean} indicating whether the line at the given buffer
# Returns a {Boolean} indicating whether the line at the given buffer
# row is a comment.
isLineCommentedAtBufferRow: (bufferRow) ->
return false unless 0 <= bufferRow <= @editor.getLastBufferRow()

View File

@@ -5,7 +5,7 @@ LessCache = require 'less-cache'
tmpDir = if process.platform is 'win32' then os.tmpdir() else '/tmp'
# Private: {LessCache} wrapper used by {ThemeManager} to read stylesheets.
# {LessCache} wrapper used by {ThemeManager} to read stylesheets.
module.exports =
class LessCompileCache
Subscriber.includeInto(this)

View File

@@ -13,26 +13,36 @@ module.exports =
class MenuManager
pendingUpdateOperation: null
# Private:
constructor: ({@resourcePath}) ->
@template = []
atom.keymap.on 'bundled-keymaps-loaded', => @loadPlatformItems()
# Public: Adds the given item definition to the existing template.
#
# * item:
# An object which describes a menu item as defined by
# https://github.com/atom/atom-shell/blob/master/docs/api/browser/menu.md
# ## Example
# ```coffee
# atom.menu.add [
# {
# label: 'Hello'
# submenu : [{label: 'World!', command: 'hello:world'}]
# }
# ]
# ```
#
# items - An {Array} of menu item {Object}s containing the keys:
# :label - The {String} menu label.
# :submenu - An optional {Array} of sub menu items.
# :command - An option {String} command to trigger when the item is clicked.
#
# Returns nothing.
add: (items) ->
@merge(@template, item) for item in items
@update()
# Private: Should the binding for the given selector be included in the menu
# Should the binding for the given selector be included in the menu
# commands.
#
# * selector: A String selector to check.
# selector - A {String} selector to check.
#
# Returns true to include the selector, false otherwise.
includeSelector: (selector) ->
@@ -59,14 +69,13 @@ class MenuManager
keystrokesByCommand[binding.command].push binding.keystroke
@sendToBrowserProcess(@template, keystrokesByCommand)
# Private:
loadPlatformItems: ->
menusDirPath = path.join(@resourcePath, 'menus')
platformMenuPath = fs.resolve(menusDirPath, process.platform, ['cson', 'json'])
{menu} = CSON.readFileSync(platformMenuPath)
@add(menu)
# Private: Merges an item in a submenu aware way such that new items are always
# Merges an item in a submenu aware way such that new items are always
# appended to the bottom of existing menus where possible.
merge: (menu, item) ->
item = _.deepClone(item)
@@ -76,7 +85,7 @@ class MenuManager
else
menu.push(item) unless _.find(menu, (i) => @normalizeLabel(i.label) == @normalizeLabel(item.label))
# Private: OSX can't handle displaying accelerators for multiple keystrokes.
# OSX can't handle displaying accelerators for multiple keystrokes.
# If they are sent across, it will stop processing accelerators for the rest
# of the menu items.
filterMultipleKeystroke: (keystrokesByCommand) ->
@@ -89,12 +98,10 @@ class MenuManager
filtered[key].push(binding)
filtered
# Private:
sendToBrowserProcess: (template, keystrokesByCommand) ->
keystrokesByCommand = @filterMultipleKeystroke(keystrokesByCommand)
ipc.sendChannel 'update-application-menu', template, keystrokesByCommand
# Private:
normalizeLabel: (label) ->
return undefined unless label?

View File

@@ -24,7 +24,6 @@ module.exports =
class PackageManager
Emitter.includeInto(this)
# Private:
constructor: ({configDirPath, devMode, @resourcePath}) ->
@packageDirPaths = [path.join(configDirPath, "packages")]
if devMode
@@ -48,11 +47,9 @@ class PackageManager
getPackageDirPaths: ->
_.clone(@packageDirPaths)
# Private:
getPackageState: (name) ->
@packageStates[name]
# Private:
setPackageState: (name, state) ->
@packageStates[name] = state
@@ -68,24 +65,23 @@ class PackageManager
pack?.disable()
pack
# Private: Activate all the packages that should be activated.
# Activate all the packages that should be activated.
activate: ->
for [activator, types] in @packageActivators
packages = @getLoadedPackagesForTypes(types)
activator.activatePackages(packages)
@emit 'activated'
# Private: another type of package manager can handle other package types.
# another type of package manager can handle other package types.
# See ThemeManager
registerPackageActivator: (activator, types) ->
@packageActivators.push([activator, types])
# Private:
activatePackages: (packages) ->
@activatePackage(pack.name) for pack in packages
@observeDisabledPackages()
# Private: Activate a single package by name
# Activate a single package by name
activatePackage: (name, options={}) ->
if options.sync? or options.immediate?
return @activatePackageSync(name, options)
@@ -100,18 +96,18 @@ class PackageManager
# Deprecated
activatePackageSync: (name, options) ->
return pack if pack = @getActivePackage(name)
return pack if pack = @getActivePackage(name)
if pack = @loadPackage(name)
@activePackages[pack.name] = pack
pack.activateSync(options)
pack
# Private: Deactivate all packages
# Deactivate all packages
deactivatePackages: ->
@deactivatePackage(pack.name) for pack in @getActivePackages()
@unobserveDisabledPackages()
# Private: Deactivate the package with the given name
# Deactivate the package with the given name
deactivatePackage: (name) ->
if pack = @getActivePackage(name)
@setPackageState(pack.name, state) if state = pack.serialize?()
@@ -132,13 +128,11 @@ class PackageManager
isPackageActive: (name) ->
@getActivePackage(name)?
# Private:
unobserveDisabledPackages: ->
return unless @observingDisabledPackages
atom.config.unobserve('core.disabledPackages')
@observingDisabledPackages = false
# Private:
observeDisabledPackages: ->
return if @observingDisabledPackages
@@ -152,7 +146,6 @@ class PackageManager
@observingDisabledPackages = true
# Private:
loadPackages: ->
# Ensure atom exports is already in the require cache so the load time
# of the first package isn't skewed by being the first to require atom
@@ -164,7 +157,6 @@ class PackageManager
@loadPackage(packagePath) for packagePath in packagePaths
@emit 'loaded'
# Private:
loadPackage: (nameOrPath) ->
if packagePath = @resolvePackagePath(nameOrPath)
name = path.basename(nameOrPath)
@@ -176,12 +168,10 @@ class PackageManager
else
throw new Error("Could not resolve '#{nameOrPath}' to a package path")
# Private:
unloadPackages: ->
@unloadPackage(name) for name in _.keys(@loadedPackages)
null
# Private:
unloadPackage: (name) ->
if @isPackageActive(name)
throw new Error("Tried to unload active package '#{name}'")
@@ -203,9 +193,9 @@ class PackageManager
getLoadedPackages: ->
_.values(@loadedPackages)
# Private: Get packages for a certain package type
# Get packages for a certain package type
#
# * types: an {Array} of {String}s like ['atom', 'textmate']
# types - an {Array} of {String}s like ['atom', 'textmate'].
getLoadedPackagesForTypes: (types) ->
pack for pack in @getLoadedPackages() when pack.getType() in types
@@ -223,7 +213,6 @@ class PackageManager
isPackageDisabled: (name) ->
_.include(atom.config.get('core.disabledPackages') ? [], name)
# Private:
hasAtomEngine: (packagePath) ->
metadata = Package.loadMetadata(packagePath, true)
metadata?.engines?.atom?
@@ -232,7 +221,6 @@ class PackageManager
isBundledPackage: (name) ->
@getPackageDependencies().hasOwnProperty(name)
# Private:
getPackageDependencies: ->
unless @packageDependencies?
try

View File

@@ -1,7 +1,6 @@
CSON = require 'season'
{basename, join} = require 'path'
### Internal ###
module.exports =
class Package
@build: (path) ->
@@ -53,7 +52,6 @@ class Package
isTheme: ->
@metadata?.theme?
# Private:
measure: (key, fn) ->
startTime = Date.now()
value = fn()

View File

@@ -1,7 +1,6 @@
{View} = require './space-pen-extensions'
PaneView = null
### Internal ###
module.exports =
class PaneAxisView extends View
initialize: (@model) ->

View File

@@ -2,7 +2,6 @@
_ = require 'underscore-plus'
PaneAxisView = require './pane-axis-view'
# Internal:
module.exports =
class PaneColumnView extends PaneAxisView

View File

@@ -3,7 +3,7 @@ Delegator = require 'delegato'
PaneView = require './pane-view'
PaneContainer = require './pane-container'
# Private: Manages the list of panes within a {WorkspaceView}
# Manages the list of panes within a {WorkspaceView}
module.exports =
class PaneContainerView extends View
Delegator.includeInto(this)
@@ -27,8 +27,6 @@ class PaneContainerView extends View
viewClass = model.getViewClass()
model._view ?= new viewClass(model)
### Public ###
getRoot: ->
@children().first().view()

View File

@@ -86,6 +86,6 @@ class PaneContainer extends Model
itemDestroyed: (item) ->
@emit 'item-destroyed', item
# Private: Called by Model superclass when destroyed
# Called by Model superclass when destroyed
destroyed: ->
pane.destroy() for pane in @getPanes()

View File

@@ -2,8 +2,6 @@
_ = require 'underscore-plus'
PaneAxisView = require './pane-axis-view'
### Internal ###
module.exports =
class PaneRowView extends PaneAxisView
@content: ->

View File

@@ -31,7 +31,6 @@ class PaneView extends View
previousActiveItem: null
# Private:
initialize: (args...) ->
if args[0] instanceof Pane
@model = args[0]
@@ -97,7 +96,6 @@ class PaneView extends View
# Deprecated: Use ::activatePreviousItem
showPreviousItem: -> @activatePreviousItem()
# Private:
afterAttach: (onDom) ->
@focus() if @model.focused and onDom
@@ -167,11 +165,9 @@ class PaneView extends View
@unsubscribe(item) if typeof item.off is 'function'
@trigger 'pane:before-item-destroyed', [item]
# Private:
activeItemTitleChanged: =>
@trigger 'pane:active-item-title-changed'
# Private:
viewForItem: (item) ->
return unless item?
if item instanceof $
@@ -184,7 +180,6 @@ class PaneView extends View
@viewsByItem.set(item, view)
view
# Private:
@::accessor 'activeView', -> @viewForItem(@activeItem)
splitLeft: (items...) -> @model.splitLeft({items})._view
@@ -204,7 +199,6 @@ class PaneView extends View
beforeRemove: ->
@model.destroy() unless @model.isDestroyed()
# Private:
remove: (selector, keepData) ->
return super if keepData
@unsubscribe()

View File

@@ -27,7 +27,6 @@ class Pane extends Model
.map((activePane) => activePane is this)
.distinctUntilChanged()
# Private:
constructor: (params) ->
super
@@ -43,31 +42,31 @@ class Pane extends Model
@activate() if params?.active
# Private: Called by the Serializable mixin during serialization.
# Called by the Serializable mixin during serialization.
serializeParams: ->
items: compact(@items.map((item) -> item.serialize?()))
activeItemUri: @activeItem?.getUri?()
focused: @focused
active: @active
# Private: Called by the Serializable mixin during deserialization.
# Called by the Serializable mixin during deserialization.
deserializeParams: (params) ->
{items, activeItemUri} = params
params.items = compact(items.map (itemState) -> atom.deserializers.deserialize(itemState))
params.activeItem = find params.items, (item) -> item.getUri?() is activeItemUri
params
# Private: Called by the view layer to construct a view for this model.
# Called by the view layer to construct a view for this model.
getViewClass: -> PaneView ?= require './pane-view'
isActive: -> @active
# Private: Called by the view layer to indicate that the pane has gained focus.
# Called by the view layer to indicate that the pane has gained focus.
focus: ->
@focused = true
@activate() unless @isActive()
# Private: Called by the view layer to indicate that the pane has lost focus.
# Called by the view layer to indicate that the pane has lost focus.
blur: ->
@focused = false
true # if this is called from an event handler, don't cancel it
@@ -78,7 +77,6 @@ class Pane extends Model
@container?.activePane = this
@emit 'activated'
# Private:
getPanes: -> [this]
# Public: Get the items in this pane.
@@ -123,11 +121,9 @@ class Pane extends Model
# Public: Adds the item to the pane.
#
# * item:
# The item to add. It can be a model with an associated view or a view.
# * index:
# An optional index at which to add the item. If omitted, the item is
# added after the current active item.
# item - The item to add. It can be a model with an associated view or a view.
# index - An optional index at which to add the item. If omitted, the item is
# added after the current active item.
#
# Returns the added item
addItem: (item, index=@getActiveItemIndex() + 1) ->
@@ -140,12 +136,11 @@ class Pane extends Model
# Public: Adds the given items to the pane.
#
# * items:
# An {Array} of items to add. Items can be models with associated views
# or views. Any items that are already present in items will not be added.
# * index:
# An optional index at which to add the item. If omitted, the item is
# added after the current active item.
# items - An {Array} of items to add. Items can be models with associated
# views or views. Any items that are already present in items will
# not be added.
# index - An optional index at which to add the item. If omitted, the item is
# added after the current active item.
#
# Returns an {Array} of the added items
addItems: (items, index=@getActiveItemIndex() + 1) ->
@@ -153,7 +148,6 @@ class Pane extends Model
@addItem(item, index + i) for item, i in items
items
# Private:
removeItem: (item, destroying) ->
index = @items.indexOf(item)
return if index is -1
@@ -209,7 +203,7 @@ class Pane extends Model
destroy: ->
super unless @container?.isAlive() and @container?.getPanes().length is 1
# Private: Called by model superclass.
# Called by model superclass.
destroyed: ->
@container.activateNextPane() if @isActive()
item.destroy?() for item in @items.slice()
@@ -240,8 +234,9 @@ class Pane extends Model
# Public: Saves the specified item.
#
# * item: The item to save.
# * nextAction: An optional function which will be called after the item is saved.
# item - The item to save.
# nextAction - An optional function which will be called after the item is
# saved.
saveItem: (item, nextAction) ->
if item?.getUri?()
item.save?()
@@ -251,8 +246,9 @@ class Pane extends Model
# Public: Saves the given item at a prompted-for location.
#
# * item: The item to save.
# * nextAction: An optional function which will be called after the item is saved.
# item - The item to save.
# nextAction - An optional function which will be called after the item is
# saved.
saveItemAs: (item, nextAction) ->
return unless item?.saveAs?
@@ -281,15 +277,14 @@ class Pane extends Model
else
false
# Private:
copyActiveItem: ->
if @activeItem?
@activeItem.copy?() ? atom.deserializers.deserialize(@activeItem.serialize())
# Public: Creates a new pane to the left of the receiver.
#
# * params:
# + items: An optional array of items with which to construct the new pane.
# params - An object with keys:
# :items - An optional array of items with which to construct the new pane.
#
# Returns the new {Pane}.
splitLeft: (params) ->
@@ -297,8 +292,8 @@ class Pane extends Model
# Public: Creates a new pane to the right of the receiver.
#
# * params:
# + items: An optional array of items with which to construct the new pane.
# params - An object with keys:
# :items - An optional array of items with which to construct the new pane.
#
# Returns the new {Pane}.
splitRight: (params) ->
@@ -306,8 +301,8 @@ class Pane extends Model
# Public: Creates a new pane above the receiver.
#
# * params:
# + items: An optional array of items with which to construct the new pane.
# params - An object with keys:
# :items - An optional array of items with which to construct the new pane.
#
# Returns the new {Pane}.
splitUp: (params) ->
@@ -315,14 +310,13 @@ class Pane extends Model
# Public: Creates a new pane below the receiver.
#
# * params:
# + items: An optional array of items with which to construct the new pane.
# params - An object with keys:
# :items - An optional array of items with which to construct the new pane.
#
# Returns the new {Pane}.
splitDown: (params) ->
@split('vertical', 'after', params)
# Private:
split: (orientation, side, params) ->
if @parent.orientation isnt orientation
@parent.replaceChild(this, new PaneAxis({@container, orientation, children: [this]}))
@@ -335,7 +329,7 @@ class Pane extends Model
newPane.activate()
newPane
# Private: If the parent is a horizontal axis, returns its first child;
# If the parent is a horizontal axis, returns its first child;
# otherwise this pane.
findLeftmostSibling: ->
if @parent.orientation is 'horizontal'
@@ -343,7 +337,7 @@ class Pane extends Model
else
this
# Private: If the parent is a horizontal axis, returns its last child;
# If the parent is a horizontal axis, returns its last child;
# otherwise returns a new pane created by splitting this pane rightward.
findOrCreateRightmostSibling: ->
if @parent.orientation is 'horizontal'

View File

@@ -50,32 +50,29 @@ class Project extends Model
#
# An {Editor} will be used if no openers return a value.
#
# ## Example:
# ## Example
# ```coffeescript
# atom.project.registerOpener (filePath) ->
# if path.extname(filePath) is '.toml'
# return new TomlEditor(filePath)
# ```
#
# * opener: A function to be called when a path is being opened.
# opener - A {Function} to be called when a path is being opened.
registerOpener: (opener) -> @openers.push(opener)
# Public: Remove a previously registered opener.
unregisterOpener: (opener) -> _.remove(@openers, opener)
# Private:
destroyed: ->
editor.destroy() for editor in @getEditors()
buffer.destroy() for buffer in @getBuffers()
@destroyRepo()
# Private:
destroyRepo: ->
if @repo?
@repo.destroy()
@repo = null
# Private:
destroyUnretainedBuffers: ->
buffer.destroy() for buffer in @getBuffers() when not buffer.isRetained()
@@ -111,8 +108,7 @@ class Project extends Model
# the path is already absolute or if it is prefixed with a scheme, it is
# returned unchanged.
#
# * uri:
# The String name of the path to convert
# uri - The {String} name of the path to convert.
#
# Returns a String.
resolve: (uri) ->
@@ -136,10 +132,8 @@ class Project extends Model
# Public: Given a path to a file, this constructs and associates a new
# {Editor}, showing the file.
#
# * filePath:
# The {String} path of the file to associate with
# * options:
# Options that you can pass to the {Editor} constructor
# filePath - The {String} path of the file to associate with.
# options - Options that you can pass to the {Editor} constructor.
#
# Returns a promise that resolves to an {Editor}.
open: (filePath, options={}) ->
@@ -153,7 +147,7 @@ class Project extends Model
@bufferForPath(filePath).then (buffer) =>
@buildEditorForBuffer(buffer, options)
# Private: Only be used in specs
# Only be used in specs
openSync: (filePath, options={}) ->
filePath = @resolve(filePath)
for opener in @openers
@@ -176,28 +170,27 @@ class Project extends Model
removeEditor: (editor) ->
_.remove(@editors, editor)
# Private: Retrieves all the {TextBuffer}s in the project; that is, the
# Retrieves all the {TextBuffer}s in the project; that is, the
# buffers for all open files.
#
# Returns an {Array} of {TextBuffer}s.
getBuffers: ->
@buffers.slice()
# Private: Is the buffer for the given path modified?
# Is the buffer for the given path modified?
isPathModified: (filePath) ->
@findBufferForPath(@resolve(filePath))?.isModified()
# Private:
findBufferForPath: (filePath) ->
_.find @buffers, (buffer) -> buffer.getPath() == filePath
# Private: Only to be used in specs
# Only to be used in specs
bufferForPathSync: (filePath) ->
absoluteFilePath = @resolve(filePath)
existingBuffer = @findBufferForPath(absoluteFilePath) if filePath
existingBuffer ? @buildBufferSync(absoluteFilePath)
# Private: Given a file path, this retrieves or creates a new {TextBuffer}.
# Given a file path, this retrieves or creates a new {TextBuffer}.
#
# If the `filePath` already has a `buffer`, that value is used instead. Otherwise,
# `text` is used as the contents of the new buffer.
@@ -210,21 +203,20 @@ class Project extends Model
existingBuffer = @findBufferForPath(absoluteFilePath) if absoluteFilePath
Q(existingBuffer ? @buildBuffer(absoluteFilePath))
# Private:
bufferForId: (id) ->
_.find @buffers, (buffer) -> buffer.id is id
# Private: DEPRECATED
# DEPRECATED
buildBufferSync: (absoluteFilePath) ->
buffer = new TextBuffer({filePath: absoluteFilePath})
@addBuffer(buffer)
buffer.loadSync()
buffer
# Private: Given a file path, this sets its {TextBuffer}.
# Given a file path, this sets its {TextBuffer}.
#
# absoluteFilePath - A {String} representing a path
# text - The {String} text to use as a buffer
# absoluteFilePath - A {String} representing a path.
# text - The {String} text to use as a buffer.
#
# Returns a promise that resolves to the {TextBuffer}.
buildBuffer: (absoluteFilePath) ->
@@ -234,38 +226,33 @@ class Project extends Model
.then((buffer) -> buffer)
.catch(=> @removeBuffer(buffer))
# Private:
addBuffer: (buffer, options={}) ->
@addBufferAtIndex(buffer, @buffers.length, options)
buffer.once 'destroyed', => @removeBuffer(buffer)
# Private:
addBufferAtIndex: (buffer, index, options={}) ->
@buffers.splice(index, 0, buffer)
buffer.once 'destroyed', => @removeBuffer(buffer)
@emit 'buffer-created', buffer
buffer
# Private: Removes a {TextBuffer} association from the project.
# Removes a {TextBuffer} association from the project.
#
# Returns the removed {TextBuffer}.
removeBuffer: (buffer) ->
index = @buffers.indexOf(buffer)
@removeBufferAtIndex(index) unless index is -1
# Private:
removeBufferAtIndex: (index, options={}) ->
[buffer] = @buffers.splice(index, 1)
buffer?.destroy()
# Public: Performs a search across all the files in the project.
#
# * regex:
# A RegExp to search with
# * options:
# - paths: an {Array} of glob patterns to search within
# * iterator:
# A Function callback on each file found
# regex - A {RegExp} to search with.
# options - An optional options {Object} (default: {}):
# :paths - An {Array} of glob patterns to search within
# iterator - A {Function} callback on each file found
scan: (regex, options={}, iterator) ->
if _.isFunction(options)
iterator = options
@@ -304,10 +291,11 @@ class Project extends Model
# Public: Performs a replace across all the specified files in the project.
#
# * regex: A RegExp to search with
# * replacementText: Text to replace all matches of regex with
# * filePaths: List of file path strings to run the replace on.
# * iterator: A Function callback on each file with replacements. `({filePath, replacements}) ->`
# regex - A {RegExp} to search with.
# replacementText - Text to replace all matches of regex with
# filePaths - List of file path strings to run the replace on.
# iterator - A {Function} callback on each file with replacements:
# `({filePath, replacements}) ->`.
replace: (regex, replacementText, filePaths, iterator) ->
deferred = Q.defer()
@@ -339,18 +327,15 @@ class Project extends Model
deferred.promise
# Private:
buildEditorForBuffer: (buffer, editorOptions) ->
editor = new Editor(_.extend({buffer}, editorOptions))
@addEditor(editor)
editor
# Private:
eachEditor: (callback) ->
callback(editor) for editor in @getEditors()
@on 'editor-created', (editor) -> callback(editor)
# Private:
eachBuffer: (args...) ->
subscriber = args.shift() if args.length > 1
callback = args.shift()

View File

@@ -1,4 +1,4 @@
# Private: Maintains the canonical map between screen and buffer positions.
# Maintains the canonical map between screen and buffer positions.
#
# Facilitates the mapping of screen rows to buffer rows and vice versa. All row
# ranges dealt with by this class are end-row exclusive. For example, a fold of

View File

@@ -2,8 +2,14 @@
# Public: Represents a view that scrolls.
#
# This `View` subclass listens to events such as `page-up`, `page-down`,
# `move-to-top`, and `move-to-bottom`.
# Subclasses must call `super` if overriding the `initialize` method or else
# the following events won't be handled by the ScrollView.
#
# ## Events
# * `core:page-up`
# * `core:page-down`
# * `core:move-to-top`
# * `core:move-to-bottom`
#
# ## Requiring in packages
#
@@ -12,8 +18,6 @@
# ```
module.exports =
class ScrollView extends View
# Internal: The constructor.
initialize: ->
@on 'core:page-up', => @pageUp()
@on 'core:page-down', => @pageDown()

View File

@@ -64,14 +64,14 @@ class SelectListView extends View
# Public: Set the array of items to display in the list.
#
# * array: The array of model elements to display in the list.
# array - The {Array} of model elements to display in the list.
setArray: (@array=[]) ->
@populateList()
@setLoading()
# Public: Set the error message to display.
#
# * message: The error message.
# message - The {String} error message (default: '').
setError: (message='') ->
if message.length is 0
@error.text('').hide()
@@ -81,7 +81,7 @@ class SelectListView extends View
# Public: Set the loading message to display.
#
# * message: The loading message.
# message - The {String} loading message (default: '').
setLoading: (message='') ->
if message.length is 0
@loading.text("")
@@ -131,8 +131,8 @@ class SelectListView extends View
#
# Subclasses may override this method to customize the message.
#
# * itemCount: The number of items in the array specified to {.setArray}
# * filteredItemCount: The number of items that pass the fuzzy filter test.
# itemCount - The {Number} of items in the array specified to {.setArray}
# filteredItemCount - The {Number} of items that pass the fuzzy filter test.
getEmptyMessage: (itemCount, filteredItemCount) -> 'No matches found'
selectPreviousItem: ->
@@ -184,7 +184,7 @@ class SelectListView extends View
#
# This method should be overridden by subclasses.
#
# * element: The selected model element.
# element - The selected model element.
confirmed: (element) ->
attach: ->

View File

@@ -1,7 +1,6 @@
{Point, Range} = require 'text-buffer'
{View, $$} = require './space-pen-extensions'
# Internal:
module.exports =
class SelectionView extends View

View File

@@ -14,7 +14,6 @@ class Selection
wordwise: false
needsAutoscroll: null
# Private:
constructor: ({@cursor, @marker, @editor}) ->
@cursor.selection = this
@marker.on 'changed', => @screenRangeChanged()
@@ -23,18 +22,15 @@ class Selection
@editor.removeSelection(this)
@emit 'destroyed' unless @editor.isDestroyed()
# Private:
destroy: ->
@marker.destroy()
# Private:
finalize: ->
@initialScreenRange = null unless @initialScreenRange?.isEqual(@getScreenRange())
if @isEmpty()
@wordwise = false
@linewise = false
# Private:
clearAutoscroll: ->
@needsAutoscroll = null
@@ -59,10 +55,8 @@ class Selection
# Public: Modifies the screen range for the selection.
#
# * screenRange:
# The new {Range} to use
# * options:
# + A hash of options matching those found in {.setBufferRange}
# screenRange - The new {Range} to use.
# options - A hash of options matching those found in {.setBufferRange}.
setScreenRange: (screenRange, options) ->
@setBufferRange(@editor.bufferRangeForScreenRange(screenRange), options)
@@ -72,13 +66,11 @@ class Selection
# Public: Modifies the buffer {Range} for the selection.
#
# * screenRange:
# The new {Range} to select
# * options
# + preserveFolds:
# if `true`, the fold settings are preserved after the selection moves
# + autoscroll:
# if `true`, the {Editor} scrolls to the new selection
# screenRange - The new {Range} to select.
# options - An {Object} with the keys:
# :preserveFolds - if `true`, the fold settings are preserved after the
# selection moves.
# :autoscroll - if `true`, the {Editor} scrolls to the new selection.
setBufferRange: (bufferRange, options={}) ->
bufferRange = Range.fromObject(bufferRange)
@needsAutoscroll = options.autoscroll
@@ -128,8 +120,7 @@ class Selection
# Public: Selects an entire line in the buffer.
#
# * row:
# The line Number to select (default: the row of the cursor)
# row - The line {Number} to select (default: the row of the cursor).
selectLine: (row=@cursor.getBufferPosition().row) ->
range = @editor.bufferRangeForBufferRow(row, includeNewline: true)
@setBufferRange(@getBufferRange().union(range))
@@ -148,8 +139,7 @@ class Selection
# Public: Selects the text from the current cursor position to a given screen
# position.
#
# * position:
# An instance of {Point}, with a given `row` and `column`.
# position - An instance of {Point}, with a given `row` and `column`.
selectToScreenPosition: (position) ->
@modifySelection =>
if @initialScreenRange
@@ -168,8 +158,7 @@ class Selection
# Public: Selects the text from the current cursor position to a given buffer
# position.
#
# * position:
# An instance of {Point}, with a given `row` and `column`.
# position - An instance of {Point}, with a given `row` and `column`.
selectToBufferPosition: (position) ->
@modifySelection => @cursor.setBufferPosition(position)
@@ -259,8 +248,6 @@ class Selection
@editor.addSelectionForBufferRange(range, goalBufferRange: range)
break
# Public:
#
# FIXME: I have no idea what this does.
getGoalBufferRange: ->
@marker.getAttributes().goalBufferRange
@@ -285,20 +272,14 @@ class Selection
# Public: Replaces text at the current selection.
#
# * text:
# A {String} representing the text to add
# * options
# + select:
# if `true`, selects the newly added text
# + autoIndent:
# if `true`, indents all inserted text appropriately
# + autoIndentNewline:
# if `true`, indent newline appropriately
# + autoDecreaseIndent:
# if `true`, decreases indent level appropriately (for example, when a
# closing bracket is inserted)
# + undo:
# if `skip`, skips the undo stack for this operation.
# text - A {String} representing the text to add
# options - An {Object} with keys:
# :select - if `true`, selects the newly added text.
# :autoIndent - if `true`, indents all inserted text appropriately.
# :autoIndentNewline - if `true`, indent newline appropriately.
# :autoDecreaseIndent - if `true`, decreases indent level appropriately
# (for example, when a closing bracket is inserted).
# :undo - if `skip`, skips the undo stack for this operation.
insertText: (text, options={}) ->
oldBufferRange = @getBufferRange()
@editor.destroyFoldsContainingBufferRow(oldBufferRange.end.row)
@@ -326,10 +307,8 @@ class Selection
# Public: Indents the given text to the suggested level based on the grammar.
#
# * text:
# The string to indent within the selection.
# * indentBasis:
# The beginning indent level.
# text - The {String} to indent within the selection.
# indentBasis - The beginning indent level.
normalizeIndents: (text, indentBasis) ->
textPrecedingCursor = @cursor.getCurrentBufferLine()[0...@cursor.getBufferColumn()]
isCursorInsideExistingLine = /\S/.test(textPrecedingCursor)
@@ -357,10 +336,9 @@ class Selection
# Public: Indents the selection.
#
# * options - A hash with one key,
# + autoIndent:
# If `true`, the indentation is performed appropriately. Otherwise,
# {Editor.getTabText} is used
# options - A {Object} with the keys:
# :autoIndent - If `true`, the indentation is performed appropriately.
# Otherwise, {Editor.getTabText} is used.
indent: ({ autoIndent }={})->
{ row, column } = @cursor.getBufferPosition()
@@ -505,25 +483,16 @@ class Selection
@editor.toggleLineCommentsForBufferRows(@getBufferRowRange()...)
# Public: Cuts the selection until the end of the line.
#
# * maintainClipboard:
# ?
cutToEndOfLine: (maintainClipboard) ->
@selectToEndOfLine() if @isEmpty()
@cut(maintainClipboard)
# Public: Copies the selection to the clipboard and then deletes it.
#
# * maintainClipboard:
# ?
cut: (maintainClipboard=false) ->
@copy(maintainClipboard)
@delete()
# Public: Copies the current selection to the clipboard.
#
# * maintainClipboard:
# ?
copy: (maintainClipboard=false) ->
return if @isEmpty()
text = @editor.buffer.getTextInRange(@getBufferRange())
@@ -540,14 +509,13 @@ class Selection
@editor.createFold(range.start.row, range.end.row)
@cursor.setBufferPosition([range.end.row + 1, 0])
# Public: ?
modifySelection: (fn) ->
@retainSelection = true
@plantTail()
fn()
@retainSelection = false
# Private: Sets the marker's tail to the same position as the marker's head.
# Sets the marker's tail to the same position as the marker's head.
#
# This only works if there isn't already a tail position.
#
@@ -557,8 +525,7 @@ class Selection
# Public: Identifies if a selection intersects with a given buffer range.
#
# * bufferRange:
# A {Range} to check against
# bufferRange - A {Range} to check against.
#
# Returns a Boolean.
intersectsBufferRange: (bufferRange) ->
@@ -566,8 +533,7 @@ class Selection
# Public: Identifies if a selection intersects with another selection.
#
# * otherSelection:
# A {Selection} to check against
# otherSelection - A {Selection} to check against.
#
# Returns a Boolean.
intersectsWith: (otherSelection) ->
@@ -576,10 +542,8 @@ class Selection
# Public: Combines the given selection into this selection and then destroys
# the given selection.
#
# * otherSelection:
# A {Selection} to merge with
# * options
# + A hash of options matching those found in {.setBufferRange}
# otherSelection - A {Selection} to merge with.
# options - A hash of options matching those found in {.setBufferRange}.
merge: (otherSelection, options) ->
myGoalBufferRange = @getGoalBufferRange()
otherGoalBufferRange = otherSelection.getGoalBufferRange()
@@ -595,12 +559,10 @@ class Selection
#
# See {Range.compare} for more details.
#
# * otherSelection:
# A {Selection} to compare with.
# otherSelection - A {Selection} to compare against.
compare: (otherSelection) ->
@getBufferRange().compare(otherSelection.getBufferRange())
# Private:
screenRangeChanged: ->
screenRange = @getScreenRange()
@emit 'screen-range-changed', screenRange

View File

@@ -1,18 +1,13 @@
_ = require 'underscore-plus'
spacePen = require 'space-pen'
{Subscriber} = require 'emissary'
ConfigObserver = require './config-observer'
ConfigObserver.includeInto(spacePen.View)
Subscriber.includeInto(spacePen.View)
jQuery = spacePen.jQuery
originalCleanData = jQuery.cleanData
jQuery.cleanData = (elements) ->
for element in elements
if view = jQuery(element).view()
view.unobserveConfig()
view.unsubscribe()
jQuery(element).view()?.unsubscribe() for element in elements
originalCleanData(elements)
tooltipDefaults =

View File

@@ -15,7 +15,6 @@ Token = require './token'
module.exports =
class Syntax extends GrammarRegistry
Subscriber.includeInto(this)
atom.deserializers.add(this)
@deserialize: ({grammarOverridesByPath}) ->
@@ -62,8 +61,8 @@ class Syntax extends GrammarRegistry
# console.log(comment) # '# '
# ```
#
# * scope: An {Array} of {String} scopes.
# * keyPath: A {String} key path.
# scope - An {Array} of {String} scopes.
# keyPath - A {String} key path.
#
# Returns a {String} property value or undefined.
getProperty: (scope, keyPath) ->

View File

@@ -24,11 +24,9 @@ class Task
# Public: A helper method to easily launch and run a task once.
#
# * taskPath:
# The path to the Coffeescript/Javascript file which exports a single
# function to execute.
# * args:
# The Array of arguments to pass to the exported function.
# taskPath - The {String} path to the CoffeeScript/JavaScript file which
# exports a single {Function} to execute.
# args - The arguments to pass to the exported function.
@once: (taskPath, args...) ->
task = new Task(taskPath)
task.once 'task:completed', -> task.terminate()
@@ -45,9 +43,8 @@ class Task
# Public: Creates a task.
#
# * taskPath:
# The path to the Coffeescript/Javascript file that exports a single
# function to execute.
# taskPath - The {String} path to the CoffeeScript/JavaScript file that
# exports a single {Function} to execute.
constructor: (taskPath) ->
coffeeCacheRequire = "require('#{require.resolve('./coffee-cache')}').register();"
coffeeScriptRequire = "require('#{require.resolve('coffee-script')}').register();"
@@ -73,7 +70,7 @@ class Task
@handleEvents()
# Private: Routes messages from the child to the appropriate event.
# Routes messages from the child to the appropriate event.
handleEvents: ->
@childProcess.removeAllListeners()
@childProcess.on 'message', ({event, args}) =>
@@ -81,21 +78,21 @@ class Task
# Public: Starts the task.
#
# * args:
# The Array of arguments to pass to the function exported by the script. If
# the last argument is a function, its removed from the array and called
# upon completion (and replaces the complete function on the task instance).
start: (args...) ->
# args - The arguments to pass to the function exported by this task's script.
# callback - An optional {Function} to call when the task completes.
start: (args..., callback) ->
throw new Error("Cannot start terminated process") unless @childProcess?
@handleEvents()
@callback = args.pop() if _.isFunction(args[args.length - 1])
if _.isFunction(callback)
@callback = callback
else
args = arguments
@send({event: 'start', args})
# Public: Send message to the task.
#
# * message:
# The message to send
# message - The message to send to the task.
send: (message) ->
throw new Error("Cannot send message to terminated process") unless @childProcess?
@childProcess.send(message)

View File

@@ -8,7 +8,7 @@ TextBufferCore = require 'text-buffer'
File = require './file'
# Private: Represents the contents of a file.
# Represents the contents of a file.
#
# The `TextBuffer` is often associated with a {File}. However, this is not always
# the case, as a `TextBuffer` could be an unsaved chunk of text.
@@ -40,7 +40,6 @@ class TextBuffer extends TextBufferCore
@load() if loadWhenAttached
# Private:
serializeParams: ->
params = super
_.extend params,
@@ -48,7 +47,6 @@ class TextBuffer extends TextBufferCore
modifiedWhenLastPersisted: @isModified()
digestWhenLastPersisted: @file?.getDigest()
# Private:
deserializeParams: (params) ->
params = super(params)
params.loadWhenAttached = true
@@ -71,8 +69,6 @@ class TextBuffer extends TextBufferCore
@clearUndoStack()
this
### Internal ###
handleTextChange: (event) =>
@conflict = false if @conflict and !@isModified()
@scheduleModifiedEvents()
@@ -127,8 +123,6 @@ class TextBuffer extends TextBufferCore
@file.on "moved", =>
@emit "path-changed", this
### Public ###
# Identifies if the buffer belongs to multiple editors.
#
# For example, if the {EditorView} was split.
@@ -145,11 +139,11 @@ class TextBuffer extends TextBufferCore
@emitModifiedStatusChanged(false)
@emit 'reloaded'
# Private: Rereads the contents of the file, and stores them in the cache.
# Rereads the contents of the file, and stores them in the cache.
updateCachedDiskContentsSync: ->
@cachedDiskContents = @file?.readSync() ? ""
# Private: Rereads the contents of the file, and stores them in the cache.
# Rereads the contents of the file, and stores them in the cache.
updateCachedDiskContents: ->
Q(@file?.read() ? "").then (contents) =>
@cachedDiskContents = contents
@@ -390,8 +384,6 @@ class TextBuffer extends TextBufferCore
return match[0][0] != '\t'
undefined
### Internal ###
change: (oldRange, newText, options={}) ->
@setTextInRange(oldRange, newText, options.normalizeLineEndings)

View File

@@ -4,8 +4,6 @@ _ = require 'underscore-plus'
fs = require 'fs-plus'
Q = require 'q'
### Internal ###
module.exports =
class TextMatePackage extends Package
@testName: (packageName) ->

View File

@@ -42,7 +42,7 @@ class ThemeManager
activatePackages: (themePackages) -> @activateThemes()
# Private: Get the enabled theme names from the config.
# Get the enabled theme names from the config.
#
# Returns an array of theme names in the order that they should be activated.
getEnabledThemeNames: ->
@@ -81,7 +81,7 @@ class ThemeManager
# Public: Set the list of enabled themes.
#
# * enabledThemeNames: An {Array} of {String} theme names.
# enabledThemeNames - An {Array} of {String} theme names.
setEnabledThemes: (enabledThemeNames) ->
atom.config.set('core.themes', enabledThemeNames)
@@ -144,8 +144,9 @@ class ThemeManager
#
# This supports both CSS and LESS stylsheets.
#
# * 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.
# 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) ->

View File

@@ -12,7 +12,7 @@ WhitespaceRegex = /\S/
MaxTokenLength = 20000
# Private: Represents a single unit of text as selected by a grammar.
# Represents a single unit of text as selected by a grammar.
module.exports =
class Token
value: null
@@ -21,15 +21,11 @@ class Token
isAtomic: null
isHardTab: null
### Internal ###
constructor: ({@value, @scopes, @isAtomic, @bufferDelta, @isHardTab}) ->
@screenDelta = @value.length
@bufferDelta ?= @screenDelta
@hasSurrogatePair = textUtils.hasSurrogatePair(@value)
### Public ###
isEqual: (other) ->
@value == other.value and _.isEqual(@scopes, other.scopes) and !!@isAtomic == !!other.isAtomic

View File

@@ -5,8 +5,6 @@ Serializable = require 'serializable'
TokenizedLine = require './tokenized-line'
Token = require './token'
### Internal ###
module.exports =
class TokenizedBuffer extends Model
Serializable.includeInto(this)

View File

@@ -1,7 +1,5 @@
_ = require 'underscore-plus'
### Internal ###
module.exports =
class TokenizedLine
constructor: ({tokens, @lineEnding, @ruleStack, @startBufferColumn, @fold, tabLength}) ->

View File

@@ -5,7 +5,7 @@ shell = require 'shell'
{Subscriber} = require 'emissary'
fs = require 'fs-plus'
# Private: Handles low-level events related to the window.
# Handles low-level events related to the window.
module.exports =
class WindowEventHandler
Subscriber.includeInto(this)
@@ -75,7 +75,7 @@ class WindowEventHandler
@handleNativeKeybindings()
# Private: Wire commands that should be handled by the native menu
# Wire commands that should be handled by the native menu
# for elements with the `.native-key-bindings` class.
handleNativeKeybindings: ->
menu = null

View File

@@ -66,14 +66,12 @@ class WorkspaceView extends View
audioBeep: true
destroyEmptyPanes: false
# Private:
@content: ->
@div class: 'workspace', tabindex: -1, =>
@div class: 'horizontal', outlet: 'horizontal', =>
@div class: 'vertical', outlet: 'vertical', =>
@div class: 'panes', outlet: 'panes'
# Private:
initialize: (@model) ->
@model ?= new Workspace
@@ -109,6 +107,7 @@ class WorkspaceView extends View
@command 'application:zoom', -> ipc.sendChannel('command', 'application:zoom')
@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-init-script', -> ipc.sendChannel('command', 'application:open-your-init-script')
@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')
@@ -158,7 +157,6 @@ class WorkspaceView extends View
message: "Commands installed."
detailedMessage: "The shell commands `atom` and `apm` are installed."
# Private:
handleFocus: (e) ->
if @getActivePane()
@getActivePane().focus()
@@ -173,7 +171,6 @@ class WorkspaceView extends View
$(document.body).focus()
true
# Private:
afterAttach: (onDom) ->
@focus() if onDom
@@ -195,7 +192,7 @@ class WorkspaceView extends View
setTitle: (title) ->
document.title = title
# Private: Returns an Array of all of the application's {EditorView}s.
# Returns an Array of all of the application's {EditorView}s.
getEditorViews: ->
@panes.find('.pane > .item-views > .editor').map(-> $(this).view()).toArray()
@@ -285,11 +282,11 @@ class WorkspaceView extends View
@on('editor:attached', attachedCallback)
off: => @off('editor:attached', attachedCallback)
# Private: Called by SpacePen
# Called by SpacePen
beforeRemove: ->
@model.destroy()
# Private: Destroys everything.
# Destroys everything.
remove: ->
editorView.remove() for editorView in @getEditorViews()
super

View File

@@ -24,7 +24,6 @@ class Workspace extends Model
fullScreen: false
destroyedItemUris: -> []
# Private:
constructor: ->
super
@subscribe @paneContainer, 'item-destroyed', @onPaneItemDestroyed
@@ -36,22 +35,24 @@ class Workspace extends Model
@open(atom.keymap.getUserKeymapPath())
when 'atom://.atom/config'
@open(atom.config.getUserConfigPath())
when 'atom://.atom/init-script'
@open(atom.getUserInitScriptPath())
# Private: Called by the Serializable mixin during deserialization
# Called by the Serializable mixin during deserialization
deserializeParams: (params) ->
params.paneContainer = PaneContainer.deserialize(params.paneContainer)
params
# Private: Called by the Serializable mixin during serialization.
# Called by the Serializable mixin during serialization.
serializeParams: ->
paneContainer: @paneContainer.serialize()
fullScreen: atom.isFullScreen()
# Public: Asynchronously opens a given a filepath in Atom.
#
# * filePath: A file path
# * options
# + initialLine: The buffer line number to open to.
# filePath - A {String} file path.
# options - An options {Object} (default: {}).
# :initialLine - The buffer line number to open to.
#
# Returns a promise that resolves to the {Editor} for the file URI.
open: (filePath, options={}) ->
@@ -77,7 +78,7 @@ class Workspace extends Model
.catch (error) ->
console.error(error.stack ? error)
# Private: Only used in specs
# Only used in specs
openSync: (uri, options={}) ->
{initialLine} = options
# TODO: Remove deprecated changeFocus option
@@ -146,16 +147,16 @@ class Workspace extends Model
fontSize = atom.config.get("editor.fontSize")
atom.config.set("editor.fontSize", fontSize - 1) if fontSize > 1
# Private: Removes the item's uri from the list of potential items to reopen.
# Removes the item's uri from the list of potential items to reopen.
itemOpened: (item) ->
if uri = item.getUri?()
remove(@destroyedItemUris, uri)
# Private: Adds the destroyed item's uri to the list of items to reopen.
# Adds the destroyed item's uri to the list of items to reopen.
onPaneItemDestroyed: (item) =>
if uri = item.getUri?()
@destroyedItemUris.push(uri)
# Private: Called by Model superclass when destroyed
# Called by Model superclass when destroyed
destroyed: ->
@paneContainer.destroy()