mirror of
https://github.com/atom/atom.git
synced 2026-04-28 03:01:47 -04:00
things got a little out of hand
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//
|
||||
//
|
||||
// JSCocoa.m
|
||||
// JSCocoa
|
||||
//
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
$ = require 'jquery'
|
||||
|
||||
Pane = require 'pane'
|
||||
|
||||
module.exports =
|
||||
class EditorPane extends Pane
|
||||
position: 'main'
|
||||
|
||||
html: $ '<div id="editor"></div>'
|
||||
|
||||
# You know what I don't like? This constructor.
|
||||
constructor: (@window, @editor) ->
|
||||
super @window
|
||||
|
||||
# Resize editor when panes are added/removed
|
||||
el = document.body
|
||||
el.addEventListener 'DOMNodeInsertedIntoDocument', => @resize()
|
||||
el.addEventListener 'DOMNodeRemovedFromDocument', => @resize()
|
||||
|
||||
resize: (timeout=1) ->
|
||||
setTimeout =>
|
||||
@editor.ace.focus()
|
||||
@editor.ace.resize()
|
||||
, timeout
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = require 'editor/editor'
|
||||
@@ -59,13 +59,19 @@
|
||||
<body>
|
||||
<div id='app-horizontal'>
|
||||
<div id='app-vertical'>
|
||||
<div class='main'></div>
|
||||
<div class='main'>
|
||||
<div id='ace-editor'></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
<script src='src/require.js'></script>
|
||||
<script>
|
||||
window.onerror = function() {
|
||||
atomController.webView.inspector.showConsole(true)
|
||||
}
|
||||
|
||||
require('startup');
|
||||
</script>
|
||||
|
||||
|
||||
@@ -5,11 +5,7 @@ module.exports =
|
||||
class App
|
||||
@startup: ->
|
||||
KeyBinder.register "app", @
|
||||
|
||||
window.startup()
|
||||
|
||||
KeyBinder.load "#{@root}/static/key-bindings.coffee"
|
||||
KeyBinder.load "~/.atomicity/key-bindings.coffee"
|
||||
|
||||
@quit: ->
|
||||
OSX.NSApp.terminate OSX.NSApp
|
||||
|
||||
@@ -1,39 +1,39 @@
|
||||
_ = require 'underscore'
|
||||
|
||||
File = require 'fs'
|
||||
Chrome = require 'chrome'
|
||||
Extension = require 'extension'
|
||||
EditorPane = require 'editor/editor-pane'
|
||||
|
||||
{bindKey} = require 'keybinder'
|
||||
|
||||
fs = require 'fs'
|
||||
ace = require 'ace/ace'
|
||||
|
||||
Event = require 'event'
|
||||
KeyBinder = require 'key-binder'
|
||||
Native = require 'native'
|
||||
|
||||
{EditSession} = require 'ace/edit_session'
|
||||
{UndoManager} = require 'ace/undomanager'
|
||||
|
||||
module.exports =
|
||||
class Editor extends Extension
|
||||
class Editor
|
||||
filename: null
|
||||
|
||||
keymap: ->
|
||||
# Maybe these don't go here?
|
||||
'Command-S' : 'save'
|
||||
'Command-Shift-S' : 'saveAs'
|
||||
sessions: {}
|
||||
|
||||
# These are cool though.
|
||||
'Command-C' : 'copy'
|
||||
'Command-X' : 'cut'
|
||||
'Command-R' : 'eval'
|
||||
'Command-/' : 'toggleComment'
|
||||
'Command-[' : 'outdent'
|
||||
'Command-]' : 'indent'
|
||||
'Alt-F' : 'forwardWord'
|
||||
'Alt-B' : 'backWord'
|
||||
'Alt-D' : 'deleteWord'
|
||||
'Alt-Shift-,' : 'home'
|
||||
'Alt-Shift-.' : 'end'
|
||||
'Ctrl-L' : 'consolelog'
|
||||
constructor: ->
|
||||
KeyBinder.register "editor", @
|
||||
# Resize editor when panes are added/removed
|
||||
el = document.body
|
||||
el.addEventListener 'DOMNodeInsertedIntoDocument', => @resize()
|
||||
el.addEventListener 'DOMNodeRemovedFromDocument', => @resize()
|
||||
|
||||
@ace = ace.edit "ace-editor"
|
||||
|
||||
# This stuff should all be grabbed from the .atomicity dir
|
||||
@ace.setTheme require "ace/theme/twilight"
|
||||
@ace.getSession().setUseSoftTabs true
|
||||
@ace.getSession().setTabSize 2
|
||||
@ace.setShowInvisibles(true)
|
||||
@ace.setPrintMarginColumn 78
|
||||
|
||||
#@ace.getSession().on 'change', -> @window.setDirty true
|
||||
Event.on 'window:open', (e) => @open e.details
|
||||
Event.on 'window:close', (e) => @close e.details
|
||||
|
||||
modeMap:
|
||||
js: 'javascript'
|
||||
@@ -45,27 +45,6 @@ class Editor extends Extension
|
||||
cs: 'csharp'
|
||||
rb: 'ruby'
|
||||
|
||||
sessions: {}
|
||||
|
||||
constructor: (args...) ->
|
||||
super(args...)
|
||||
|
||||
@pane = new EditorPane @window
|
||||
@pane.add()
|
||||
|
||||
@ace = ace.edit "editor"
|
||||
|
||||
# This stuff should all be grabbed from the .atomicity dir
|
||||
@ace.setTheme require "ace/theme/twilight"
|
||||
@ace.getSession().setUseSoftTabs true
|
||||
@ace.getSession().setTabSize 2
|
||||
@ace.setShowInvisibles(true)
|
||||
@ace.setPrintMarginColumn 78
|
||||
|
||||
@ace.getSession().on 'change', -> @window.setDirty true
|
||||
@window.on 'open', ({filename}) => @open filename
|
||||
@window.on 'close', ({filename}) => @close filename
|
||||
|
||||
modeForLanguage: (language) ->
|
||||
language = language.toLowerCase()
|
||||
modeName = @modeMap[language] or language
|
||||
@@ -76,45 +55,36 @@ class Editor extends Extension
|
||||
null
|
||||
|
||||
setMode: ->
|
||||
if mode = @modeForLanguage _.last @filename.split '.'
|
||||
if mode = @modeForLanguage _.last @activePath.split '.'
|
||||
@ace.getSession().setMode new mode
|
||||
|
||||
save: ->
|
||||
return @saveAs() if not @filename
|
||||
return @saveAs() if not @activePath
|
||||
|
||||
@removeTrailingWhitespace()
|
||||
File.write @filename, @code()
|
||||
@sessions[@filename] = @ace.getSession()
|
||||
@window.setDirty false
|
||||
@window._emit 'save', { filename: @filename }
|
||||
fs.write @activePath, @code()
|
||||
@sessions[@activePath] = @ace.getSession()
|
||||
#@window.setDirty false
|
||||
#@window._emit 'save', { filename: @activePath }
|
||||
|
||||
open: (path) ->
|
||||
path = Chrome.openPanel() if not path
|
||||
return if not path
|
||||
@filename = path
|
||||
return unless fs.isFile path
|
||||
@activePath = path
|
||||
|
||||
if File.isDirectory @filename
|
||||
File.changeWorkingDirectory @filename
|
||||
@window.setTitle _.last @filename.split '/'
|
||||
@ace.setSession @newSession()
|
||||
@window.setDirty false
|
||||
else
|
||||
if /png|jpe?g|gif/i.test @filename
|
||||
Chrome.openURL @filename
|
||||
else
|
||||
@window.setTitle _.last @filename.split '/'
|
||||
@sessions[@filename] or= @newSession File.read @filename
|
||||
@ace.setSession @sessions[@filename]
|
||||
@window.setDirty false
|
||||
@setMode()
|
||||
@sessions[@activePath] ?= @newSession fs.read @activePath
|
||||
@ace.setSession @sessions[@activePath]
|
||||
@setMode()
|
||||
|
||||
close: (path) ->
|
||||
@deleteSession path
|
||||
@activePath = null if path is @activePath
|
||||
|
||||
delete @sessions[path]
|
||||
@ace.setSession @newSession()
|
||||
|
||||
saveAs: ->
|
||||
if file = Chrome.savePanel()
|
||||
@filename = file
|
||||
@window.setTitle _.last @filename.split '/'
|
||||
if path = Native.savePanel()
|
||||
@activePath = path
|
||||
#@window.setTitle _.last @activePath.split '/'
|
||||
@save()
|
||||
|
||||
code: ->
|
||||
@@ -127,12 +97,6 @@ class Editor extends Extension
|
||||
regExp: true
|
||||
wrap: true
|
||||
|
||||
deleteSession: (path) ->
|
||||
if path is @filename
|
||||
@filename = null
|
||||
delete @sessions[path]
|
||||
@ace.setSession @newSession()
|
||||
|
||||
newSession: (code) ->
|
||||
doc = new EditSession code or ''
|
||||
doc.setUndoManager new UndoManager
|
||||
@@ -148,15 +112,21 @@ class Editor extends Extension
|
||||
match = /^( +)[^*]/im.exec code || @code()
|
||||
match?[1].length or 2
|
||||
|
||||
resize: (timeout=1) ->
|
||||
setTimeout =>
|
||||
@editor.ace.focus()
|
||||
@editor.ace.resize()
|
||||
, timeout
|
||||
|
||||
copy: ->
|
||||
editor = @ace
|
||||
text = editor.getSession().doc.getTextRange editor.getSelectionRange()
|
||||
Chrome.writeToPasteboard text
|
||||
Native.writeToPasteboard text
|
||||
|
||||
cut: ->
|
||||
editor = @ace
|
||||
text = editor.getSession().doc.getTextRange editor.getSelectionRange()
|
||||
Chrome.writeToPasteboard text
|
||||
Native.writeToPasteboard text
|
||||
editor.session.remove editor.getSelectionRange()
|
||||
|
||||
eval: ->
|
||||
24
src/event.coffee
Normal file
24
src/event.coffee
Normal file
@@ -0,0 +1,24 @@
|
||||
# Using the DOM event system, and copying the JQuery Event API
|
||||
# https://developer.mozilla.org/en/DOM/Creating_and_triggering_events
|
||||
|
||||
module.exports =
|
||||
class Event
|
||||
@events: {}
|
||||
|
||||
@on: (name, callback) ->
|
||||
window.document.addEventListener name, callback
|
||||
callback
|
||||
|
||||
@off: (name, callback) ->
|
||||
window.document.removeEventListener name, callback
|
||||
|
||||
@trigger: (name, data) ->
|
||||
event = @events[name]
|
||||
if not event
|
||||
event = window.document.createEvent "CustomEvent"
|
||||
event.initCustomEvent name, true, true, null
|
||||
@events[name] = event
|
||||
|
||||
event.details = data
|
||||
window.document.dispatchEvent event
|
||||
null
|
||||
@@ -9,11 +9,13 @@ module.exports =
|
||||
# Make the given path absolute by resolving it against the
|
||||
# current working directory.
|
||||
absolute: (path) ->
|
||||
path = OSX.NSString.stringWithString(path).stringByStandardizingPath.toString()
|
||||
return path if path[0] == "/"
|
||||
path = OSX.NSString.stringWithString(path).stringByStandardizingPath
|
||||
return path if path.toString()[0] == "/"
|
||||
|
||||
resolvedString = OSX.NSString.stringWithString(@workingDirectory)
|
||||
resolvedString.stringByAppendingPath(path).stringByStandardizingPath.toString()
|
||||
resolvedString = OSX.NSString.stringWithString(@workingDirectory())
|
||||
resolvedString = resolvedString.stringByAppendingPathComponent(path).stringByStandardizingPath
|
||||
|
||||
resolvedString.toString()
|
||||
|
||||
# Return the basename of the given path. That is the path with
|
||||
# any leading directory components removed. If specified, also
|
||||
@@ -28,12 +30,13 @@ module.exports =
|
||||
|
||||
# Returns true if the file specified by path exists
|
||||
exists: (path) ->
|
||||
exists = OSX.NSFileManager.defaultManager.
|
||||
fileExistsAtPath_isDirectory path, null
|
||||
console.log "exists"
|
||||
OSX.NSFileManager.defaultManager.fileExistsAtPath_isDirectory path, null
|
||||
|
||||
# Returns true if the file specified by path exists and is a
|
||||
# directory.
|
||||
isDirectory: (path) ->
|
||||
console.log "dir"
|
||||
isDir = new jscocoa.outArgument
|
||||
exists = OSX.NSFileManager.defaultManager.
|
||||
fileExistsAtPath_isDirectory path, isDir
|
||||
|
||||
34
src/native.coffee
Normal file
34
src/native.coffee
Normal file
@@ -0,0 +1,34 @@
|
||||
module.exports =
|
||||
class Native
|
||||
# path - Optional. The String path to the file to base it on.
|
||||
@newWindow: (path) ->
|
||||
controller = OSX.NSApp.createController
|
||||
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.toString()
|
||||
|
||||
@openURL: (url) ->
|
||||
window.location = url
|
||||
App = require 'app'
|
||||
App.activeWindow.setTitle _.last url.replace(/\/$/,'').split '/'
|
||||
|
||||
# Returns null or a file path.
|
||||
@savePanel: ->
|
||||
panel = OSX.NSSavePanel.savePanel
|
||||
if panel.runModal isnt OSX.NSFileHandlingPanelOKButton
|
||||
return null
|
||||
panel.filenames.lastObject
|
||||
|
||||
@writeToPasteboard: (text) ->
|
||||
pb = OSX.NSPasteboard.generalPasteboard
|
||||
pb.declareTypes_owner [OSX.NSStringPboardType], null
|
||||
pb.setString_forType text, OSX.NSStringPboardType
|
||||
39
src/pane.coffee
Normal file
39
src/pane.coffee
Normal file
@@ -0,0 +1,39 @@
|
||||
$ = require 'jquery'
|
||||
|
||||
module.exports =
|
||||
class Pane
|
||||
position: null
|
||||
|
||||
html: null
|
||||
|
||||
showing: false
|
||||
|
||||
add: ->
|
||||
verticalDiv = $('#app-vertical')
|
||||
horizontalDiv = $('#app-horizontal')
|
||||
|
||||
el = $ "<div>"
|
||||
el.addClass "pane " + @position
|
||||
el.append @html
|
||||
|
||||
switch @position
|
||||
when 'main'
|
||||
$('.main').replaceWith el
|
||||
when 'top'
|
||||
verticalDiv.prepend el
|
||||
when 'left'
|
||||
horizontalDiv.prepend el
|
||||
when 'bottom'
|
||||
verticalDiv.append el
|
||||
when 'right'
|
||||
horizontalDiv.append el
|
||||
else
|
||||
throw "I DON'T KNOW HOW TO DEAL WITH #{@position}"
|
||||
|
||||
toggle: ->
|
||||
if @showing
|
||||
@html.parent().detach()
|
||||
else
|
||||
@add this
|
||||
|
||||
@showing = not @showing
|
||||
@@ -34,7 +34,7 @@ class Watcher
|
||||
|
||||
switch notification.toString()
|
||||
when "UKKQueueFileRenamedNotification"
|
||||
raise "Doesn't handle this yet"
|
||||
throw "Doesn't handle this yet"
|
||||
when "UKKQueueFileDeletedNotification"
|
||||
@watchedPaths[path] = null
|
||||
@queue.removePathFromQueue path
|
||||
|
||||
@@ -1,16 +1,51 @@
|
||||
Editor = require 'editor'
|
||||
Event = require 'event'
|
||||
KeyBinder = require 'key-binder'
|
||||
Native = require 'native'
|
||||
|
||||
fs = require 'fs'
|
||||
|
||||
# This file is a weirdo. We don't create a Window class, we just add stuff to
|
||||
# the DOM window.
|
||||
windowAdditions =
|
||||
editor: null
|
||||
|
||||
extensions: []
|
||||
|
||||
appRoot: OSX.NSBundle.mainBundle.resourcePath
|
||||
|
||||
path: localStorage.lastOpenedPath ? fs.workingDirectory()
|
||||
|
||||
startup: ->
|
||||
KeyBinder.register "window", window
|
||||
|
||||
@path = localStorage.lastOpenedPath ? File.workingDirectory()
|
||||
@appPath = OSX.NSBundle.mainBundle.resourcePath
|
||||
@editor = new Editor()
|
||||
|
||||
@loadExtensions()
|
||||
|
||||
KeyBinder.load "#{@appRoot}/static/key-bindings.coffee"
|
||||
KeyBinder.load "~/.atomicity/key-bindings.coffee"
|
||||
|
||||
loadExtensions: ->
|
||||
extension.shutdown() for extension in @extensions
|
||||
@extensions = []
|
||||
|
||||
extensionPaths = fs.list(@appRoot + "/extensions")
|
||||
for extensionPath in extensionPaths when fs.isDirectory extensionPath
|
||||
try
|
||||
extension = require extensionPath
|
||||
extensions.push new Extension()
|
||||
catch error
|
||||
console.warn "window: Loading Extension #{fs.base extensionPath} failed."
|
||||
console.warn error
|
||||
|
||||
# After all the extensions are created, start them up.
|
||||
for extension in @extensions
|
||||
try
|
||||
extension.startup()
|
||||
catch error
|
||||
console.warn "window: Extension #{extension.constructor.name} failed to startup."
|
||||
console.warn error
|
||||
|
||||
handleKeyEvent: ->
|
||||
KeyBinder.handleEvent.apply KeyBinder, arguments
|
||||
@@ -18,6 +53,10 @@ windowAdditions =
|
||||
showConsole: ->
|
||||
atomController.webView.inspector.showConsole true
|
||||
|
||||
open: (path) ->
|
||||
path = Native.openPanel() if not path
|
||||
Event.trigger 'window:open', path if path
|
||||
|
||||
for key, value of windowAdditions
|
||||
raise "DOMWindow already has a key named #{key}" if window[key]
|
||||
console.warn "DOMWindow already has a key named `#{key}`" if window[key]
|
||||
window[key] = value
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
app:
|
||||
"cmd-q": (app) -> app.quit()
|
||||
"cmd-j": (app) -> console.log "OMG YOU TOUCHED THE LETTER J!"
|
||||
'cmd-q': (app) -> app.quit()
|
||||
'cmd-j': (app) -> console.log "OMG YOU TOUCHED THE LETTER J!"
|
||||
|
||||
window:
|
||||
"cmd-shift-i": (window) -> window.showConsole()
|
||||
'cmd-shift-i': (window) -> window.showConsole()
|
||||
'cmd-o': (window) -> window.open()
|
||||
|
||||
editor:
|
||||
'cmd-s': 'save'
|
||||
'cmd-shift-s': 'saveAs'
|
||||
'cmd-c': 'copy'
|
||||
'cmd-x': 'cut'
|
||||
'cmd-r': 'eval'
|
||||
'cmd-/': 'toggleComment'
|
||||
'cmd-[': 'outdent'
|
||||
'cmd-]': 'indent'
|
||||
'alt-f': 'forwardWord'
|
||||
'alt-b': 'backWord'
|
||||
'alt-d': 'deleteWord'
|
||||
'alt-shift-,': 'home'
|
||||
'alt-shift-.': 'end'
|
||||
'ctrl-l': 'consolelog'
|
||||
|
||||
Reference in New Issue
Block a user