Merge branch 'master' into cj-update-docs

This commit is contained in:
Kevin Sawicki
2013-12-04 09:01:27 -08:00
30 changed files with 202 additions and 380 deletions

View File

@@ -20,6 +20,7 @@ module.exports = (grunt) ->
buildDir = grunt.option('build-dir') ? path.join(tmpDir, 'atom-build')
shellAppDir = path.join(buildDir, appName)
appDir = path.join(shellAppDir, 'resources', 'app')
atomShellDownloadDir = path.join(os.tmpdir(), 'atom-cached-atom-shells')
else
appName = 'Atom.app'
tmpDir = '/tmp'
@@ -28,6 +29,7 @@ module.exports = (grunt) ->
shellAppDir = path.join(buildDir, appName)
contentsDir = path.join(shellAppDir, 'Contents')
appDir = path.join(contentsDir, 'Resources', 'app')
atomShellDownloadDir = '/tmp/atom-cached-atom-shells'
installDir = path.join(installRoot, appName)
@@ -168,6 +170,12 @@ module.exports = (grunt) ->
_.extend(context, parsed.attributes)
parsed.body
'download-atom-shell':
version: packageJson.atomShellVersion
outputDir: 'atom-shell'
downloadDir: atomShellDownloadDir
rebuild: true # rebuild native modules after atom-shell is updated
shell:
'kill-atom':
command: 'pkill -9 Atom'
@@ -183,13 +191,14 @@ module.exports = (grunt) ->
grunt.loadNpmTasks('grunt-contrib-coffee')
grunt.loadNpmTasks('grunt-contrib-less')
grunt.loadNpmTasks('grunt-markdown')
grunt.loadNpmTasks('grunt-download-atom-shell')
grunt.loadNpmTasks('grunt-shell')
grunt.loadTasks('tasks')
grunt.registerTask('compile', ['coffee', 'prebuild-less', 'cson'])
grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint'])
grunt.registerTask('test', ['shell:kill-atom', 'run-specs'])
grunt.registerTask('ci', ['update-atom-shell', 'build', 'set-development-version', 'lint', 'test'])
grunt.registerTask('deploy', ['partial-clean', 'update-atom-shell', 'build', 'codesign'])
grunt.registerTask('ci', ['download-atom-shell', 'build', 'set-development-version', 'lint', 'test'])
grunt.registerTask('deploy', ['partial-clean', 'download-atom-shell', 'build', 'codesign'])
grunt.registerTask('docs', ['markdown:guides', 'build-docs'])
grunt.registerTask('default', ['update-atom-shell', 'build', 'set-development-version', 'install'])
grunt.registerTask('default', ['download-atom-shell', 'build', 'set-development-version', 'install'])

13
LICENSE.md Normal file
View File

