mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
Merge pull request #14435 from atom/mb-use-native-text-buffer
Use new native text-buffer implementation
This commit is contained in:
@@ -232,19 +232,14 @@ class ApplicationDelegate
|
||||
new Disposable ->
|
||||
ipcRenderer.removeListener('context-command', outerCallback)
|
||||
|
||||
onSaveWindowStateRequest: (callback) ->
|
||||
onDidRequestUnload: (callback) ->
|
||||
outerCallback = (event, message) ->
|
||||
callback(event)
|
||||
callback(event).then (shouldUnload) ->
|
||||
ipcRenderer.send('did-prepare-to-unload', shouldUnload)
|
||||
|
||||
ipcRenderer.on('save-window-state', outerCallback)
|
||||
ipcRenderer.on('prepare-to-unload', outerCallback)
|
||||
new Disposable ->
|
||||
ipcRenderer.removeListener('save-window-state', outerCallback)
|
||||
|
||||
didSaveWindowState: ->
|
||||
ipcRenderer.send('did-save-window-state')
|
||||
|
||||
didCancelWindowUnload: ->
|
||||
ipcRenderer.send('did-cancel-window-unload')
|
||||
ipcRenderer.removeListener('prepare-to-unload', outerCallback)
|
||||
|
||||
onDidChangeHistoryManager: (callback) ->
|
||||
outerCallback = (event, message) ->
|
||||
|
||||
@@ -694,9 +694,14 @@ class AtomEnvironment extends Model
|
||||
@disposables.add(@applicationDelegate.onDidOpenLocations(@openLocations.bind(this)))
|
||||
@disposables.add(@applicationDelegate.onApplicationMenuCommand(@dispatchApplicationMenuCommand.bind(this)))
|
||||
@disposables.add(@applicationDelegate.onContextMenuCommand(@dispatchContextMenuCommand.bind(this)))
|
||||
@disposables.add @applicationDelegate.onSaveWindowStateRequest =>
|
||||
callback = => @applicationDelegate.didSaveWindowState()
|
||||
@saveState({isUnloading: true}).catch(callback).then(callback)
|
||||
@disposables.add @applicationDelegate.onDidRequestUnload =>
|
||||
@saveState({isUnloading: true})
|
||||
.catch(console.error)
|
||||
.then =>
|
||||
@workspace?.confirmClose({
|
||||
windowCloseRequested: true,
|
||||
projectHasPaths: @project.getPaths().length > 0
|
||||
})
|
||||
|
||||
@listenForUpdates()
|
||||
|
||||
@@ -705,30 +710,30 @@ class AtomEnvironment extends Model
|
||||
@packages.loadPackages()
|
||||
|
||||
startTime = Date.now()
|
||||
@deserialize(state) if state?
|
||||
@deserializeTimings.atom = Date.now() - startTime
|
||||
@deserialize(state).then =>
|
||||
@deserializeTimings.atom = Date.now() - startTime
|
||||
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'custom'
|
||||
@workspace.addHeaderPanel({item: new TitleBar({@workspace, @themes, @applicationDelegate})})
|
||||
@document.body.classList.add('custom-title-bar')
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'custom-inset'
|
||||
@workspace.addHeaderPanel({item: new TitleBar({@workspace, @themes, @applicationDelegate})})
|
||||
@document.body.classList.add('custom-inset-title-bar')
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'hidden'
|
||||
@document.body.classList.add('hidden-title-bar')
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'custom'
|
||||
@workspace.addHeaderPanel({item: new TitleBar({@workspace, @themes, @applicationDelegate})})
|
||||
@document.body.classList.add('custom-title-bar')
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'custom-inset'
|
||||
@workspace.addHeaderPanel({item: new TitleBar({@workspace, @themes, @applicationDelegate})})
|
||||
@document.body.classList.add('custom-inset-title-bar')
|
||||
if process.platform is 'darwin' and @config.get('core.titleBar') is 'hidden'
|
||||
@document.body.classList.add('hidden-title-bar')
|
||||
|
||||
@document.body.appendChild(@workspace.getElement())
|
||||
@backgroundStylesheet?.remove()
|
||||
@document.body.appendChild(@workspace.getElement())
|
||||
@backgroundStylesheet?.remove()
|
||||
|
||||
@watchProjectPaths()
|
||||
@watchProjectPaths()
|
||||
|
||||
@packages.activate()
|
||||
@keymaps.loadUserKeymap()
|
||||
@requireUserInitScript() unless @getLoadSettings().safeMode
|
||||
@packages.activate()
|
||||
@keymaps.loadUserKeymap()
|
||||
@requireUserInitScript() unless @getLoadSettings().safeMode
|
||||
|
||||
@menu.update()
|
||||
@menu.update()
|
||||
|
||||
@openInitialEmptyEditorIfNecessary()
|
||||
@openInitialEmptyEditorIfNecessary()
|
||||
|
||||
loadHistoryPromise = @history.loadState().then =>
|
||||
@reopenProjectMenuManager = new ReopenProjectMenuManager({
|
||||
@@ -986,6 +991,8 @@ class AtomEnvironment extends Model
|
||||
Promise.resolve(null)
|
||||
|
||||
deserialize: (state) ->
|
||||
return Promise.resolve() unless state?
|
||||
|
||||
if grammarOverridesByPath = state.grammars?.grammarOverridesByPath
|
||||
@grammars.grammarOverridesByPath = grammarOverridesByPath
|
||||
|
||||
@@ -994,14 +1001,19 @@ class AtomEnvironment extends Model
|
||||
@packages.packageStates = state.packageStates ? {}
|
||||
|
||||
startTime = Date.now()
|
||||
@project.deserialize(state.project, @deserializers) if state.project?
|
||||
@deserializeTimings.project = Date.now() - startTime
|
||||
if state.project?
|
||||
projectPromise = @project.deserialize(state.project, @deserializers)
|
||||
else
|
||||
projectPromise = Promise.resolve()
|
||||
|
||||
@textEditors.deserialize(state.textEditors) if state.textEditors
|
||||
projectPromise.then =>
|
||||
@deserializeTimings.project = Date.now() - startTime
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace.deserialize(state.workspace, @deserializers) if state.workspace?
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
@textEditors.deserialize(state.textEditors) if state.textEditors
|
||||
|
||||
startTime = Date.now()
|
||||
@workspace.deserialize(state.workspace, @deserializers) if state.workspace?
|
||||
@deserializeTimings.workspace = Date.now() - startTime
|
||||
|
||||
getStateKey: (paths) ->
|
||||
if paths?.length > 0
|
||||
|
||||
@@ -437,6 +437,7 @@ class GitRepository
|
||||
if bufferPath = buffer.getPath()
|
||||
@getPathStatus(bufferPath)
|
||||
|
||||
getBufferPathStatus()
|
||||
bufferSubscriptions = new CompositeDisposable
|
||||
bufferSubscriptions.add buffer.onDidSave(getBufferPathStatus)
|
||||
bufferSubscriptions.add buffer.onDidReload(getBufferPathStatus)
|
||||
@@ -449,9 +450,10 @@ class GitRepository
|
||||
|
||||
# Subscribes to editor view event.
|
||||
checkoutHeadForEditor: (editor) ->
|
||||
if filePath = editor.getPath()
|
||||
editor.buffer.reload() if editor.buffer.isModified()
|
||||
buffer = editor.getBuffer()
|
||||
if filePath = buffer.getPath()
|
||||
@checkoutHead(filePath)
|
||||
buffer.reload()
|
||||
|
||||
# Returns the corresponding {Repository}
|
||||
getRepo: (path) ->
|
||||
|
||||
@@ -270,7 +270,7 @@ class AtomApplication
|
||||
unless @quitting
|
||||
event.preventDefault()
|
||||
@quitting = true
|
||||
Promise.all(@windows.map((window) -> window.saveState())).then(-> app.quit())
|
||||
Promise.all(@windows.map((window) -> window.prepareToUnload())).then(-> app.quit())
|
||||
|
||||
@disposable.add ipcHelpers.on app, 'will-quit', =>
|
||||
@killAllProcesses()
|
||||
@@ -373,11 +373,6 @@ class AtomApplication
|
||||
@disposable.add ipcHelpers.respondTo 'set-temporary-window-state', (win, state) ->
|
||||
win.temporaryState = state
|
||||
|
||||
@disposable.add ipcHelpers.on ipcMain, 'did-cancel-window-unload', =>
|
||||
@quitting = false
|
||||
for window in @windows
|
||||
window.didCancelWindowUnload()
|
||||
|
||||
clipboard = require '../safe-clipboard'
|
||||
@disposable.add ipcHelpers.on ipcMain, 'write-text-to-selection-clipboard', (event, selectedText) ->
|
||||
clipboard.writeText(selectedText, 'selection')
|
||||
|
||||
@@ -147,7 +147,8 @@ class AtomWindow
|
||||
event.preventDefault()
|
||||
@unloading = true
|
||||
@atomApplication.saveState(false)
|
||||
@saveState().then(=> @close())
|
||||
@prepareToUnload().then (result) =>
|
||||
@close() if result
|
||||
|
||||
@browserWindow.on 'closed', =>
|
||||
@fileRecoveryService.didCloseWindow(this)
|
||||
@@ -191,21 +192,19 @@ class AtomWindow
|
||||
@browserWindow.on 'blur', =>
|
||||
@browserWindow.focusOnWebView()
|
||||
|
||||
didCancelWindowUnload: ->
|
||||
@unloading = false
|
||||
|
||||
saveState: ->
|
||||
prepareToUnload: ->
|
||||
if @isSpecWindow()
|
||||
return Promise.resolve()
|
||||
|
||||
@lastSaveStatePromise = new Promise (resolve) =>
|
||||
callback = (event) =>
|
||||
return Promise.resolve(true)
|
||||
@lastPrepareToUnloadPromise = new Promise (resolve) =>
|
||||
callback = (event, result) =>
|
||||
if BrowserWindow.fromWebContents(event.sender) is @browserWindow
|
||||
ipcMain.removeListener('did-save-window-state', callback)
|
||||
resolve()
|
||||
ipcMain.on('did-save-window-state', callback)
|
||||
@browserWindow.webContents.send('save-window-state')
|
||||
@lastSaveStatePromise
|
||||
ipcMain.removeListener('did-prepare-to-unload', callback)
|
||||
unless result
|
||||
@unloading = false
|
||||
@atomApplication.quitting = false
|
||||
resolve(result)
|
||||
ipcMain.on('did-prepare-to-unload', callback)
|
||||
@browserWindow.webContents.send('prepare-to-unload')
|
||||
|
||||
openPath: (pathToOpen, initialLine, initialColumn) ->
|
||||
@openLocations([{pathToOpen, initialLine, initialColumn}])
|
||||
@@ -287,7 +286,8 @@ class AtomWindow
|
||||
|
||||
reload: ->
|
||||
@loadedPromise = new Promise((@resolveLoadedPromise) =>)
|
||||
@saveState().then => @browserWindow.reload()
|
||||
@prepareToUnload().then (result) =>
|
||||
@browserWindow.reload() if result
|
||||
@loadedPromise
|
||||
|
||||
showSaveDialog: (params) ->
|
||||
|
||||
@@ -172,18 +172,13 @@ class PaneContainer {
|
||||
}
|
||||
|
||||
confirmClose (options) {
|
||||
let allSaved = true
|
||||
|
||||
for (let pane of this.getPanes()) {
|
||||
for (let item of pane.getItems()) {
|
||||
if (!pane.promptToSaveItem(item, options)) {
|
||||
allSaved = false
|
||||
break
|
||||
}
|
||||
const promises = []
|
||||
for (const pane of this.getPanes()) {
|
||||
for (const item of pane.getItems()) {
|
||||
promises.push(pane.promptToSaveItem(item, options))
|
||||
}
|
||||
}
|
||||
|
||||
return allSaved
|
||||
return Promise.all(promises).then((results) => !results.includes(false))
|
||||
}
|
||||
|
||||
activateNextPane () {
|
||||
|
||||
104
src/pane.coffee
104
src/pane.coffee
@@ -7,6 +7,9 @@ PaneElement = require './pane-element'
|
||||
|
||||
nextInstanceId = 1
|
||||
|
||||
class SaveCancelledError extends Error
|
||||
constructor: -> super
|
||||
|
||||
# Extended: A container for presenting content in the center of the workspace.
|
||||
# Panes can contain multiple items, one of which is *active* at a given time.
|
||||
# The view corresponding to the active item is displayed in the interface. In
|
||||
@@ -410,7 +413,6 @@ class Pane
|
||||
@addItemToStack(@activeItem)
|
||||
@emitter.emit 'done-choosing-mru-item'
|
||||
|
||||
|
||||
# Public: Makes the next item active.
|
||||
activateNextItem: ->
|
||||
index = @getActiveItemIndex()
|
||||
@@ -614,39 +616,47 @@ class Pane
|
||||
# * `force` (optional) {Boolean} Destroy the item without prompting to save
|
||||
# it, even if the item's `isPermanentDockItem` method returns true.
|
||||
#
|
||||
# Returns a {Boolean} indicating whether or not the item was destroyed.
|
||||
# Returns a {Promise} that resolves with a {Boolean} indicating whether or not
|
||||
# the item was destroyed.
|
||||
destroyItem: (item, force) ->
|
||||
index = @items.indexOf(item)
|
||||
if index isnt -1
|
||||
return false if not force and @getContainer()?.getLocation() isnt 'center' and item.isPermanentDockItem?()
|
||||
@emitter.emit 'will-destroy-item', {item, index}
|
||||
@container?.willDestroyPaneItem({item, index, pane: this})
|
||||
if force or @promptToSaveItem(item)
|
||||
if force or not item?.shouldPromptToSave?()
|
||||
@removeItem(item, false)
|
||||
item.destroy?()
|
||||
true
|
||||
else
|
||||
false
|
||||
@promptToSaveItem(item).then (result) =>
|
||||
if result
|
||||
@removeItem(item, false)
|
||||
item.destroy?()
|
||||
result
|
||||
|
||||
# Public: Destroy all items.
|
||||
destroyItems: ->
|
||||
@destroyItem(item) for item in @getItems()
|
||||
return
|
||||
Promise.all(
|
||||
@getItems().map(@destroyItem.bind(this))
|
||||
)
|
||||
|
||||
# Public: Destroy all items except for the active item.
|
||||
destroyInactiveItems: ->
|
||||
@destroyItem(item) for item in @getItems() when item isnt @activeItem
|
||||
return
|
||||
Promise.all(
|
||||
@getItems()
|
||||
.filter((item) => item isnt @activeItem)
|
||||
.map(@destroyItem.bind(this))
|
||||
)
|
||||
|
||||
promptToSaveItem: (item, options={}) ->
|
||||
return true unless item.shouldPromptToSave?(options)
|
||||
return Promise.resolve(true) unless item.shouldPromptToSave?(options)
|
||||
|
||||
if typeof item.getURI is 'function'
|
||||
uri = item.getURI()
|
||||
else if typeof item.getUri is 'function'
|
||||
uri = item.getUri()
|
||||
else
|
||||
return true
|
||||
return Promise.resolve(true)
|
||||
|
||||
saveDialog = (saveButtonText, saveFn, message) =>
|
||||
chosen = @applicationDelegate.confirm
|
||||
@@ -654,15 +664,23 @@ class Pane
|
||||
detailedMessage: "Your changes will be lost if you close this item without saving."
|
||||
buttons: [saveButtonText, "Cancel", "Don't Save"]
|
||||
switch chosen
|
||||
when 0 then saveFn(item, saveError)
|
||||
when 1 then false
|
||||
when 2 then true
|
||||
when 0
|
||||
new Promise (resolve) ->
|
||||
saveFn item, (error) ->
|
||||
if error instanceof SaveCancelledError
|
||||
resolve(false)
|
||||
else
|
||||
saveError(error).then(resolve)
|
||||
when 1
|
||||
Promise.resolve(false)
|
||||
when 2
|
||||
Promise.resolve(true)
|
||||
|
||||
saveError = (error) =>
|
||||
if error
|
||||
saveDialog("Save as", @saveItemAs, "'#{item.getTitle?() ? uri}' could not be saved.\nError: #{@getMessageForErrorCode(error.code)}")
|
||||
else
|
||||
true
|
||||
Promise.resolve(true)
|
||||
|
||||
saveDialog("Save", @saveItem, "'#{item.getTitle?() ? uri}' has changes, do you want to save them?")
|
||||
|
||||
@@ -675,6 +693,8 @@ class Pane
|
||||
#
|
||||
# * `nextAction` (optional) {Function} which will be called after the item is
|
||||
# successfully saved.
|
||||
#
|
||||
# Returns a {Promise} that resolves when the save is complete
|
||||
saveActiveItemAs: (nextAction) ->
|
||||
@saveItemAs(@getActiveItem(), nextAction)
|
||||
|
||||
@@ -685,6 +705,8 @@ class Pane
|
||||
# after the item is successfully saved, or with the error if it failed.
|
||||
# The return value will be that of `nextAction` or `undefined` if it was not
|
||||
# provided
|
||||
#
|
||||
# Returns a {Promise} that resolves when the save is complete
|
||||
saveItem: (item, nextAction) =>
|
||||
if typeof item?.getURI is 'function'
|
||||
itemURI = item.getURI()
|
||||
@@ -692,14 +714,16 @@ class Pane
|
||||
itemURI = item.getUri()
|
||||
|
||||
if itemURI?
|
||||
try
|
||||
item.save?()
|
||||
if item.save?
|
||||
promisify -> item.save()
|
||||
.then -> nextAction?()
|
||||
.catch (error) =>
|
||||
if nextAction
|
||||
nextAction(error)
|
||||
else
|
||||
@handleSaveError(error, item)
|
||||
else
|
||||
nextAction?()
|
||||
catch error
|
||||
if nextAction
|
||||
nextAction(error)
|
||||
else
|
||||
@handleSaveError(error, item)
|
||||
else
|
||||
@saveItemAs(item, nextAction)
|
||||
|
||||
@@ -718,14 +742,15 @@ class Pane
|
||||
saveOptions.defaultPath ?= item.getPath()
|
||||
newItemPath = @applicationDelegate.showSaveDialog(saveOptions)
|
||||
if newItemPath
|
||||
try
|
||||
item.saveAs(newItemPath)
|
||||
nextAction?()
|
||||
catch error
|
||||
if nextAction
|
||||
nextAction(error)
|
||||
else
|
||||
@handleSaveError(error, item)
|
||||
promisify -> item.saveAs(newItemPath)
|
||||
.then -> nextAction?()
|
||||
.catch (error) =>
|
||||
if nextAction?
|
||||
nextAction(error)
|
||||
else
|
||||
@handleSaveError(error, item)
|
||||
else if nextAction?
|
||||
nextAction(new SaveCancelledError('Save Cancelled'))
|
||||
|
||||
# Public: Save all items.
|
||||
saveItems: ->
|
||||
@@ -794,7 +819,6 @@ class Pane
|
||||
item.destroy?() for item in @items.slice()
|
||||
@container?.didDestroyPane(pane: this)
|
||||
|
||||
|
||||
isAlive: -> @alive
|
||||
|
||||
# Public: Determine whether this pane has been destroyed.
|
||||
@@ -921,13 +945,13 @@ class Pane
|
||||
bottommostSibling = @findBottommostSibling()
|
||||
if bottommostSibling is this then @splitDown() else bottommostSibling
|
||||
|
||||
# Private: Close the pane unless the user cancels the action via a dialog.
|
||||
#
|
||||
# Returns a {Promise} that resolves once the pane is either closed, or the
|
||||
# closing has been cancelled.
|
||||
close: ->
|
||||
@destroy() if @confirmClose()
|
||||
|
||||
confirmClose: ->
|
||||
for item in @getItems()
|
||||
return false unless @promptToSaveItem(item)
|
||||
true
|
||||
Promise.all(@getItems().map(@promptToSaveItem.bind(this))).then (results) =>
|
||||
@destroy() unless results.includes(false)
|
||||
|
||||
handleSaveError: (error, item) ->
|
||||
itemPath = error.path ? item?.getPath?()
|
||||
@@ -960,3 +984,9 @@ class Pane
|
||||
when 'EROFS' then 'Read-only file system'
|
||||
when 'ESPIPE' then 'Invalid seek'
|
||||
when 'ETIMEDOUT' then 'Connection timed out'
|
||||
|
||||
promisify = (callback) ->
|
||||
try
|
||||
Promise.resolve(callback())
|
||||
catch error
|
||||
Promise.reject(error)
|
||||
@@ -27,6 +27,7 @@ class Project extends Model
|
||||
@defaultDirectoryProvider = new DefaultDirectoryProvider()
|
||||
@repositoryPromisesByPath = new Map()
|
||||
@repositoryProviders = [new GitRepositoryProvider(this, config)]
|
||||
@loadPromisesByPath = {}
|
||||
@consumeServices(packageManager)
|
||||
|
||||
destroyed: ->
|
||||
@@ -42,6 +43,7 @@ class Project extends Model
|
||||
buffer?.destroy() for buffer in @buffers
|
||||
@buffers = []
|
||||
@setPaths([])
|
||||
@loadPromisesByPath = {}
|
||||
@consumeServices(packageManager)
|
||||
|
||||
destroyUnretainedBuffers: ->
|
||||
@@ -53,35 +55,29 @@ class Project extends Model
|
||||
###
|
||||
|
||||
deserialize: (state) ->
|
||||
state.paths = [state.path] if state.path? # backward compatibility
|
||||
|
||||
@buffers = _.compact state.buffers.map (bufferState) ->
|
||||
# Check that buffer's file path is accessible
|
||||
return if fs.isDirectorySync(bufferState.filePath)
|
||||
bufferPromises = []
|
||||
for bufferState in state.buffers
|
||||
continue if fs.isDirectorySync(bufferState.filePath)
|
||||
if bufferState.filePath
|
||||
try
|
||||
fs.closeSync(fs.openSync(bufferState.filePath, 'r'))
|
||||
catch error
|
||||
return unless error.code is 'ENOENT'
|
||||
continue unless error.code is 'ENOENT'
|
||||
unless bufferState.shouldDestroyOnFileDelete?
|
||||
bufferState.shouldDestroyOnFileDelete =
|
||||
-> atom.config.get('core.closeDeletedFileTabs')
|
||||
TextBuffer.deserialize(bufferState)
|
||||
|
||||
@subscribeToBuffer(buffer) for buffer in @buffers
|
||||
@setPaths(state.paths)
|
||||
bufferState.shouldDestroyOnFileDelete = ->
|
||||
atom.config.get('core.closeDeletedFileTabs')
|
||||
bufferPromises.push(TextBuffer.deserialize(bufferState))
|
||||
Promise.all(bufferPromises).then (@buffers) =>
|
||||
@subscribeToBuffer(buffer) for buffer in @buffers
|
||||
@setPaths(state.paths)
|
||||
|
||||
serialize: (options={}) ->
|
||||
deserializer: 'Project'
|
||||
paths: @getPaths()
|
||||
buffers: _.compact(@buffers.map (buffer) ->
|
||||
if buffer.isRetained()
|
||||
state = buffer.serialize({markerLayers: options.isUnloading is true})
|
||||
# Skip saving large buffer text unless unloading to avoid blocking main thread
|
||||
if not options.isUnloading and state.text.length > 2 * 1024 * 1024
|
||||
delete state.text
|
||||
delete state.digestWhenLastPersisted
|
||||
state
|
||||
isUnloading = options.isUnloading is true
|
||||
buffer.serialize({markerLayers: isUnloading, history: isUnloading})
|
||||
)
|
||||
|
||||
###
|
||||
@@ -371,11 +367,12 @@ class Project extends Model
|
||||
|
||||
# Still needed when deserializing a tokenized buffer
|
||||
buildBufferSync: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({
|
||||
filePath: absoluteFilePath
|
||||
shouldDestroyOnFileDelete: @shouldDestroyBufferOnFileDelete})
|
||||
params = {shouldDestroyOnFileDelete: @shouldDestroyBufferOnFileDelete}
|
||||
if absoluteFilePath?
|
||||
buffer = TextBuffer.loadSync(absoluteFilePath, params)
|
||||
else
|
||||
buffer = new TextBuffer(params)
|
||||
@addBuffer(buffer)
|
||||
buffer.loadSync()
|
||||
buffer
|
||||
|
||||
# Given a file path, this sets its {TextBuffer}.
|
||||
@@ -385,13 +382,20 @@ class Project extends Model
|
||||
#
|
||||
# Returns a {Promise} that resolves to the {TextBuffer}.
|
||||
buildBuffer: (absoluteFilePath) ->
|
||||
buffer = new TextBuffer({
|
||||
filePath: absoluteFilePath
|
||||
shouldDestroyOnFileDelete: @shouldDestroyBufferOnFileDelete})
|
||||
@addBuffer(buffer)
|
||||
buffer.load()
|
||||
.then((buffer) -> buffer)
|
||||
.catch(=> @removeBuffer(buffer))
|
||||
params = {shouldDestroyOnFileDelete: @shouldDestroyBufferOnFileDelete}
|
||||
if absoluteFilePath?
|
||||
promise =
|
||||
@loadPromisesByPath[absoluteFilePath] ?=
|
||||
TextBuffer.load(absoluteFilePath, params).catch (error) =>
|
||||
delete @loadPromisesByPath[absoluteFilePath]
|
||||
throw error
|
||||
else
|
||||
promise = Promise.resolve(new TextBuffer(params))
|
||||
promise.then (buffer) =>
|
||||
delete @loadPromisesByPath[absoluteFilePath]
|
||||
@addBuffer(buffer)
|
||||
buffer
|
||||
|
||||
|
||||
addBuffer: (buffer, options={}) ->
|
||||
@addBufferAtIndex(buffer, @buffers.length, options)
|
||||
|
||||
@@ -185,8 +185,9 @@ class TextEditor extends Model
|
||||
@preferredLineLength ?= 80
|
||||
@showLineNumbers ?= true
|
||||
|
||||
@buffer ?= new TextBuffer({shouldDestroyOnFileDelete: ->
|
||||
atom.config.get('core.closeDeletedFileTabs')})
|
||||
@buffer ?= new TextBuffer({
|
||||
shouldDestroyOnFileDelete: -> atom.config.get('core.closeDeletedFileTabs')
|
||||
})
|
||||
@tokenizedBuffer ?= new TokenizedBuffer({
|
||||
grammar, tabLength, @buffer, @largeFileMode, @assert
|
||||
})
|
||||
@@ -447,8 +448,6 @@ class TextEditor extends Model
|
||||
@disposables.add @buffer.onDidChangeModified =>
|
||||
@terminatePendingState() if not @hasTerminatedPendingState and @buffer.isModified()
|
||||
|
||||
@preserveCursorPositionOnBufferReload()
|
||||
|
||||
terminatePendingState: ->
|
||||
@emitter.emit 'did-terminate-pending-state' if not @hasTerminatedPendingState
|
||||
@hasTerminatedPendingState = true
|
||||
@@ -2361,14 +2360,6 @@ class TextEditor extends Model
|
||||
positions[position] = true
|
||||
return
|
||||
|
||||
preserveCursorPositionOnBufferReload: ->
|
||||
cursorPosition = null
|
||||
@disposables.add @buffer.onWillReload =>
|
||||
cursorPosition = @getCursorBufferPosition()
|
||||
@disposables.add @buffer.onDidReload =>
|
||||
@setCursorBufferPosition(cursorPosition) if cursorPosition
|
||||
cursorPosition = null
|
||||
|
||||
###
|
||||
Section: Selections
|
||||
###
|
||||
@@ -2982,7 +2973,7 @@ class TextEditor extends Model
|
||||
# Returns a {Boolean} or undefined if no non-comment lines had leading
|
||||
# whitespace.
|
||||
usesSoftTabs: ->
|
||||
for bufferRow in [0..@buffer.getLastRow()]
|
||||
for bufferRow in [0..Math.min(1000, @buffer.getLastRow())]
|
||||
continue if @tokenizedBuffer.tokenizedLines[bufferRow]?.isComment()
|
||||
|
||||
line = @buffer.lineForRow(bufferRow)
|
||||
|
||||
@@ -147,19 +147,12 @@ class WindowEventHandler
|
||||
@document.body.classList.remove("fullscreen")
|
||||
|
||||
handleWindowBeforeunload: (event) =>
|
||||
projectHasPaths = @atomEnvironment.project.getPaths().length > 0
|
||||
confirmed = @atomEnvironment.workspace?.confirmClose(windowCloseRequested: true, projectHasPaths: projectHasPaths)
|
||||
if confirmed and not @reloadRequested and not @atomEnvironment.inSpecMode() and @atomEnvironment.getCurrentWindow().isWebViewFocused()
|
||||
if not @reloadRequested and not @atomEnvironment.inSpecMode() and @atomEnvironment.getCurrentWindow().isWebViewFocused()
|
||||
@atomEnvironment.hide()
|
||||
@reloadRequested = false
|
||||
|
||||
@atomEnvironment.storeWindowDimensions()
|
||||
if confirmed
|
||||
@atomEnvironment.unloadEditorWindow()
|
||||
@atomEnvironment.destroy()
|
||||
else
|
||||
@applicationDelegate.didCancelWindowUnload()
|
||||
event.returnValue = false
|
||||
@atomEnvironment.unloadEditorWindow()
|
||||
@atomEnvironment.destroy()
|
||||
|
||||
handleWindowToggleFullScreen: =>
|
||||
@atomEnvironment.toggleFullScreen()
|
||||
|
||||
@@ -1340,9 +1340,9 @@ module.exports = class Workspace extends Model {
|
||||
}
|
||||
|
||||
confirmClose (options) {
|
||||
return this.getPaneContainers()
|
||||
.map(container => container.confirmClose(options))
|
||||
.every(saved => saved)
|
||||
return Promise.all(this.getPaneContainers().map(container =>
|
||||
container.confirmClose(options)
|
||||
)).then((results) => !results.includes(false))
|
||||
}
|
||||
|
||||
// Save the active pane item.
|
||||
@@ -1352,7 +1352,7 @@ module.exports = class Workspace extends Model {
|
||||
// {::saveActivePaneItemAs} # will be called instead. This method does nothing
|
||||
// if the active item does not implement a `.save` method.
|
||||
saveActivePaneItem () {
|
||||
this.getCenter().getActivePane().saveActiveItem()
|
||||
return this.getCenter().getActivePane().saveActiveItem()
|
||||
}
|
||||
|
||||
// Prompt the user for a path and save the active pane item to it.
|
||||
@@ -1975,7 +1975,7 @@ module.exports = class Workspace extends Model {
|
||||
if (editor.getPath()) {
|
||||
const checkoutHead = () => {
|
||||
return this.project.repositoryForDirectory(new Directory(editor.getDirectoryPath()))
|
||||
.then(repository => repository != null ? repository.checkoutHeadForEditor(editor) : undefined)
|
||||
.then(repository => repository && repository.checkoutHeadForEditor(editor))
|
||||
}
|
||||
|
||||
if (this.config.get('editor.confirmCheckoutHeadRevision')) {
|
||||
|
||||
Reference in New Issue
Block a user