Merge branch 'chrome'

This commit is contained in:
Corey Johnson & Nathan Sobo
2012-03-01 16:24:01 -08:00
2647 changed files with 32546 additions and 325808 deletions

View File

@@ -0,0 +1,2 @@
App = require 'app'
window.atom = new App(atom.loadPath, $native)

View File

@@ -1,28 +1,30 @@
Native = require 'native'
GlobalKeymap = require 'global-keymap'
$ = require 'jquery'
_ = require 'underscore'
module.exports =
class App
globalKeymap: null
native: null
keymap: null
windows: null
constructor: ->
@native = new Native
@globalKeymap = new GlobalKeymap
$(document).on 'keydown', (e) => @globalKeymap.handleKeyEvent(e)
constructor: (@loadPath, nativeMethods)->
@windows = []
@setupKeymap()
bindKeys: (selector, bindings) ->
@globalKeymap.bindKeys(selector, bindings)
bindKey: (selector, pattern, eventName) ->
@globalKeymap.bindKey(selector, pattern, eventName)
setupKeymap: ->
@keymap = new GlobalKeymap()
$(document).on 'keydown', (e) => @keymap.handleKeyEvent(e)
open: (url) ->
OSX.NSApp.open url
$native.open url
quit: ->
OSX.NSApp.terminate null
$native.terminate null
windows: ->
controller.jsWindow for controller in OSX.NSApp.controllers
windowOpened: (window) ->
@windows.push window
windowClosed: (window) ->
index = @windows.indexOf(window)
@windows.splice(index, 1) if index >= 0

View File

@@ -41,7 +41,7 @@ class Editor extends View
@setBuffer(new Buffer)
bindKeys: ->
atom.bindKeys '*:not(.editor *)',
window.keymap.bindKeys '*:not(.editor *)',
right: 'move-right'
left: 'move-left'
down: 'move-down'
@@ -304,7 +304,7 @@ class Editor extends View
cutSelection: -> @selection.cut()
copySelection: -> @selection.copy()
paste: -> @selection.insertText(atom.native.readFromPasteboard())
paste: -> @selection.insertText($native.readFromPasteboard())
foldSelection: -> @selection.fold()

View File

@@ -17,7 +17,7 @@ class FileFinder extends View
@maxResults = 10
@populateUrlList()
atom.bindKeys ".file-finder",
window.keymap.bindKeys ".file-finder",
'up': 'move-up'
'down': 'move-down'
'enter': 'select'
@@ -60,7 +60,12 @@ class FileFinder extends View
urls = @urls
else
scoredUrls = ({url, score: stringScore(url, query)} for url in @urls)
scoredUrls.sort (a, b) -> a.score > b.score
scoredUrls.sort (a, b) ->
if a.score > b.score then -1
else if a.score < b.score then 1
else 0
window.x = scoredUrls
urls = (urlAndScore.url for urlAndScore in scoredUrls when urlAndScore.score > 0)
urls.slice 0, @maxResults

View File

@@ -9,6 +9,16 @@ class GlobalKeymap
constructor: ->
@bindingSets = []
@bindKeys "*",
'meta-n': 'newWindow'
'meta-o': 'open'
$(document).on 'newWindow', => $native.newWindow()
$(document).on 'open', =>
url = $native.openDialog()
atom.open(url) if url
bindKeys: (selector, bindings) ->
@bindingSets.unshift(new BindingSet(selector, bindings))
@@ -19,7 +29,7 @@ class GlobalKeymap
handleKeyEvent: (event) ->
event.keystroke = @keystrokeStringForEvent(event)
currentNode = $(event.target)
currentNode = $(event.target)
while currentNode.length
candidateBindingSets = @bindingSets.filter (set) -> currentNode.is(set.selector)
candidateBindingSets.sort (a, b) -> b.specificity - a.specificity

View File

