diff --git a/Atom/Classes/AtomController.m b/Atom/Classes/AtomController.m index 03f2d3859..eab076161 100644 --- a/Atom/Classes/AtomController.m +++ b/Atom/Classes/AtomController.m @@ -1,9 +1,11 @@ #import "AtomController.h" #import "AtomApp.h" -#import #import "JSCocoa.h" +#import +#import + @implementation AtomController @synthesize webView, path, jscocoa; @@ -48,6 +50,16 @@ [super close]; } +- (NSString *)tempfile { + char *directory = "/tmp"; + char *prefix = "temp-file"; + char *tmpPath = tempnam(directory, prefix); + NSString *tmpPathString = [NSString stringWithUTF8String:tmpPath]; + free(tmpPath); + + return tmpPathString; +} + // WebUIDelegate Protocol - (NSArray *)webView:(WebView *)sender contextMenuItemsForElement:(NSDictionary *)element defaultMenuItems:(NSArray *)defaultMenuItems { return defaultMenuItems; diff --git a/extensions/tabs/tabs.coffee b/extensions/tabs/tabs.coffee index d5a020a4a..cc730e504 100644 --- a/extensions/tabs/tabs.coffee +++ b/extensions/tabs/tabs.coffee @@ -15,14 +15,16 @@ class Tabs extends Extension @pane = new TabsPane @ - Event.on 'window:open', (e) => + Event.on 'editor:bufferAdd', (e) => path = e.details return if fs.isDirectory path # Ignore directories @pane.addTab path - Event.on 'editor:close', (e) => + Event.on 'editor:bufferRemove', (e) => path = e.details @pane.removeTab path startup: -> - @pane.show() \ No newline at end of file + @pane.show() + for path, buffer of window.editor.buffers + @pane.addTab path diff --git a/extensions/tabs/tabsPane.coffee b/extensions/tabs/tabsPane.coffee index acf900d60..2e51b0487 100644 --- a/extensions/tabs/tabsPane.coffee +++ b/extensions/tabs/tabsPane.coffee @@ -21,10 +21,6 @@ class TabsPane extends Pane tabPane.switchToTab this false - closeActiveTab: -> - activeTab = $('#tabs ul .active') - window.editor.close activeTab.data 'path' - nextTab: -> @switchToTab $('#tabs ul .active').next() @@ -37,14 +33,14 @@ class TabsPane extends Pane $("#tabs ul .active").removeClass("active") $(tab).addClass 'active' - window.editor.open $(tab).data 'path' + window.editor.focusBuffer $(tab).data 'path' addTab: (path) -> existing = $("#tabs [data-path='#{path}']") if existing.length return @switchToTab existing - name = _.last path.split '/' + name = if path then _.last path.split '/' else "untitled" $("#tabs ul .active").removeClass() $("#tabs ul").append """
  • #{name}
  • diff --git a/src/editor.coffee b/src/editor.coffee index 5267e8b3e..303dd8971 100644 --- a/src/editor.coffee +++ b/src/editor.coffee @@ -13,7 +13,7 @@ module.exports = class Editor activePath: null - sessions: {} + buffers: {} constructor: (path) -> KeyBinder.register "editor", @ @@ -31,13 +31,11 @@ class Editor @ace.getSession().setTabSize 2 @ace.setShowInvisibles(true) @ace.setPrintMarginColumn 78 - @ace.setSession @newSession() - #@ace.getSession().on 'change', -> @window.setDirty true - Event.on 'window:open', (e) => @open e.details - Event.on 'window:close', (e) => @close e.details + Event.on 'window:open', (e) => @addBuffer e.details + Event.on 'window:close', (e) => @removeBuffer e.details - @open path + @addBuffer path modeMap: js: 'javascript' @@ -49,7 +47,10 @@ class Editor cs: 'csharp' rb: 'ruby' - modeForLanguage: (language) -> + modeForPath: (path) -> + return null if not path + + language = _.last path.split '.' language = language.toLowerCase() modeName = @modeMap[language] or language @@ -58,36 +59,40 @@ class Editor catch e null - setMode: -> - return unless @activePath - if mode = @modeForLanguage _.last @activePath.split '.' - @ace.getSession().setMode new mode + addBuffer: (path) -> + return if not path - open: (path) -> - return if fs.isDirectory path + throw "#{@constructor.name}: Cannot create buffer from a directory `#{path}`" if fs.isDirectory path - if not path - @activePath = null - @ace.setSession @newSession() - else - @activePath = path + buffer = @buffers[path] + if not buffer + code = if path then fs.read path else '' + buffer = new EditSession code + buffer.setUndoManager new UndoManager + buffer.setUseSoftTabs useSoftTabs = @usesSoftTabs code + buffer.setTabSize if useSoftTabs then @guessTabSize code else 8 - session = @sessions[path] - if not session - @sessions[path] = session = @newSession fs.read path - session.on 'change', -> session.$atom_dirty = true + mode = @modeForPath path + buffer.setMode new mode if mode - @ace.setSession session - @setMode() + @buffers[path] = buffer - Event.trigger "editor:open", path + buffer.on 'change', -> buffer.$atom_dirty = true + Event.trigger "editor:bufferAdd", path - close: (path) -> + @focusBuffer path + + removeBuffer: (path) -> path ?= @activePath - # ICK, clean this up... too many assumptions being made - session = @sessions[path] - if session?.$atom_dirty or (not session and @code.length > 0) + return if not path + + buffer = @buffers[path] + return if not buffer + + if buffer.$atom_dirty + # This should be thrown into it's own method, but I can't think of a good + # name. detailedMessage = if @activePath "#{@activePath} has changes." else @@ -96,19 +101,30 @@ class Editor canceled = Native.alert "Do you want to save the changes you made?", detailedMessage, "Save": => path = @save() - not path # if save fails/cancels, consider it canceled + not path # if save modal fails/cancels, consider it canceled "Cancel": => true "Don't Save": => false return if canceled - delete @sessions[path] + delete @buffers[path] + + Event.trigger "editor:bufferRemove", path if path is @activePath - @activePath = null - @ace.setSession @newSession() + newActivePath = Object.keys(@buffers)[0] + if newActivePath + @focusBuffer newActivePath + else + @ace.setSession new EditSession '' - Event.trigger "editor:close", path + focusBuffer: (path) -> + @activePath = path + + buffer = @buffers[path] or @addBuffer path + @ace.setSession buffer + + Event.trigger "editor:bufferFocus", path save: (path) -> path ?= @activePath @@ -117,8 +133,8 @@ class Editor @removeTrailingWhitespace() fs.write path, @code() - if @sessions[path] - @sessions[path].$atom_dirty = false + if @buffers[path] + @buffers[path].$atom_dirty = false path @@ -126,7 +142,7 @@ class Editor path = Native.savePanel()?.toString() if path @save path - @open path + @addBuffer path path @@ -140,13 +156,6 @@ class Editor regExp: true wrap: true - newSession: (code) -> - doc = new EditSession code or '' - doc.setUndoManager new UndoManager - doc.setUseSoftTabs useSoftTabs = @usesSoftTabs code - doc.setTabSize if useSoftTabs then @guessTabSize code else 8 - doc - usesSoftTabs: (code) -> not /^\t/m.test code or @code() @@ -170,17 +179,15 @@ class Editor Native.writeToPasteboard text @ace.session.remove @ace.getSelectionRange() - eval: -> - eval @code() - + eval: -> eval @code() toggleComment: -> @ace.toggleCommentLines() - outdent: -> @ace.blockOutdent() - indent: -> @ace.indent() - forwardWord: -> @ace.navigateWordRight() - backWord: -> @ace.navigateWordLeft() - deleteWord: -> @ace.removeWordRight() - home: -> @ace.navigateFileStart() - end: -> @ace.navigateFileEnd() + outdent: -> @ace.blockOutdent() + indent: -> @ace.indent() + forwardWord: -> @ace.navigateWordRight() + backWord: -> @ace.navigateWordLeft() + deleteWord: -> @ace.removeWordRight() + home: -> @ace.navigateFileStart() + end: -> @ace.navigateFileEnd() consolelog: -> @ace.insert 'console.log ""' diff --git a/src/key-binder.coffee b/src/key-binder.coffee index 040d617e5..aae77e7c4 100644 --- a/src/key-binder.coffee +++ b/src/key-binder.coffee @@ -60,8 +60,8 @@ class KeyBinder try _.last(callbacks)() catch e - console.warn "Failed to run binding #{binding}. #{e}" - + console.warn "Failed to run binding #{@bindingFromAscii binding}. #{e}" + true @bindingParser: (binding) -> @@ -85,17 +85,35 @@ class KeyBinder modifiers.concat(key).sort().join "-" + @bindingFromAscii: (binding) -> + inverseModifierKeys = {} + inverseModifierKeys[number] = label for label, number of @modifierKeys + + inverseNamedKeys = {} + inverseNamedKeys[number] = label for label, number of @namedKeys + + asciiKeys = binding.split '-' + keys = [] + + for asciiKey in asciiKeys + key = inverseModifierKeys[asciiKey] + key ?= inverseNamedKeys[asciiKey] + key ?= String.fromCharCode asciiKey + keys.push key or "?" + + keys.join '-' + @modifierKeys: '⇧': 16 + '⌘': 91 + '⌥': 18 shift: 16 alt: 18 option: 18 - '⌥': 18 control: 17 ctrl: 17 command: 91 cmd: 91 - '⌘': 91 @namedKeys: backspace: 8 diff --git a/src/window.coffee b/src/window.coffee index f3c9cae22..0be5317e2 100644 --- a/src/window.coffee +++ b/src/window.coffee @@ -31,14 +31,6 @@ windowAdditions = @loadExtensions() @loadKeyBindings() - Event.on "editor:open", (e) => - path = e.details - basename = fs.base path - @setTitle basename - - Event.on "editor:close", (e) => - @setTitle "untitled" - loadExtensions: -> extension.shutdown() for extension in @extensions @extensions = [] @@ -86,8 +78,9 @@ windowAdditions = if fs.isFile path Event.trigger 'window:open', path - close: -> + close: (path) -> atomController.close + Event.trigger 'window:close', path # Global methods that are used by the cocoa side of things handleKeyEvent: -> diff --git a/static/key-bindings.coffee b/static/key-bindings.coffee index 997c5d482..575297f25 100644 --- a/static/key-bindings.coffee +++ b/static/key-bindings.coffee @@ -7,7 +7,7 @@ window: 'cmd-r': (window) -> window.reload() editor: - 'cmd-w': 'close' + 'cmd-w': 'removeBuffer' 'cmd-s': 'save' 'cmd-shift-s': 'saveAs' 'cmd-c': 'copy'