diff --git a/Gruntfile.coffee b/Gruntfile.coffee index 7e8b30bb2..35801d193 100644 --- a/Gruntfile.coffee +++ b/Gruntfile.coffee @@ -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']) diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 000000000..4d1c86e77 --- /dev/null +++ b/LICENSE.md @@ -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. diff --git a/docs/creating-a-package.md b/docs/creating-a-package.md index e951c2e66..7f9864d41 100644 --- a/docs/creating-a-package.md +++ b/docs/creating-a-package.md @@ -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' ``` diff --git a/keymaps/base.cson b/keymaps/base.cson index ba4a71e08..dd8a5973b 100644 --- a/keymaps/base.cson +++ b/keymaps/base.cson @@ -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!' diff --git a/keymaps/darwin.cson b/keymaps/darwin.cson index ddddc5783..d19ae9ac3 100644 --- a/keymaps/darwin.cson +++ b/keymaps/darwin.cson @@ -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!' diff --git a/menus/win32.cson b/menus/win32.cson index 2c9024401..e0e8d9a34 100644 --- a/menus/win32.cson +++ b/menus/win32.cson @@ -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' } ] } diff --git a/package.json b/package.json index fef12e807..a2c130902 100644 --- a/package.json +++ b/package.json @@ -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": { diff --git a/resources/mac/file.icns b/resources/mac/file.icns index 3f65ab726..2c366fdb9 100644 Binary files a/resources/mac/file.icns and b/resources/mac/file.icns differ diff --git a/spec/editor-view-spec.coffee b/spec/editor-view-spec.coffee index 4f773e40e..c7fc72a6f 100644 --- a/spec/editor-view-spec.coffee +++ b/spec/editor-view-spec.coffee @@ -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 diff --git a/spec/spec-bootstrap.coffee b/spec/spec-bootstrap.coffee index 07ce34b89..f2b2fd7fe 100644 --- a/spec/spec-bootstrap.coffee +++ b/spec/spec-bootstrap.coffee @@ -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' diff --git a/src/atom.coffee b/src/atom.coffee index be1b3af49..6fb271322 100644 --- a/src/atom.coffee +++ b/src/atom.coffee @@ -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 diff --git a/src/browser/atom-application.coffee b/src/browser/atom-application.coffee index 0bc6d0add..75b978e72 100644 --- a/src/browser/atom-application.coffee +++ b/src/browser/atom-application.coffee @@ -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. diff --git a/src/browser/main.coffee b/src/browser/main.coffee index 5bce464ed..f93063ac5 100644 --- a/src/browser/main.coffee +++ b/src/browser/main.coffee @@ -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) diff --git a/src/context-menu-manager.coffee b/src/context-menu-manager.coffee index 81d7580ea..2cbfe0364 100644 --- a/src/context-menu-manager.coffee +++ b/src/context-menu-manager.coffee @@ -14,7 +14,7 @@ class ContextMenuManager @devModeDefinitions = {} @activeElement = null - @devModeDefinitions['#workspace-view'] = [ + @devModeDefinitions['.workspace'] = [ label: 'Inspect Element' command: 'application:inspect' executeAtBuild: (e) -> diff --git a/src/display-buffer.coffee b/src/display-buffer.coffee index 9ffadc5ed..938551e85 100644 --- a/src/display-buffer.coffee +++ b/src/display-buffer.coffee @@ -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) => diff --git a/src/editor-view.coffee b/src/editor-view.coffee index 71431c8b9..0b5076ba9 100644 --- a/src/editor-view.coffee +++ b/src/editor-view.coffee @@ -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) diff --git a/src/editor.coffee b/src/editor.coffee index 48adc43cc..3e97bf451 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -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') diff --git a/src/package-manager.coffee b/src/package-manager.coffee index e94a69785..a85e51e43 100644 --- a/src/package-manager.coffee +++ b/src/package-manager.coffee @@ -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. diff --git a/src/pane-axis.coffee b/src/pane-axis.coffee index e1155b811..66c13b555 100644 --- a/src/pane-axis.coffee +++ b/src/pane-axis.coffee @@ -70,7 +70,7 @@ class PaneAxis extends View child.detach() getContainer: -> - @closest('#panes').view() + @closest('.panes').view() getActivePaneItem: -> @getActivePane()?.activeItem diff --git a/src/pane-container.coffee b/src/pane-container.coffee index 90d24f6f8..f6894b541 100644 --- a/src/pane-container.coffee +++ b/src/pane-container.coffee @@ -16,7 +16,7 @@ class PaneContainer extends View container @content: -> - @div id: 'panes' + @div class: 'panes' initialize: (state) -> @destroyedItemStates = [] diff --git a/src/pane.coffee b/src/pane.coffee index 396bc75e2..57827b803 100644 --- a/src/pane.coffee +++ b/src/pane.coffee @@ -412,7 +412,7 @@ class Pane extends View # Private: getContainer: -> - @closest('#panes').view() + @closest('.panes').view() # Private: copyActiveItem: -> diff --git a/src/project.coffee b/src/project.coffee index 96c630ded..a1026ebf5 100644 --- a/src/project.coffee +++ b/src/project.coffee @@ -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) -> diff --git a/src/select-list.coffee b/src/select-list.coffee index aba3f139f..21cb270de 100644 --- a/src/select-list.coffee +++ b/src/select-list.coffee @@ -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 diff --git a/src/text-buffer.coffee b/src/text-buffer.coffee index d669b5075..d3f9eac9f 100644 --- a/src/text-buffer.coffee +++ b/src/text-buffer.coffee @@ -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') diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 599b660ab..0b6ba31dd 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -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') diff --git a/src/window-bootstrap.coffee b/src/window-bootstrap.coffee index c7cd6b190..df17cb3d0 100644 --- a/src/window-bootstrap.coffee +++ b/src/window-bootstrap.coffee @@ -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' diff --git a/src/workspace-view.coffee b/src/workspace-view.coffee index 0a0ce793b..22f260b22 100644 --- a/src/workspace-view.coffee +++ b/src/workspace-view.coffee @@ -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) -> diff --git a/static/workspace-view.less b/static/workspace-view.less index bb8c037d9..26e6b37cc 100644 --- a/static/workspace-view.less +++ b/static/workspace-view.less @@ -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; diff --git a/tasks/update-atom-shell-task.coffee b/tasks/update-atom-shell-task.coffee deleted file mode 100644 index 18bc2bd05..000000000 --- a/tasks/update-atom-shell-task.coffee +++ /dev/null @@ -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) diff --git a/vendor/apm b/vendor/apm index 809d8d42f..49b1e740f 160000 --- a/vendor/apm +++ b/vendor/apm @@ -1 +1 @@ -Subproject commit 809d8d42f7e8935ba02de7b3b6053862ff4294c6 +Subproject commit 49b1e740f6ea02c11bf726346e0adbaadee7eb4d