@@ -11,8 +11,8 @@ class Project
getFilePaths: ->
projectUrl = @url
fs.async.listFiles(@url, true).pipe (urls) ->
url.replace(projectUrl, "") for url in urls
fs.async.listTree(@url).pipe (urls) ->
url.replace(projectUrl, "") for url in urls when fs.isFile(url)
open: (filePath) ->
filePath = @resolve filePath

View File

@@ -7,7 +7,6 @@ Buffer = require 'buffer'
Editor = require 'editor'
FileFinder = require 'file-finder'
Project = require 'project'
GlobalKeymap = require 'global-keymap'
VimMode = require 'vim-mode'
module.exports =
@@ -18,13 +17,11 @@ class RootView extends View
@div id: 'main', outlet: 'main', =>
@subview 'editor', new Editor
globalKeymap: null
initialize: ({url}) ->
@editor.keyEventHandler = atom.globalKeymap
@editor.keyEventHandler = window.keymap
@createProject(url)
atom.bindKeys '*'
window.keymap.bindKeys '*'
'meta-s': 'save'
'meta-w': 'close'
'meta-t': 'toggle-file-finder'
@@ -43,9 +40,6 @@ class RootView extends View
@project = new Project(fs.directory(url))
@editor.setBuffer(@project.open(url)) if fs.isFile(url)
bindKeys: (selector, bindings) ->
@globalKeymap.bindKeys(selector, bindings)
addPane: (view) ->
pane = $('<div class="pane">')
pane.append(view)

View File

@@ -166,7 +166,7 @@ class Selection extends View
copy: ->
return if @isEmpty()
text = @editor.buffer.getTextInRange(@getBufferRange())
atom.native.writeToPasteboard text
$native.writeToPasteboard text
fold: ->
range = @getBufferRange()

View File

@@ -15,13 +15,13 @@ class VimMode
@opStack = []
@activateCommandMode()
atom.bindKeys '.editor', 'escape': 'activate-command-mode'
window.keymap.bindKeys '.editor', 'escape': 'activate-command-mode'
@editor.on 'activate-command-mode', => @activateCommandMode()
@setupCommandMode()
setupCommandMode: ->
atom.bindKeys '.command-mode', (e) =>
window.keymap.bindKeys '.command-mode', (e) =>
if e.keystroke.match /^\d$/
return 'command-mode:numeric-prefix'
if e.keystroke.match /^.$/
@@ -62,7 +62,7 @@ class VimMode
for pattern, commandName of bindings
prefixedBindings[pattern] = "command-mode:#{commandName}"
atom.bindKeys ".command-mode", prefixedBindings
window.keymap.bindKeys ".command-mode", prefixedBindings
handleCommands: (commands) ->
_.each commands, (fn, commandName) =>

View File

@@ -1,8 +1,8 @@
fs = require 'fs'
_ = require 'underscore'
$ = require 'jquery'
fs = require 'fs'
GlobalKeymap = require 'global-keymap'
RootView = require 'root-view'
# This a weirdo file. We don't create a Window class, we just add stuff to
@@ -10,21 +10,33 @@ RootView = require 'root-view'
windowAdditions =
rootView: null
menuItemActions: null
keymap: null
startup: ->
@menuItemActions = {}
@rootView = new RootView(url: $atomController.url?.toString())
$('body').append @rootView
@registerEventHandlers()
@bindMenuItems()
$(this).on 'close', => @close()
startup: (url) ->
@setupKeymap()
@attachRootView(url)
$(window).on 'close', =>
@shutdown()
@close()
$(window).focus()
atom.windowOpened this
shutdown: ->
@rootView.remove()
$(window).unbind('focus')
$(window).unbind('blur')
atom.windowClosed this
setupKeymap: ->
@keymap = new GlobalKeymap()
$(document).on 'keydown', (e) => @keymap.handleKeyEvent(e)
attachRootView: (url) ->
@rootView = new RootView {url}
$('body').append @rootView
requireStylesheet: (path) ->
fullPath = require.resolve(path)
@@ -32,35 +44,15 @@ windowAdditions =
return if $("head style[path='#{fullPath}']").length
$('head').append "<style path='#{fullPath}'>#{content}</style>"
bindMenuItems: ->
# we want to integrate this better with keybindings
# @bindMenuItem "File > Save", "meta+s", => @rootView.editor.save()
bindMenuItem: (path, pattern, action) ->
@menuItemActions[path] = {action: action, pattern: pattern}
registerEventHandlers: ->
$(window).focus => @registerMenuItems()
$(window).blur -> atom.native.resetMainMenu()
registerMenuItems: ->
for path, {pattern} of @menuItemActions
atom.native.addMenuItem(path, pattern)
performActionForMenuItemPath: (path) ->
@menuItemActions[path].action()
showConsole: ->
$atomController.webView.inspector.showConsole true
$native.showDevTools()
onerror: ->
@showConsole true
@showConsole()
for key, value of windowAdditions
console.warn "DOMWindow already has a key named `#{key}`" if window[key]
window[key] = value
requireStylesheet 'reset.css'
requireStylesheet 'atom.css'

