diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 837961e6a..c8a79b4e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -285,8 +285,8 @@ If you want to read about using Atom or developing packages in Atom, the [Atom F All JavaScript must adhere to [JavaScript Standard Style](http://standardjs.com/). -* Prefer `Object.assign()` to the object spread operator (`{...anotherObj}`) -* Inline `export`s with expressions +* Prefer the object spread operator (`{...anotherObj}`) to `Object.assign()` +* Inline `export`s with expressions whenever possible ```js // Use this: export default class ClassName { diff --git a/build/tasks/compile-packages-slug-task.coffee b/build/tasks/compile-packages-slug-task.coffee index f6f297bec..a4f9ff072 100644 --- a/build/tasks/compile-packages-slug-task.coffee +++ b/build/tasks/compile-packages-slug-task.coffee @@ -8,13 +8,12 @@ semver = require 'semver' OtherPlatforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32'].filter (platform) -> platform isnt process.platform module.exports = (grunt) -> - {spawn, rm} = require('./task-helpers')(grunt) + {spawn} = require('./task-helpers')(grunt) getMenu = (appDir) -> menusPath = path.join(appDir, 'menus') menuPath = path.join(menusPath, "#{process.platform}.json") menu = CSON.readFileSync(menuPath) if fs.isFileSync(menuPath) - rm menusPath menu getKeymaps = (appDir) -> @@ -26,7 +25,6 @@ module.exports = (grunt) -> keymap = CSON.readFileSync(keymapPath) keymaps[path.basename(keymapPath)] = keymap - rm keymapsPath keymaps grunt.registerTask 'compile-packages-slug', 'Add bundled package metadata information to the main package.json file', -> @@ -54,7 +52,6 @@ module.exports = (grunt) -> moduleCache = metadata._atomModuleCache ? {} - rm metadataPath _.remove(moduleCache.extensions?['.json'] ? [], 'package.json') for property in ['_from', '_id', 'dist', 'readme', 'readmeFilename'] @@ -70,15 +67,11 @@ module.exports = (grunt) -> for keymapPath in fs.listSync(keymapsPath, ['.cson', '.json']) relativePath = path.relative(appDir, keymapPath) pack.keymaps[relativePath] = CSON.readFileSync(keymapPath) - rm keymapPath - rm keymapsPath if fs.listSync(keymapsPath).length is 0 menusPath = path.join(moduleDirectory, 'menus') for menuPath in fs.listSync(menusPath, ['.cson', '.json']) relativePath = path.relative(appDir, menuPath) pack.menus[relativePath] = CSON.readFileSync(menuPath) - rm menuPath - rm menusPath if fs.listSync(menusPath).length is 0 packages[metadata.name] = pack diff --git a/exports/atom.coffee b/exports/atom.coffee deleted file mode 100644 index bd8a1b62c..000000000 --- a/exports/atom.coffee +++ /dev/null @@ -1,44 +0,0 @@ -TextBuffer = require 'text-buffer' -{Point, Range} = TextBuffer -{File, Directory} = require 'pathwatcher' -{Emitter, Disposable, CompositeDisposable} = require 'event-kit' -Grim = require 'grim' - -module.exports = - BufferedNodeProcess: require '../src/buffered-node-process' - BufferedProcess: require '../src/buffered-process' - GitRepository: require '../src/git-repository' - Notification: require '../src/notification' - TextBuffer: TextBuffer - Point: Point - Range: Range - File: File - Directory: Directory - Emitter: Emitter - Disposable: Disposable - CompositeDisposable: CompositeDisposable - -# Shell integration is required by both Squirrel and Settings-View -if process.platform is 'win32' - module.exports.WinShell = require '../src/main-process/win-shell' - -# The following classes can't be used from a Task handler and should therefore -# only be exported when not running as a child node process -unless process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE - module.exports.Task = require '../src/task' - - TextEditor = (params) -> - atom.workspace.buildTextEditor(params) - - TextEditor.prototype = require('../src/text-editor').prototype - - Object.defineProperty module.exports, 'TextEditor', - enumerable: true - get: -> - Grim.deprecate """ - The `TextEditor` constructor is no longer public. - - To construct a text editor, use `atom.workspace.buildTextEditor()`. - To check if an object is a text editor, use `atom.workspace.isTextEditor(object)`. - """ - TextEditor diff --git a/exports/atom.js b/exports/atom.js new file mode 100644 index 000000000..50c8c687f --- /dev/null +++ b/exports/atom.js @@ -0,0 +1,58 @@ +/** @babel */ + +import TextBuffer, {Point, Range} from 'text-buffer' +import {File, Directory} from 'pathwatcher' +import {Emitter, Disposable, CompositeDisposable} from 'event-kit' +import Grim from 'grim' +import dedent from 'dedent' +import BufferedNodeProcess from '../src/buffered-node-process' +import BufferedProcess from '../src/buffered-process' +import GitRepository from '../src/git-repository' +import Notification from '../src/notification' + +const atomExport = { + BufferedNodeProcess, + BufferedProcess, + GitRepository, + Notification, + TextBuffer, + Point, + Range, + File, + Directory, + Emitter, + Disposable, + CompositeDisposable +} + +// Shell integration is required by both Squirrel and Settings-View +if (process.platform === 'win32') { + atomExport.WinShell = require('../src/main-process/win-shell') +} + +// The following classes can't be used from a Task handler and should therefore +// only be exported when not running as a child node process +if (!process.env.ATOM_SHELL_INTERNAL_RUN_AS_NODE) { + atomExport.Task = require('../src/task') + + const TextEditor = (params) => { + return atom.workspace.buildTextEditor(params) + } + + TextEditor.prototype = require('../src/text-editor').prototype + + Object.defineProperty(atomExport, 'TextEditor', { + enumerable: true, + get () { + Grim.deprecate(dedent` + The \`TextEditor\` constructor is no longer public. + + To construct a text editor, use \`atom.workspace.buildTextEditor()\`. + To check if an object is a text editor, use \`atom.workspace.isTextEditor(object)\`. + `) + return TextEditor + } + }) +} + +export default atomExport diff --git a/package.json b/package.json index bbac58d5e..cac285ee0 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "deprecation-cop": "0.54.1", "dev-live-reload": "0.47.0", "encoding-selector": "0.22.0", - "exception-reporting": "0.38.2", + "exception-reporting": "0.39.0", "find-and-replace": "0.201.0", "fuzzy-finder": "1.3.0", "git-diff": "1.1.0", @@ -112,7 +112,7 @@ "settings-view": "0.241.1", "snippets": "1.0.2", "spell-check": "0.67.1", - "status-bar": "1.4.0", + "status-bar": "1.4.1", "styleguide": "0.47.0", "symbols-view": "0.113.1", "tabs": "0.100.0", diff --git a/resources/linux/atom.desktop.in b/resources/linux/atom.desktop.in index 290d368d2..6fa5d79c8 100644 --- a/resources/linux/atom.desktop.in +++ b/resources/linux/atom.desktop.in @@ -2,7 +2,7 @@ Name=<%= appName %> Comment=<%= description %> GenericName=Text Editor -Exec=<%= installDir %>/share/<%= appFileName %>/atom %U +Exec=<%= installDir %>/share/<%= appFileName %>/atom %F Icon=<%= iconPath %> Type=Application StartupNotify=true diff --git a/spec/git-spec.coffee b/spec/git-repository-spec.coffee similarity index 94% rename from spec/git-spec.coffee rename to spec/git-repository-spec.coffee index ef87d83ee..d427fc3b9 100644 --- a/spec/git-spec.coffee +++ b/spec/git-repository-spec.coffee @@ -199,7 +199,7 @@ describe "GitRepository", -> beforeEach -> workingDirectory = copyRepository() - repo = new GitRepository(workingDirectory) + repo = new GitRepository(workingDirectory, {project: atom.project, config: atom.config}) modifiedPath = path.join(workingDirectory, 'file.txt') newPath = path.join(workingDirectory, 'untracked.txt') cleanPath = path.join(workingDirectory, 'other.txt') @@ -249,6 +249,22 @@ describe "GitRepository", -> expect(repo.isStatusModified(status)).toBe false expect(repo.isStatusNew(status)).toBe false + it "works correctly when the project has multiple folders (regression)", -> + atom.project.addPath(workingDirectory) + atom.project.addPath(path.join(__dirname, 'fixtures', 'dir')) + statusHandler = jasmine.createSpy('statusHandler') + repo.onDidChangeStatuses statusHandler + + repo.refreshStatus() + + waitsFor -> + statusHandler.callCount > 0 + + runs -> + expect(repo.getCachedPathStatus(cleanPath)).toBeUndefined() + expect(repo.isStatusNew(repo.getCachedPathStatus(newPath))).toBeTruthy() + expect(repo.isStatusModified(repo.getCachedPathStatus(modifiedPath))).toBeTruthy() + it 'caches statuses that were looked up synchronously', -> originalContent = 'undefined' fs.writeFileSync(modifiedPath, 'making this path modified') diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index 4ef292b51..e3b4f7c42 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -2252,6 +2252,17 @@ describe('TextEditorComponent', function () { expect(overlay.style.left).toBe(windowWidth - itemWidth + 'px') expect(overlay.style.top).toBe(position.top + editor.getLineHeightInPixels() + 'px') + + // window size change + + windowWidth = Math.round(gutterWidth + 29 * editor.getDefaultCharWidth()) + await atom.setWindowDimensions({ + width: windowWidth, + height: windowHeight, + }) + atom.views.performDocumentPoll() + expect(overlay.style.left).toBe(windowWidth - itemWidth + 'px') + expect(overlay.style.top).toBe(position.top + editor.getLineHeightInPixels() + 'px') }) }) }) diff --git a/src/application-delegate.coffee b/src/application-delegate.coffee index 74c498e78..3372962be 100644 --- a/src/application-delegate.coffee +++ b/src/application-delegate.coffee @@ -1,5 +1,5 @@ _ = require 'underscore-plus' -{screen, ipcRenderer, remote, shell, webFrame} = require 'electron' +{screen, ipcRenderer, remote, shell, systemPreferences, webFrame} = require 'electron' ipcHelpers = require './ipc-helpers' {Disposable} = require 'event-kit' {getWindowLoadSettings, setWindowLoadSettings} = require './window-load-settings-helpers' @@ -57,12 +57,18 @@ class ApplicationDelegate reloadWindow: -> ipcRenderer.send("call-window-method", "reload") + minimizeWindow: -> + ipcRenderer.send("call-window-method", "minimize") + isWindowMaximized: -> remote.getCurrentWindow().isMaximized() maximizeWindow: -> ipcRenderer.send("call-window-method", "maximize") + unmaximizeWindow: -> + ipcRenderer.send("call-window-method", "unmaximize") + isWindowFullScreen: -> remote.getCurrentWindow().isFullScreen() @@ -130,6 +136,9 @@ class ApplicationDelegate getPrimaryDisplayWorkAreaSize: -> remote.screen.getPrimaryDisplay().workAreaSize + getUserDefault: (key, type) -> + remote.systemPreferences.getUserDefault(key, type) + confirm: ({message, detailedMessage, buttons}) -> buttons ?= {} if _.isArray(buttons) diff --git a/src/config-schema.coffee b/src/config-schema.coffee index 67f3a430f..173056ee0 100644 --- a/src/config-schema.coffee +++ b/src/config-schema.coffee @@ -266,4 +266,4 @@ if process.platform is 'darwin' module.exports.core.properties.useCustomTitleBar = type: 'boolean' default: false - description: 'Use custom, theme-aware title-bar.
Note: Note: This currently does not include a proxy icon.
This setting will require a relaunch of Atom to take effect.' + description: 'Use custom, theme-aware title bar.
Note: This currently does not include a proxy icon.
This setting will require a relaunch of Atom to take effect.' diff --git a/src/git-repository.coffee b/src/git-repository.coffee index 85600bba7..e0d7dfb25 100644 --- a/src/git-repository.coffee +++ b/src/git-repository.coffee @@ -3,6 +3,7 @@ _ = require 'underscore-plus' {Emitter, Disposable, CompositeDisposable} = require 'event-kit' fs = require 'fs-plus' +path = require 'path' GitUtils = require 'git-utils' Task = require './task' @@ -309,8 +310,8 @@ class GitRepository getDirectoryStatus: (directoryPath) -> directoryPath = "#{@relativize(directoryPath)}/" directoryStatus = 0 - for path, status of @statuses - directoryStatus |= status if path.indexOf(directoryPath) is 0 + for statusPath, status of @statuses + directoryStatus |= status if statusPath.indexOf(directoryPath) is 0 directoryStatus # Public: Get the status of a single path in the repository. @@ -432,8 +433,8 @@ class GitRepository # Subscribes to buffer events. subscribeToBuffer: (buffer) -> getBufferPathStatus = => - if path = buffer.getPath() - @getPathStatus(path) + if bufferPath = buffer.getPath() + @getPathStatus(bufferPath) bufferSubscriptions = new CompositeDisposable bufferSubscriptions.add buffer.onDidSave(getBufferPathStatus) @@ -468,8 +469,8 @@ class GitRepository @handlerPath ?= require.resolve('./repository-status-handler') relativeProjectPaths = @project?.getPaths() - .map (path) => @relativize(path) - .filter (path) -> path.length > 0 + .map (projectPath) => @relativize(projectPath) + .filter (projectPath) -> projectPath.length > 0 and not path.isAbsolute(projectPath) @statusTask?.terminate() new Promise (resolve) => diff --git a/src/module-cache.coffee b/src/module-cache.coffee index 39bdfa244..8c6a7c312 100644 --- a/src/module-cache.coffee +++ b/src/module-cache.coffee @@ -196,8 +196,8 @@ resolveModulePath = (relativePath, parentModule) -> registerBuiltins = (devMode) -> if devMode or not cache.resourcePath.startsWith("#{process.resourcesPath}#{path.sep}") fs = require 'fs-plus' - atomCoffeePath = path.join(cache.resourcePath, 'exports', 'atom.coffee') - cache.builtins.atom = atomCoffeePath if fs.isFileSync(atomCoffeePath) + atomJsPath = path.join(cache.resourcePath, 'exports', 'atom.js') + cache.builtins.atom = atomJsPath if fs.isFileSync(atomJsPath) cache.builtins.atom ?= path.join(cache.resourcePath, 'exports', 'atom.js') electronAsarRoot = path.join(process.resourcesPath, 'electron.asar') diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index a8ed9b6c1..744f82770 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -727,6 +727,7 @@ class TextEditorComponent pollDOM: => unless @checkForVisibilityChange() @sampleBackgroundColors() + @measureWindowSize() @measureDimensions() @sampleFontStyling() @overlayManager?.measureOverlays() diff --git a/src/title-bar.coffee b/src/title-bar.coffee index e2da3ed62..b81b08060 100644 --- a/src/title-bar.coffee +++ b/src/title-bar.coffee @@ -8,12 +8,25 @@ class TitleBar @titleElement.classList.add('title') @element.appendChild(@titleElement) + @element.addEventListener 'dblclick', @dblclickHandler + @workspace.onDidChangeActivePaneItem => @updateTitle() @themes.onDidChangeActiveThemes => @updateWindowSheetOffset() @updateTitle() @updateWindowSheetOffset() + dblclickHandler: => + # User preference deciding which action to take on a title bar double-click + switch @applicationDelegate.getUserDefault('AppleActionOnDoubleClick', 'string') + when 'Minimize' + @applicationDelegate.minimizeWindow() + when 'Maximize' + if @applicationDelegate.isWindowMaximized() + @applicationDelegate.unmaximizeWindow() + else + @applicationDelegate.maximizeWindow() + updateTitle: -> @titleElement.textContent = document.title diff --git a/src/tokenized-buffer.coffee b/src/tokenized-buffer.coffee index 7bb568474..d68069170 100644 --- a/src/tokenized-buffer.coffee +++ b/src/tokenized-buffer.coffee @@ -195,6 +195,17 @@ class TokenizedBuffer extends Model row + delta handleBufferChange: (e) -> + if @lastBufferChangeEventId? + @assert( + @lastBufferChangeEventId is e.eventId - 1, + 'Buffer Change Event Ids are not sequential', + (error) => + error.metadata = { + tokenizedBufferEventId: @lastBufferChangeEventId, + nextTokenizedBufferEventId: e.eventId, + } + ) + @lastBufferChangeEventId = e.eventId @changeCount = @buffer.changeCount {oldRange, newRange} = e