Merge pull request #3355 from atom/ks-open-files-in-current-window

Open file paths in focused window
This commit is contained in:
Kevin Sawicki
2014-08-25 09:39:11 -07:00
5 changed files with 77 additions and 16 deletions

View File

@@ -308,6 +308,9 @@ class Atom extends Model
@themes.loadBaseStylesheets()
@packages.loadPackages()
@deserializeEditorWindow()
@watchProjectPath()
@packages.activate()
@keymaps.loadUserKeymap()
@requireUserInitScript()
@@ -347,13 +350,29 @@ class Atom extends Model
pack.reloadStylesheets?()
null
# Notify the browser project of the window's current project path
watchProjectPath: ->
onProjectPathChanged = =>
ipc.send('window-command', 'project-path-changed', @project.getPath())
@subscribe @project, 'path-changed', onProjectPathChanged
onProjectPathChanged()
# Public: Open a new Atom window using the given options.
#
# Calling this method without an options parameter will open a prompt to pick
# a file/folder to open in the new window.
#
# options - An {Object} with the following keys:
# :pathsToOpen - An {Array} of {String} paths to open.
# :pathsToOpen - An {Array} of {String} paths to open.
# :newWindow - A {Boolean}, true to always open a new window instead of
# reusing existing windows depending on the paths to open.
# :devMode - A {Boolean}, true to open the window in development mode.
# Development mode loads the Atom source from the locally
# cloned repository and also loads all the packages in
# ~/.atom/dev/packages
# :safeMode - A {Boolean}, true to open the window in safe mode. Safe
# mode prevents all packages installed to ~/.atom/packages
# from loading.
open: (options) ->
ipc.send('open', options)

View File

@@ -103,6 +103,12 @@ class AtomApplication
window.once 'window:loaded', =>
@autoUpdateManager.emitUpdateAvailableEvent(window)
focusHandler = => @lastFocusedWindow = window
window.browserWindow.on 'focus', focusHandler
window.browserWindow.once 'closed', =>
@lastFocusedWindow = null if window is @lastFocusedWindow
window.browserWindow.removeListener 'focus', focusHandler
# Creates server to listen for additional atom application launches.
#
# You can run the atom command multiple times, but after the first launch
@@ -199,13 +205,15 @@ class AtomApplication
# A request from the associated render process to open a new render process.
ipc.on 'open', (event, options) =>
window = @windowForEvent(event)
if options?
if options.pathsToOpen?.length > 0
options.window = window
@openPaths(options)
else
new AtomWindow(options)
else
@promptForPath()
@promptForPath({window})
ipc.on 'update-application-menu', (event, template, keystrokesByCommand) =>
@applicationMenu.update(template, keystrokesByCommand)
@@ -281,8 +289,12 @@ class AtomApplication
# Returns the {AtomWindow} for the given path.
windowForPath: (pathToOpen) ->
for atomWindow in @windows
return atomWindow if atomWindow.containsPath(pathToOpen)
_.find @windows, (atomWindow) -> atomWindow.containsPath(pathToOpen)
# Returns the {AtomWindow} for the given ipc event.
windowForEvent: ({sender}) ->
window = BrowserWindow.fromWebContents(sender)
_.find @windows, ({browserWindow}) -> window is browserWindow
# Public: Returns the currently focused {AtomWindow} or undefined if none.
focusedWindow: ->
@@ -296,9 +308,10 @@ class AtomApplication
# :newWindow - Boolean of whether this should be opened in a new window.
# :devMode - Boolean to control the opened window's dev mode.
# :safeMode - Boolean to control the opened window's safe mode.
openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode}) ->
# :window - {AtomWindow} to open file paths in.
openPaths: ({pathsToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, window}) ->
for pathToOpen in pathsToOpen ? []
@openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode})
@openPath({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, window})
# Public: Opens a single path, in an existing window if possible.
#
@@ -309,12 +322,27 @@ class AtomApplication
# :devMode - Boolean to control the opened window's dev mode.
# :safeMode - Boolean to control the opened window's safe mode.
# :windowDimensions - Object with height and width keys.
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions}={}) ->
# :window - {AtomWindow} to open file paths in.
openPath: ({pathToOpen, pidToKillWhenClosed, newWindow, devMode, safeMode, windowDimensions, window}={}) ->
{pathToOpen, initialLine, initialColumn} = @locationForPathToOpen(pathToOpen)
unless devMode
existingWindow = @windowForPath(pathToOpen) unless pidToKillWhenClosed or newWindow
if existingWindow
unless pidToKillWhenClosed or newWindow
pathToOpenStat = fs.statSyncNoException(pathToOpen)
# Default to using the specified window or the last focused window
currentWindow = window ? @lastFocusedWindow
if pathToOpenStat.isFile?()
# Open the file in the current window
existingWindow = currentWindow
else if pathToOpenStat.isDirectory?()
# Open the folder in the current window if it doesn't have a path
existingWindow = currentWindow unless currentWindow?.hasProjectPath()
# Don't reuse windows in dev mode
existingWindow ?= @windowForPath(pathToOpen) unless devMode
if existingWindow?
openedWindow = existingWindow
openedWindow.openPath(pathToOpen, initialLine)
openedWindow.restore()
@@ -331,7 +359,7 @@ class AtomApplication
if pidToKillWhenClosed?
@pidsToOpenWindows[pidToKillWhenClosed] = openedWindow
openedWindow.browserWindow.on 'closed', =>
openedWindow.browserWindow.once 'closed', =>
@killProcessForWindow(openedWindow)
# Kill all processes associated with opened windows.
@@ -444,7 +472,8 @@ class AtomApplication
# should be in dev mode or not.
# :safeMode - A Boolean which controls whether any newly opened windows
# should be in safe mode or not.
promptForPath: ({type, devMode, safeMode}={}) ->
# :window - An {AtomWindow} to use for opening a selected file path.
promptForPath: ({type, devMode, safeMode, window}={}) ->
type ?= 'all'
properties =
switch type
@@ -453,4 +482,4 @@ class AtomApplication
when 'all' then ['openFile', 'openDirectory']
else throw new Error("#{type} is an invalid type for promptForPath")
dialog.showOpenDialog title: 'Open', properties: properties.concat(['multiSelections', 'createDirectory']), (pathsToOpen) =>
@openPaths({pathsToOpen, devMode, safeMode})
@openPaths({pathsToOpen, devMode, safeMode, window})