View File

@@ -3,13 +3,12 @@
_ = require 'underscore'
$ = require 'jquery'
jscocoa = require 'jscocoa'
module.exports =
# Make the given path absolute by resolving it against the
# current working directory.
absolute: (path) ->
$atomController.absolute(path).toString()
$native.absolute(path)
# Return the basename of the given path. That is the path with
# any leading directory components removed. If specified, also
@@ -18,22 +17,17 @@ module.exports =
base = path.split("/").pop()
if ext then base.replace(RegEx(ext + "$"), "") else base
# Set the current working directory to `path`.
changeWorkingDirectory: (path) ->
OSX.NSFileManager.defaultManager.changeCurrentDirectoryPath path
# Return the dirname of the given path. That is the path with any trailing
# Return the dirname of the given path. That is the path with any trailing
# non-directory component removed.
directory: (path) ->
absPath = @absolute(path)
if @isDirectory(absPath)
absPath.replace(/\/?$/, '/')
if @isDirectory(path)
path.replace(/\/?$/, '/')
else
absPath.replace(new RegExp("/#{@base(path)}$"), '/')
path.replace(new RegExp("/#{@base(path)}$"), '/')
# Returns true if the file specified by path exists
exists: (path) ->
OSX.NSFileManager.defaultManager.fileExistsAtPath_isDirectory path, null
$native.exists path
join: (paths...) ->
return paths[0] if paths.length == 1
@@ -43,62 +37,44 @@ module.exports =
# Returns true if the file specified by path exists and is a
# directory.
isDirectory: (path) ->
isDir = new jscocoa.outArgument
exists = OSX.NSFileManager.defaultManager.
fileExistsAtPath_isDirectory path, isDir
exists and isDir.valueOf()
$native.isDirectory path
# Returns true if the file specified by path exists and is a
# regular file.
isFile: (path) ->
$atomController.fs.isFile path
not $native.isDirectory path
# Returns an array with all the names of files contained
# in the directory path.
list: (path, recursive) ->
path = @absolute path
fm = OSX.NSFileManager.defaultManager
if recursive
paths = fm.subpathsAtPath path
else
paths = fm.contentsOfDirectoryAtPath_error path, null
_.map paths, (entry) -> "#{path}/#{entry}"
list: (path) ->
$native.list(path, false)
# Return an array with all directories below (and including)
# the given path, as discovered by depth-first traversal. Entries
# are in lexically sorted order within directories. Symbolic links
# to directories are not traversed into.
listDirectoryTree: (path) ->
@list path, true
listTree: (path) ->
$native.list(path, true)
# Remove a file at the given path. Throws an error if path is not a
# file or a symbolic link to a file.
remove: (path) ->
fm = OSX.NSFileManager.defaultManager
paths = fm.removeItemAtPath_error path, null
$native.remove path
# Open, read, and close a file, returning the file's contents.
read: (path) ->
path = @absolute path
enc = OSX.NSUTF8StringEncoding
OSX.NSString.stringWithContentsOfFile_encoding_error(path, enc, null)
.toString()
$native.read(path)
# Open, write, flush, and close a file, writing the given content.
write: (path, content) ->
str = OSX.NSString.stringWithUTF8String content
path = @absolute path
enc = OSX.NSUTF8StringEncoding
str.writeToFile_atomically_encoding_error path, true, enc, null
# Return the path name of the current working directory.
workingDirectory: ->
OSX.NSFileManager.defaultManager.currentDirectoryPath.toString()
$native.write(path, content)
async:
listFiles: (path, recursive) ->
list: (path) ->
deferred = $.Deferred()
$atomController.fs.listFilesAtPath_recursive_onComplete path, recursive, (subpaths) ->
$native.asyncList path, false, (subpaths) ->
deferred.resolve subpaths
deferred
listTree: (path) ->
deferred = $.Deferred()
$native.asyncList path, true, (subpaths) ->
deferred.resolve subpaths
deferred