@@ -0,0 +1,13 @@
Copyright 2013 GitHub Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -206,7 +206,7 @@ specific parts of the interface, like adding a file in the tree-view:
'context-menu':
'.tree-view':
'Add file': 'tree-view:add-file'
'#workspace-view':
'.workspace':
'Inspect Element': 'core:inspect'
```

View File

@@ -34,16 +34,21 @@
'escape': 'editor:consolidate-selections'
# allow standard input fields to work correctly
'input:not(.hidden-input), .native-key-bindings':
'body .native-key-bindings':
'tab': 'core:focus-next'
'shift-tab': 'core:focus-previous'
'enter': 'native!'
'backspace': 'native!'
'shift-backspace': 'native!'
'delete': 'native!'
'left': 'native!'
'right': 'native!'
'shift-left': 'native!'
'shift-right': 'native!'
'backspace': 'native!'
'shift-backspace': 'native!'
'delete': 'native!'
'alt-left': 'native!'
'alt-right': 'native!'
'alt-shift-left': 'native!'
'alt-shift-right': 'native!'
'ctrl-b': 'native!'
'ctrl-f': 'native!'
'ctrl-F': 'native!'

View File

@@ -146,7 +146,7 @@
'cmd-k cmd-9': 'editor:fold-at-indent-level-9'
# allow standard input fields to work correctly
'body.platform-darwin input:not(.hidden-input), body.platform-darwin .native-key-bindings':
'body.platform-darwin .native-key-bindings':
'cmd-z': 'native!'
'cmd-Z': 'native!'
'cmd-x': 'native!'

View File

@@ -165,7 +165,6 @@
{ label: "Install &update", command: 'application:install-update', visible: false }
{ type: 'separator' }
{ label: '&Documentation', command: 'application:open-documentation' }
{ label: 'Report an &Issue', command: 'application:report-issue' }
{ type: 'separator' }
]
}

View File

@@ -1,6 +1,6 @@
{
"name": "atom",
"version": "39.0.0",
"version": "0.40.0",
"main": "./src/browser/main.js",
"repository": {
"type": "git",
@@ -9,7 +9,13 @@
"bugs": {
"url": "https://github.com/atom/atom/issues"
},
"atomShellVersion": "0.6.11",
"licenses": [
{
"type": "Apache",
"url": "http://github.com/atom/atom/raw/master/LICENSE.md"
}
],
"atomShellVersion": "0.7.3",
"dependencies": {
"async": "0.2.6",
"bootstrap": "git://github.com/benogle/bootstrap.git",
@@ -35,7 +41,7 @@
"season": "0.14.0",
"semver": "1.1.4",
"space-pen": "2.0.1",
"telepath": "0.45.0",
"telepath": "0.45.1",
"temp": "0.5.0",
"underscore-plus": "0.3.0"
},
@@ -64,9 +70,9 @@
"rimraf": "~2.2.2"
},
"packageDependencies": {
"atom-light-ui": "0.9.0",
"atom-light-ui": "0.11.0",
"atom-light-syntax": "0.6.0",
"atom-dark-ui": "0.9.0",
"atom-dark-ui": "0.10.0",
"atom-dark-syntax": "0.6.0",
"base16-tomorrow-dark-theme": "0.6.0",
"solarized-dark-syntax": "0.4.0",
@@ -75,23 +81,24 @@
"autoflow": "0.11.0",
"autosave": "0.9.0",
"bookmarks": "0.15.0",
"bracket-matcher": "0.14.0",
"bracket-matcher": "0.15.0",
"command-logger": "0.8.0",
"command-palette": "0.11.0",
"dev-live-reload": "0.18.0",
"editor-stats": "0.8.0",
"exception-reporting": "0.8.0",
"find-and-replace": "0.54.0",
"feedback": "0.9.0",
"find-and-replace": "0.55.0",
"fuzzy-finder": "0.27.0",
"gists": "0.12.0",
"git-diff": "0.19.0",
"github-sign-in": "0.13.0",
"go-to-line": "0.12.0",
"grammar-selector": "0.13.0",
"image-view": "0.9.0",
"image-view": "0.10.0",
"keybinding-resolver": "0.6.0",
"link": "0.10.0",
"markdown-preview": "0.21.0",
"link": "0.11.0",
"markdown-preview": "0.22.0",
"metrics": "0.12.0",
"package-generator": "0.23.0",
"release-notes": "0.13.0",
@@ -100,13 +107,14 @@
"spell-check": "0.17.0",
"status-bar": "0.23.0",
"styleguide": "0.17.0",
"symbols-view": "0.26.0",
"tabs": "0.14.1",
"symbols-view": "0.27.0",
"tabs": "0.15.0",
"terminal": "0.23.0",
"timecop": "0.11.0",
"to-the-hubs": "0.15.0",
"tree-view": "0.41.0",
"tree-view": "0.42.0",
"visual-bell": "0.6.0",
"welcome": "0.1.0",
"whitespace": "0.10.0",
"wrap-guide": "0.8.0",
"language-c": "0.2.0",
@@ -141,7 +149,8 @@
"language-todo": "0.2.0",
"language-toml": "0.7.0",
"language-xml": "0.2.0",
"language-yaml": "0.1.0"
"language-yaml": "0.1.0",
"grunt-download-atom-shell": "0.1.1"
},
"private": true,
"scripts": {

Binary file not shown.

View File

@@ -2730,21 +2730,6 @@ describe "EditorView", ->
expect(buffer.lineForRow(15)).toBeUndefined()
expect(editorView.getCursorBufferPosition()).toEqual [13, 0]
describe "editor:save-debug-snapshot", ->
it "saves the state of the rendered lines, the display buffer, and the buffer to a file of the user's choosing", ->
saveDialogCallback = null
spyOn(atom, 'showSaveDialog').andCallFake (callback) -> saveDialogCallback = callback
spyOn(fs, 'writeFileSync')
editorView.trigger 'editor:save-debug-snapshot'
statePath = path.join(temp.dir, 'state')
expect(atom.showSaveDialog).toHaveBeenCalled()
saveDialogCallback(statePath)
expect(fs.writeFileSync).toHaveBeenCalled()
expect(fs.writeFileSync.argsForCall[0][0]).toBe statePath
expect(typeof fs.writeFileSync.argsForCall[0][1]).toBe 'string'
describe "when the escape key is pressed on the editor view", ->
it "clears multiple selections if there are any, and otherwise allows other bindings to be handled", ->
atom.keymap.bindKeys 'name', '.editor', 'escape': 'test-event'
@@ -2847,3 +2832,22 @@ describe "EditorView", ->
setEditorWidthInChars(editorView, 100)
$(window).trigger 'resize'
expect(editorView.editor.getSoftWrapColumn()).toBe 100
describe "character width caching", ->
describe "when soft wrap is enabled", ->
it "correctly calculates the the position left for a column", ->
editor.setSoftWrap(true)
editorView.setText('lllll 00000')
editorView.setFontFamily('serif')
editorView.setFontSize(10)
editorView.attachToDom()
editorView.setWidthInChars(5)
expect(editorView.pixelPositionForScreenPosition([0, 5]).left).toEqual 15
expect(editorView.pixelPositionForScreenPosition([1, 5]).left).toEqual 25
# Check that widths are actually being cached
spyOn(editorView, 'measureToColumn').andCallThrough()
editorView.pixelPositionForScreenPosition([0, 5])
editorView.pixelPositionForScreenPosition([1, 5])
expect(editorView.measureToColumn.callCount).toBe 0

View File

@@ -1,3 +1,6 @@
# Start the crash reporter before anything else.
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
try
require '../src/window'
Atom = require '../src/atom'

View File

@@ -352,6 +352,10 @@ class Atom
getVersion: ->
app.getVersion()
# Public: Gets the user agent of the atom instance.
getUserAgent: ->
"GitHubAtom/#{app.getVersion()}"
# Public: Get the directory path to Atom's configuration area.
#
# Returns the absolute path to ~/.atom

View File

@@ -349,8 +349,8 @@ class AtomApplication
# A Boolean which controls whether any newly opened windows should be in
# dev mode or not.
promptForPath: ({devMode}={}) ->
pathsToOpen = dialog.showOpenDialog title: 'Open', properties: ['openFile', 'openDirectory', 'multiSelections', 'createDirectory']
@openPaths({pathsToOpen, devMode})
dialog.showOpenDialog title: 'Open', properties: ['openFile', 'openDirectory', 'multiSelections', 'createDirectory'], (pathsToOpen) =>
@openPaths({pathsToOpen, devMode})
# Public: If an update is available, it returns the new version string
# otherwise it returns null.

View File

@@ -67,9 +67,7 @@ delegate.browserMainParts.preMainMessageLoopRun = ->
global.devResourcePath = path.join(app.getHomeDir(), 'github', 'atom')
setupCrashReporter = ->
crashReporter.setCompanyName 'GitHub'
crashReporter.setSubmissionUrl 'https://speakeasy.githubapp.com/submit_crash_log'
crashReporter.setAutoSubmit true
crashReporter.start(productName: 'Atom', companyName: 'GitHub')
setupAutoUpdater = ->
autoUpdater.setFeedUrl 'https://speakeasy.githubapp.com/apps/27/appcast.xml'
@@ -92,11 +90,11 @@ parseCommandLine = ->
options.alias('w', 'wait').boolean('w').describe('w', 'Wait for window to be closed before returning.')
args = options.argv
if args.h
if args.help
process.stdout.write(options.help())
process.exit(0)
if args.v
if args.version
process.stdout.write("#{version}\n")
process.exit(0)

View File

@@ -14,7 +14,7 @@ class ContextMenuManager
@devModeDefinitions = {}
@activeElement = null
@devModeDefinitions['#workspace-view'] = [
@devModeDefinitions['.workspace'] = [
label: 'Inspect Element'
command: 'application:inspect'
executeAtBuild: (e) ->

View File

@@ -584,12 +584,6 @@ class DisplayBuffer
line = @lineForRow(row).text
console.log row, line, line.length
getDebugSnapshot: ->
lines = ["Display Buffer:"]
for screenLine, row in @linesForRows(0, @getLastRow())
lines.push "#{row}: #{screenLine.text}"
lines.join('\n')
### Internal ###
handleTokenizedBufferChange: (tokenizedBufferChange) =>

View File

@@ -206,7 +206,6 @@ class EditorView extends View
'editor:duplicate-line': @duplicateLine
'editor:join-line': @joinLine
'editor:toggle-indent-guide': => atom.config.toggle('editor.showIndentGuide')
'editor:save-debug-snapshot': @saveDebugSnapshot
'editor:toggle-line-numbers': => atom.config.toggle('editor.showLineNumbers')
'editor:scroll-to-cursor': @scrollToCursorPosition
@@ -613,31 +612,34 @@ class EditorView extends View
# {Delegates to: Editor.getPath}
getPath: -> @editor?.getPath()
# {Delegates to: TextBuffer.getLineCount}
# {Delegates to: Editor.transact}
transact: (fn) -> @editor.transact(fn)
# {Delegates to: TextBuffer.getLineCount}
getLineCount: -> @getBuffer().getLineCount()
# {Delegates to: TextBuffer.getLastRow}
# {Delegates to: TextBuffer.getLastRow}
getLastBufferRow: -> @getBuffer().getLastRow()
# {Delegates to: TextBuffer.getTextInRange}
# {Delegates to: TextBuffer.getTextInRange}
getTextInRange: (range) -> @getBuffer().getTextInRange(range)
# {Delegates to: TextBuffer.getEofPosition}
# {Delegates to: TextBuffer.getEofPosition}
getEofPosition: -> @getBuffer().getEofPosition()
# {Delegates to: TextBuffer.lineForRow}
# {Delegates to: TextBuffer.lineForRow}
lineForBufferRow: (row) -> @getBuffer().lineForRow(row)
# {Delegates to: TextBuffer.lineLengthForRow}
# {Delegates to: TextBuffer.lineLengthForRow}
lineLengthForBufferRow: (row) -> @getBuffer().lineLengthForRow(row)
# {Delegates to: TextBuffer.rangeForRow}
# {Delegates to: TextBuffer.rangeForRow}
rangeForBufferRow: (row) -> @getBuffer().rangeForRow(row)
# {Delegates to: TextBuffer.scanInRange}
# {Delegates to: TextBuffer.scanInRange}
scanInBufferRange: (args...) -> @getBuffer().scanInRange(args...)
# {Delegates to: TextBuffer.backwardsScanInRange}
# {Delegates to: TextBuffer.backwardsScanInRange}
backwardsScanInBufferRange: (args...) -> @getBuffer().backwardsScanInRange(args...)
### Internal ###
@@ -975,9 +977,11 @@ class EditorView extends View
@setWidthInChars()
@editor.setSoftWrap(not @editor.getSoftWrap())
# Private:
calculateWidthInChars: ->
Math.floor(@scrollView.width() / @charWidth)
# Private:
calculateHeightInLines: ->
Math.ceil($(window).height() / @lineHeight)
@@ -1062,6 +1066,7 @@ class EditorView extends View
super
atom.workspaceView?.focus()
# Private:
beforeRemove: ->
@trigger 'editor:will-be-removed'
@removed = true
@@ -1588,36 +1593,32 @@ class EditorView extends View
@renderedLines[0].removeChild(lineElement)
{ top: row * @lineHeight, left }
positionLeftForLineAndColumn: (lineElement, screenRow, column) ->
return 0 if column == 0
positionLeftForLineAndColumn: (lineElement, screenRow, screenColumn) ->
return 0 if screenColumn == 0
bufferRow = @bufferRowsForScreenRows(screenRow, screenRow)[0] ? screenRow
bufferColumn = @bufferPositionForScreenPosition([screenRow, screenColumn]).column
tokenizedLine = @editor.displayBuffer.tokenizedBuffer.tokenizedLines[bufferRow]
left = 0
index = 0
startIndex = @bufferPositionForScreenPosition([screenRow, 0]).column
for token in tokenizedLine.tokens
for char in token.value
return left if index >= column
return left if index >= bufferColumn
val = @getCharacterWidthCache(token.scopes, char)
if val?
left += val
else
return @measureToColumn(lineElement, tokenizedLine, column)
if index >= startIndex
val = @getCharacterWidthCache(token.scopes, char)
if val?
left += val
else
return @measureToColumn(lineElement, tokenizedLine, screenColumn, startIndex)
index++
left
scopesForColumn: (tokenizedLine, column) ->
index = 0
for token in tokenizedLine.tokens
for char in token.value
return token.scopes if index == column
index++
null
measureToColumn: (lineElement, tokenizedLine, column) ->
# Private:
measureToColumn: (lineElement, tokenizedLine, screenColumn, lineStartBufferColumn) ->
left = oldLeft = index = 0
iterator = document.createNodeIterator(lineElement, NodeFilter.SHOW_TEXT, TextNodeFilter)
@@ -1631,13 +1632,13 @@ class EditorView extends View
for char, i in content
# Don't continue caching long lines :racehorse:
break if index > LongLineLength and column < index
break if index > LongLineLength and screenColumn < index
# Dont return right away, finish caching the whole line
returnLeft = left if index == column
returnLeft = left if index == screenColumn
oldLeft = left
scopes = @scopesForColumn(tokenizedLine, index)
scopes = tokenizedLine.tokenAtBufferColumn(lineStartBufferColumn + index)?.scopes
cachedCharWidth = @getCharacterWidthCache(scopes, char)
if cachedCharWidth?
@@ -1656,12 +1657,13 @@ class EditorView extends View
# Assume all the characters are the same width when dealing with long
# lines :racehorse:
return column * cachedCharWidth if index > LongLineLength
return screenColumn * cachedCharWidth if index > LongLineLength
index++
returnLeft ? left
# Private:
getCharacterWidthCache: (scopes, char) ->
scopes ?= NoScope
obj = EditorView.characterWidthCache
@@ -1670,6 +1672,7 @@ class EditorView extends View
return null unless obj?
obj[char]
# Private:
setCharacterWidthCache: (scopes, char, val) ->
scopes ?= NoScope
obj = EditorView.characterWidthCache
@@ -1678,6 +1681,7 @@ class EditorView extends View
obj = obj[scope]
obj[char] = val
# Private:
clearCharacterWidthCache: ->
EditorView.characterWidthCache = {}
@@ -1845,30 +1849,12 @@ class EditorView extends View
logCursorScope: ->
console.log @editor.getCursorScopes()
transact: (fn) -> @editor.transact(fn)
beginTransaction: -> @editor.beginTransaction()
commitTransaction: -> @editor.commitTransaction()
abortTransaction: -> @editor.abortTransaction()
saveDebugSnapshot: ->
atom.showSaveDialog (path) =>
fs.writeFileSync(path, @getDebugSnapshot()) if path
getDebugSnapshot: ->
[
"Debug Snapshot: #{@getPath()}"
@getRenderedLinesDebugSnapshot()
@editor.getDebugSnapshot()
@getBuffer().getDebugSnapshot()
].join('\n\n')
getRenderedLinesDebugSnapshot: ->
lines = ['Rendered Lines:']
firstRenderedScreenRow = @firstRenderedScreenRow
@renderedLines.find('.line').each (n) ->
lines.push "#{firstRenderedScreenRow + n}: #{$(this).text()}"
lines.join('\n')
logScreenLines: (start, end) ->
@editor.logScreenLines(start, end)

View File

@@ -12,7 +12,7 @@ TextMateScopeSelector = require('first-mate').ScopeSelector
# Public: The core model of Atom.
#
# An {Editor} represents a unique view of each document, with it's own
# An {Editor} represents a unique view of each document, with its own
# {Cursor}s and scroll position.
#
# For instance if a user creates a split, Atom creates a second {Editor}
@@ -1251,11 +1251,9 @@ class Editor
# Public: Transposes the current text selections.
#
# FIXME: I have no idea what this function does.
#
# This only works if there is more than one selection. Each selection is transferred
# to the position of the selection after it. The last selection is transferred to the
# position of the first.
# The text in each selection is reversed so `abcd` would become `dcba`. The
# characters before and after the cursor are swapped when the selection is
# empty so `x|y` would become `y|x` where `|` is the cursor location.
transpose: ->
@mutateSelectedText (selection) =>
if selection.isEmpty()
@@ -1437,10 +1435,3 @@ class Editor
# Private:
getSelectionMarkerAttributes: ->
type: 'selection', editorId: @id, invalidate: 'never'
# Private:
getDebugSnapshot: ->
[
@displayBuffer.getDebugSnapshot()
@displayBuffer.tokenizedBuffer.getDebugSnapshot()
].join('\n\n')

View File

@@ -226,6 +226,10 @@ class PackageManager
{@packageDependencies} = JSON.parse(fs.readFileSync(metadataPath)) ? {}
@packageDependencies ?= {}
# Temporarily ignore 'grunt-download-atom-shell' here, should remove this
# when it became a public npm module.
delete @packageDependencies['grunt-download-atom-shell']
@packageDependencies
# Public: Get an array of all the available package paths.

View File

@@ -70,7 +70,7 @@ class PaneAxis extends View
child.detach()
getContainer: ->
@closest('#panes').view()
@closest('.panes').view()
getActivePaneItem: ->
@getActivePane()?.activeItem

View File

@@ -16,7 +16,7 @@ class PaneContainer extends View
container
@content: ->
@div id: 'panes'
@div class: 'panes'
initialize: (state) ->
@destroyedItemStates = []

View File

@@ -412,7 +412,7 @@ class Pane extends View
# Private:
getContainer: ->
@closest('#panes').view()
@closest('.panes').view()
# Private:
copyActiveItem: ->

View File

@@ -105,18 +105,6 @@ class Project extends telepath.Model
getRootDirectory: ->
@rootDirectory
# Public: Determines if a path is ignored via Atom configuration.
isPathIgnored: (path) ->
for segment in path.split("/")
ignoredNames = atom.config.get("core.ignoredNames") or []
return true if _.contains(ignoredNames, segment)
@ignoreRepositoryPath(path)
# Public: Determines if a given path is ignored via repository configuration.
ignoreRepositoryPath: (repositoryPath) ->
atom.config.get("core.hideGitIgnoredFiles") and @repo?.isPathIgnored(path.join(@getPath(), repositoryPath))
# Public: Given a uri, this resolves it relative to the project directory. If
# the path is already absolute or if it is prefixed with a scheme, it is
# returned unchanged.
@@ -193,11 +181,13 @@ class Project extends telepath.Model
getBuffers: ->
new Array(@buffers.getValues()...)
# Private: Is the buffer for the given path modified?
isPathModified: (filePath) ->
@findBufferForPath(@resolve(filePath))?.isModified()
# Private:
findBufferForPath: (filePath) ->
_.find @buffers.getValues(), (buffer) -> buffer.getPath() == filePath
_.find @buffers.getValues(), (buffer) -> buffer.getPath() == filePath
# Private: Only to be used in specs
bufferForPathSync: (filePath) ->

View File

@@ -25,7 +25,10 @@ class SelectList extends View
inputThrottle: 50
cancelling: false
# Public:
# Public: Initialize the select list view.
#
# This method can be overridden by subclasses but `super` should always
# be called.
initialize: ->
@miniEditor.getBuffer().on 'changed', => @schedulePopulateList()
@miniEditor.hiddenInput.on 'focusout', => @cancel() unless @cancelling
@@ -57,12 +60,16 @@ class SelectList extends View
@populateList() if @isOnDom()
@scheduleTimeout = setTimeout(populateCallback, @inputThrottle)
# Public:
setArray: (@array) ->
# Public: Set the array of items to display in the list.
#
# * array: The array of model elements to display in the list.
setArray: (@array=[]) ->
@populateList()
@setLoading()
# Public:
# Public: Set the error message to display.
#
# * message: The error message.
setError: (message='') ->
if message.length is 0
@error.text('').hide()
@@ -70,7 +77,9 @@ class SelectList extends View
@setLoading()
@error.text(message).show()
# Public:
# Public: Set the loading message to display.
#
# * message: The loading message.
setLoading: (message='') ->
if message.length is 0
@loading.text("")
@@ -81,11 +90,18 @@ class SelectList extends View
@loading.text(message)
@loadingArea.show()
# Public:
# Public: Get the filter query to use when fuzzy filtering the visible
# elements.
#
# By default this method returns the text in the mini editor but it can be
# overridden by subclasses if needed.
#
# Returns a {String} to use when fuzzy filtering the elements to display.
getFilterQuery: ->
@miniEditor.getText()
# Public:
# Public: Build the DOM elements using the array from the last call to
# {.setArray}.
populateList: ->
return unless @array?
@@ -109,7 +125,12 @@ class SelectList extends View
else
@setError(@getEmptyMessage(@array.length, filteredArray.length))
# Public:
# Public: Get the message to display when there are no items.
#
# 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.
getEmptyMessage: (itemCount, filteredItemCount) -> 'No matches found'
# Private:
@@ -124,14 +145,14 @@ class SelectList extends View
item = @list.find('li:first') unless item.length
@selectItem(item)
# Public:
# Private:
selectItem: (item) ->
return unless item.length
@list.find('.selected').removeClass('selected')
item.addClass 'selected'
@scrollToItem(item)
# Public:
# Private:
scrollToItem: (item) ->
scrollTop = @list.scrollTop()
desiredTop = item.position().top + scrollTop
@@ -142,15 +163,19 @@ class SelectList extends View
else if desiredBottom > @list.scrollBottom()
@list.scrollBottom(desiredBottom)
# Public:
# Public: Get the selected DOM element.
#
# Call {.getSelectedElement} to get the selected model element.
getSelectedItem: ->
@list.find('li.selected')
# Public:
# Public: Get the selected model element.
#
# Call {.getSelectedItem} to get the selected DOM element.
getSelectedElement: ->
@getSelectedItem().data('select-list-element')
# Public:
# Private:
confirmSelection: ->
element = @getSelectedElement()
if element?
@@ -158,6 +183,13 @@ class SelectList extends View
else
@cancel()
# Public: Callback function for when a selection is made.
#
# This method should be overridden by subclasses.
#
# * element: The selected model element.
confirmed: (element) ->
# Private:
attach: ->
@storeFocusedElement()
@@ -173,12 +205,12 @@ class SelectList extends View
else
atom.workspaceView.focus()
# Public:
# Private:
cancelled: ->
@miniEditor.setText('')
@miniEditor.updateDisplay()
# Public:
# Public: Cancel and close the select list dialog.
cancel: ->
@list.empty()
@cancelling = true

View File

@@ -670,9 +670,3 @@ class TextBuffer extends telepath.Model
for row in [start..end]
line = @lineForRow(row)
console.log row, line, line.length
getDebugSnapshot: ->
lines = ['TextBuffer:']
for row in [0..@getLastRow()]
lines.push "#{row}: #{@lineForRow(row)}"
lines.join('\n')

View File

@@ -322,9 +322,3 @@ class TokenizedBuffer
for row in [start..end]
line = @lineForScreenRow(row).text
console.log row, line, line.length
getDebugSnapshot: ->
lines = ["Tokenized Buffer:"]
for screenLine, row in @linesForScreenRows(0, @getLastRow())
lines.push "#{row}: #{screenLine.text}"
lines.join('\n')

View File

@@ -1,6 +1,9 @@
# Like sands through the hourglass, so are the days of our lives.
startTime = Date.now()
# Start the crash reporter before anything else.
require('crash-reporter').start(productName: 'Atom', companyName: 'GitHub')
require './window'
Atom = require './atom'

View File

@@ -54,10 +54,10 @@ class WorkspaceView extends View
# Private:
@content: (state) ->
@div id: 'workspace', tabindex: -1, =>
@div id: 'horizontal', outlet: 'horizontal', =>
@div id: 'vertical', outlet: 'vertical', =>
@div outlet: 'panes'
@div class: 'workspace', tabindex: -1, =>
@div class: 'horizontal', outlet: 'horizontal', =>
@div class: 'vertical', outlet: 'vertical', =>
@div class: 'panes', outlet: 'panes'
# Private:
@deserialize: (state) ->

View File

@@ -21,19 +21,19 @@ h6 {
font-family: @font-family;
}
#workspace {
.workspace {
height: 100%;
overflow: hidden;
position: relative;
background-color: @app-background-color;
font-family: @font-family;
#horizontal {
.horizontal {
display: -webkit-flex;
height: 100%;
}
#vertical {
.vertical {
display: -webkit-flex;
-webkit-flex: 1;
-webkit-flex-flow: column;
@@ -45,7 +45,7 @@ h6 {
content: ""; // This is not a space, it is a skull and crossbones
}
padding: @component-icon-padding;
padding: 0 @component-icon-padding;
position: absolute;
top: 0;
right: 0;
@@ -57,7 +57,7 @@ h6 {
}
}
#panes {
.panes {
position: relative;
-webkit-flex: 1;

View File

@@ -1,210 +0,0 @@
fs = require 'fs'
path = require 'path'
os = require 'os'
request = require 'request'
formidable = require 'formidable'
unzip = require 'unzip'
module.exports = (grunt) ->
{spawn, mkdir, rm, cp} = require('./task-helpers')(grunt)
accessToken = null
getTokenFromKeychain = (callback) ->
accessToken ?= process.env['ATOM_ACCESS_TOKEN']
if accessToken
callback(null, accessToken)
return
spawn {cmd: 'security', args: ['-q', 'find-generic-password', '-ws', 'GitHub API Token']}, (error, result, code) ->
accessToken = result.stdout unless error?
callback(error, accessToken)
callAtomShellReposApi = (path, callback) ->
getTokenFromKeychain (error, accessToken) ->
if error
callback(error)
return
options =
url: "https://api.github.com/repos/atom/atom-shell#{path}"
proxy: process.env.http_proxy || process.env.https_proxy
headers:
authorization: "token #{accessToken}"
accept: 'application/vnd.github.manifold-preview'
'user-agent': 'Atom'
request options, (error, response, body) ->
if not error?
body = JSON.parse(body)
error = new Error(body.message) if response.statusCode != 200
callback(error, response, body)
findReleaseIdFromAtomShellVersion = (version, callback) ->
callAtomShellReposApi '/releases', (error, response, data) ->
if error?
grunt.log.error('GitHub API failed to access atom-shell releases')
callback(error)
else
for release in data when release.tag_name is version
callback(null, release.id)
return
grunt.log.error("There is no #{version} release of atom-shell")
callback(false)
getAtomShellDownloadUrl = (version, releaseId, callback) ->
callAtomShellReposApi "/releases/#{releaseId}/assets", (error, response, data) ->
if error?
grunt.log.error("Cannot get assets of atom-shell's #{version} release")
callback(error)
else
filename = "atom-shell-#{version}-#{process.platform}.zip"
for asset in data when asset.name is filename and asset.state is 'uploaded'
callback(null, asset.url)
return
grunt.log.error("Cannot get url of atom-shell's release asset")
callback(false)
getAtomShellVersion = ->
versionPath = path.join('atom-shell', 'version')
if grunt.file.isFile(versionPath)
grunt.file.read(versionPath).trim()
else
null
getTempDir = ->
if process.platform is 'win32' then os.tmpdir() else '/tmp'
getCachePath = (version) ->
path.join(getTempDir(), 'atom-cached-atom-shells', version)
isAtomShellVersionCached = (version) ->
grunt.file.isFile(getCachePath(version), 'version')
getDownloadOptions = (version, url, callback) ->
options =
url: url
followRedirect: false
proxy: process.env.http_proxy || process.env.https_proxy
# Only set headers for GitHub host, the url could also be a S3 link and
# setting headers for it would make the request fail.
if require('url').parse(url).hostname is 'api.github.com'
getTokenFromKeychain (error, accessToken) ->
options.headers =
authorization: "token #{accessToken}"
accept: 'application/octet-stream'
'user-agent': 'Atom'
callback(error, options)
else
callback(null, options)
downloadAtomShell = (version, url, callback) ->
getDownloadOptions version, url, (error, options) ->
if error
callback(error)
return
inputStream = request(options)
inputStream.on 'response', (response) ->
if response.statusCode is 302
# Manually handle redirection so headers would not be sent for S3.
downloadAtomShell(version, response.headers.location, callback)
else if response.statusCode is 200
grunt.verbose.writeln("Downloading atom-shell version #{version.cyan}")
cacheDirectory = getCachePath(version)
rm(cacheDirectory)
mkdir(cacheDirectory)
form = new formidable.IncomingForm()
form.uploadDir = cacheDirectory
form.maxFieldsSize = 100 * 1024 * 1024
form.on 'file', (name, file) ->
cacheFile = path.join(cacheDirectory, 'atom-shell.zip')
fs.renameSync(file.path, cacheFile)
callback(null, cacheFile)
form.parse response, (error) ->
if error
grunt.log.error("atom-shell #{version.cyan} failed to download")
else
if response.statusCode is 404
grunt.log.error("atom-shell #{version.cyan} not found")
else
grunt.log.error("atom-shell #{version.cyan} request failed")
callback(false)
downloadAtomShellOfVersion = (version, callback) ->
findReleaseIdFromAtomShellVersion version, (error, releaseId) ->
if error?
callback(error)
else
getAtomShellDownloadUrl version, releaseId, (error, url) ->
if error?
callback(error)
else
downloadAtomShell version, url, callback
unzipAtomShell = (zipPath, callback) ->
grunt.verbose.writeln('Unzipping atom-shell')
directoryPath = path.dirname(zipPath)
if process.platform is 'darwin'
# The zip archive of darwin build contains symbol links, only the "unzip"
# command can handle it correctly.
spawn {cmd: 'unzip', args: [zipPath, '-d', directoryPath]}, (error) ->
rm(zipPath)
callback(error)
else
fileStream = fs.createReadStream(zipPath)
fileStream.on('error', callback)
zipStream = fileStream.pipe(unzip.Extract(path: directoryPath))
zipStream.on('error', callback)
zipStream.on 'close', ->
rm(zipPath)
callback(null)
rebuildNativeModules = (previousVersion, callback) ->
newVersion = getAtomShellVersion()
if newVersion and newVersion isnt previousVersion
grunt.verbose.writeln("Rebuilding native modules for new atom-shell version #{newVersion.cyan}.")
cmd = path.join('node_modules', '.bin', 'apm')
cmd += ".cmd" if process.platform is 'win32'
spawn {cmd, args: ['rebuild']}, (error) -> callback(error)
else
callback()
installAtomShell = (version) ->
rm('atom-shell')
cp(getCachePath(version), 'atom-shell')
grunt.registerTask 'update-atom-shell', 'Update atom-shell', ->
done = @async()
{atomShellVersion} = grunt.file.readJSON('package.json')
if atomShellVersion
atomShellVersion = "v#{atomShellVersion}"
currentAtomShellVersion = getAtomShellVersion()
if atomShellVersion isnt currentAtomShellVersion
if isAtomShellVersionCached(atomShellVersion)
grunt.verbose.writeln("Installing cached atom-shell #{atomShellVersion.cyan}")
installAtomShell(atomShellVersion)
rebuildNativeModules(currentAtomShellVersion, done)
else
downloadAtomShellOfVersion atomShellVersion, (error, zipPath) ->
if error?
done(error)
else if zipPath?
unzipAtomShell zipPath, (error) ->
if error?
done(error)
else
grunt.verbose.writeln("Installing atom-shell #{atomShellVersion.cyan}")
installAtomShell(atomShellVersion)
rebuildNativeModules(currentAtomShellVersion, done)
else
done(false)
else
done()
else
grunt.log.error("atom-shell version missing from package.json")
done(false)

2
vendor/apm vendored

Submodule vendor/apm updated: 809d8d42f7...49b1e740f6