View File

@@ -25,9 +25,9 @@ class AtomWindow
# Normalize to make sure drive letter case is consistent on Windows
@resourcePath = path.normalize(@resourcePath) if @resourcePath
@browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath
global.atomApplication.addWindow(this)
@browserWindow = new BrowserWindow show: false, title: 'Atom', icon: @constructor.iconPath
@handleEvents()
loadSettings = _.extend({}, settings)
@@ -49,6 +49,8 @@ class AtomWindow
@emit 'window:loaded'
@loaded = true
@browserWindow.on 'project-path-changed', (@projectPath) =>
@browserWindow.loadUrl @getUrl(loadSettings)
@browserWindow.focusOnWebView() if @isSpec
@@ -66,6 +68,8 @@ class AtomWindow
slashes: true
query: {loadSettings: JSON.stringify(loadSettings)}
hasProjectPath: -> @projectPath?.length > 0
getInitialPath: ->
@browserWindow.loadSettings.initialPath

View File

@@ -63,7 +63,14 @@ parseCommandLine = ->
options.usage """
Atom Editor v#{version}
Usage: atom [options] [file ...]
Usage: atom [options] [path ...]
One or more paths to files or folders to open may be specified.
File paths will open in the current window.
Folder paths will open in an existing window if that folder has already been
opened or a new window if it hasn't.
"""
options.alias('d', 'dev').boolean('d').describe('d', 'Run in development mode.')
options.alias('f', 'foreground').boolean('f').describe('f', 'Keep the browser process in the foreground.')

View File

@@ -28,7 +28,9 @@ class WindowEventHandler
@subscribe $(window), 'blur', -> document.body.classList.add('is-blurred')
@subscribe $(window), 'window:open-path', (event, {pathToOpen, initialLine, initialColumn}) ->
unless fs.isDirectorySync(pathToOpen)
if fs.isDirectorySync(pathToOpen)
atom.project.setPath(pathToOpen) unless atom.project.getPath()
else
atom.workspace?.open(pathToOpen, {initialLine, initialColumn})
@subscribe $(window), 'beforeunload', =>