View File

@@ -1,13 +0,0 @@
# This is where we put things from JSCocoa's class.js file
exports.outArgument = (args...) ->
# Derive to store some javascript data in the internal hash
if not @outArgument2?
OSX.JSCocoa.createClass_parentClass_ 'JSCocoaOutArgument2', 'JSCocoaOutArgument'
o = OSX.JSCocoaOutArgument2.instance
o.isOutArgument = true
if args.length == 2
o.mateWithMemoryBuffer_atIndex_ args[0], args[1]
o

View File

@@ -1,86 +0,0 @@
_ = require 'underscore'
module.exports =
class Native
alert: (message, detailedMessage, buttons) ->
alert = OSX.NSAlert.alloc.init
alert.setMessageText message
alert.setInformativeText detailedMessage
callbacks = {}
for label, callback of buttons
button = alert.addButtonWithTitle label
callbacks[button.tag] = callback
buttonTag = alert.runModal
return callbacks[buttonTag]()
# path - Optional. The String path to the file to base it on.
newWindow: (path) ->
controller = OSX.NSApp.createController path
controller.window
controller.window.makeKeyAndOrderFront null
# Returns null or a file path.
openPanel: ->
panel = OSX.NSOpenPanel.openPanel
panel.setCanChooseDirectories true
if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
return null
filename = panel.filenames.lastObject
localStorage.lastOpenedPath = filename
filename.valueOf()
# Returns null or a file path.
savePanel: ->
panel = OSX.NSSavePanel.savePanel
if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
return null
panel.filenames.lastObject.valueOf()
writeToPasteboard: (text) ->
pb = OSX.NSPasteboard.generalPasteboard
pb.declareTypes_owner [OSX.NSStringPboardType], null
pb.setString_forType text, OSX.NSStringPboardType
readFromPasteboard: (text) ->
pb = OSX.NSPasteboard.generalPasteboard
results = pb.readObjectsForClasses_options [OSX.NSString], null
results?[0]?.toString()
resetMainMenu: (menu) ->
OSX.NSApp.resetMainMenu
addMenuItem: (itemPath, keyPattern) ->
itemPathComponents = itemPath.split /\s*>\s*/
submenu = @buildSubmenuPath(OSX.NSApp.mainMenu, itemPathComponents[0..-2])
title = _.last(itemPathComponents)
unless submenu.itemWithTitle(title)
item = OSX.AtomMenuItem.alloc.initWithTitle_itemPath(title, itemPath).autorelease
item.setKeyEquivalentModifierMask 0 # Because in Cocoa defaults it to NSCommandKeyMask
if keyPattern
bindingSet = new (require('binding-set'))("*", {})
keys = bindingSet.parseKeyPattern keyPattern
modifierMask = (keys.metaKey and OSX.NSCommandKeyMask ) |
(keys.shiftKey and OSX.NSShiftKeyMask) |
(keys.altKey and OSX.NSAlternateKeyMask) |
(keys.ctrlKey and OSX.NSControlKeyMask)
item.setKeyEquivalent keys.key
item.setKeyEquivalentModifierMask modifierMask
submenu.addItem(item)
buildSubmenuPath: (menu, path) ->
return menu if path.length == 0
first = path[0]
unless item = menu.itemWithTitle(first)
item = OSX.AtomMenuItem.alloc.initWithTitle_action_keyEquivalent(first, null, "").autorelease
menu.addItem(item)
unless submenu = item.submenu
submenu = OSX.NSMenu.alloc.initWithTitle(first)
item.submenu = submenu
@buildSubmenuPath(submenu, path[1..-1])

