mirror of
https://github.com/atom/atom.git
synced 2026-01-23 05:48:10 -05:00
editor is more editorish
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
#import "AtomController.h"
|
||||
#import "AtomApp.h"
|
||||
|
||||
#import <WebKit/WebKit.h>
|
||||
#import "JSCocoa.h"
|
||||
|
||||
#import <WebKit/WebKit.h>
|
||||
#import <stdio.h>
|
||||
|
||||
@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;
|
||||
|
||||
@@ -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()
|
||||
@pane.show()
|
||||
for path, buffer of window.editor.buffers
|
||||
@pane.addTab path
|
||||
|
||||
@@ -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 """
|
||||
<li data-path='#{path}'><a href='#'>#{name}</a></li>
|
||||
|
||||
@@ -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 ""'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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: ->
|
||||
|
||||
@@ -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'
|
||||
|
||||
Reference in New Issue
Block a user