View File

@@ -1,14 +1,10 @@
# Hack to get code reloading working in dev mode
resourcePath = $atomController.projectPath ? OSX.NSBundle.mainBundle.resourcePath
paths = [
"#{resourcePath}/spec"
"#{resourcePath}/src/stdlib"
"#{resourcePath}/src/atom"
"#{resourcePath}/src"
"#{resourcePath}/extensions"
"#{resourcePath}/vendor"
"#{resourcePath}/static"
"#{atom.loadPath}/spec"
"#{atom.loadPath}/src/stdlib"
"#{atom.loadPath}/src/atom"
"#{atom.loadPath}/src"
"#{atom.loadPath}/vendor"
"#{atom.loadPath}/static"
]
window.__filename = null
@@ -16,7 +12,7 @@ window.__filename = null
nakedLoad = (file) ->
file = resolve file
code = __read file
__jsc__.evalJSString_withScriptPath code, file
window.eval(code + "\n//@ sourceURL=" + file)
require = (file, cb) ->
return cb require file if cb?
@@ -55,7 +51,7 @@ exts =
define(function(require, exports, module) { 'use strict'; #{code};
});
"""
__jsc__.evalJSString_withScriptPath code, file
eval(code + "\n//@ sourceURL=" + file)
__defines.pop()?.call()
coffee: (file) ->
exts.js(file, __coffeeCache(file))
@@ -65,10 +61,6 @@ resolve = (file) ->
parts = file.split '!'
file = parts[parts.length-1]
if file[0] is '~'
file = OSX.NSString.stringWithString(file)
.stringByExpandingTildeInPath.toString()
if file[0..1] is './'
prefix = __filename.split('/')[0..-2].join '/'
file = file.replace './', "#{prefix}/"
@@ -78,7 +70,7 @@ resolve = (file) ->
file = file.replace '../', "#{prefix}/"
if file[0] isnt '/'
require.paths.some (path) ->
paths.some (path) ->
fileExists = /\.(.+)$/.test(file) and __exists "#{path}/#{file}"
jsFileExists = not /\.(.+)$/.test(file) and __exists "#{path}/#{file}.js"
@@ -107,19 +99,15 @@ __expand = (path) ->
return null
__exists = (path) ->
OSX.NSFileManager.defaultManager.fileExistsAtPath path
$native.exists path
__coffeeCache = (filePath) ->
js = OSX.NSApp.getCachedScript(filePath)
if not js
{CoffeeScript} = require 'coffee-script'
js = CoffeeScript.compile(__read(filePath), filename: filePath)
OSX.NSApp.setCachedScript_contents(filePath, js)
js
{CoffeeScript} = require 'coffee-script'
CoffeeScript.compile(__read(filePath), filename: filePath)
__read = (path) ->
try
OSX.NSString.stringWithContentsOfFile(path).toString()
$native.read(path)
catch e
throw "require: can't read #{path}"
@@ -130,7 +118,6 @@ this.require = require
this.nakedLoad = nakedLoad
this.define = define
this.require.resourcePath = resourcePath
this.require.paths = paths
this.require.exts = exts

View File

@@ -1,7 +1,4 @@
# Like sands through the hourglass, so are the days of our lives.
App = require 'app'
window.atom = new App
require 'window'
window.startup()
window.startup $pathToOpen