Merge branch 'master' of github.com:github/atom

This commit is contained in:
Nathan Sobo
2012-06-12 15:21:06 -06:00
10 changed files with 138 additions and 18 deletions

View File

@@ -85,7 +85,19 @@
- (bool)keyEventOfType:(cef_handler_keyevent_type_t)type code:(int)code modifiers:(int)modifiers isSystemKey:(bool)isSystemKey isAfterJavaScript:(bool)isAfterJavaScript {
if (isAfterJavaScript && type == KEYEVENT_RAWKEYDOWN && modifiers == KEY_META && code == 'R') {
_clientHandler->GetBrowser()->ReloadIgnoreCache();
CefRefPtr<CefV8Context> context = _clientHandler->GetBrowser()->GetMainFrame()->GetV8Context();
CefRefPtr<CefV8Value> global = context->GetGlobal();
context->Enter();
CefRefPtr<CefV8Value> retval;
CefRefPtr<CefV8Exception> exception;
CefV8ValueList arguments;
global->GetValue("reload")->ExecuteFunction(global, arguments, retval, exception, true);
if (exception) _clientHandler->GetBrowser()->ReloadIgnoreCache();
context->Exit();
return YES;
}

View File

@@ -16,7 +16,7 @@ NSString *stringFromCefV8Value(const CefRefPtr<CefV8Value>& value) {
NativeHandler::NativeHandler() : CefV8Handler() {
std::string extensionCode = "var $native = {}; (function() {";
const char *functionNames[] = {"exists", "alert", "read", "write", "absolute", "list", "isFile", "isDirectory", "remove", "asyncList", "open", "openDialog", "quit", "writeToPasteboard", "readFromPasteboard", "showDevTools", "newWindow", "saveDialog", "exit", "watchPath", "unwatchPath", "makeDirectory", "move", "moveToTrash"};
const char *functionNames[] = {"exists", "alert", "read", "write", "absolute", "list", "isFile", "isDirectory", "remove", "asyncList", "open", "openDialog", "quit", "writeToPasteboard", "readFromPasteboard", "showDevTools", "newWindow", "saveDialog", "exit", "watchPath", "unwatchPath", "makeDirectory", "move", "moveToTrash", "reload"};
NSUInteger arrayLength = sizeof(functionNames) / sizeof(const char *);
for (NSUInteger i = 0; i < arrayLength; i++) {
std::string functionName = std::string(functionNames[i]);
@@ -375,5 +375,8 @@ bool NativeHandler::Execute(const CefString& name,
return true;
}
else if (name == "reload") {
CefV8Context::GetCurrentContext()->GetBrowser()->ReloadIgnoreCache();
}
return false;
};

View File

@@ -31,6 +31,43 @@ describe 'Buffer', ->
buffer = new Buffer
expect(buffer.getText()).toBe ""
describe "path-change event", ->
it "emits path-change event when path is changed", ->
eventHandler = jasmine.createSpy('eventHandler')
buffer.on 'path-change', eventHandler
buffer.setPath("moo.text")
expect(eventHandler).toHaveBeenCalledWith(buffer)
describe ".isModified()", ->
describe "when deserialized", ->
it "returns false", ->
buffer = Buffer.deserialize(buffer.serialize(), new Project)
expect(buffer.isModified()).toBe false
buffer = Buffer.deserialize((new Buffer).serialize(), new Project)
expect(buffer.isModified()).toBe false
it "returns is true if buffer no path and had changes", ->
buffer = new Buffer
buffer.insert([0,0], "oh hi")
expect(buffer.isModified()).toBe true
it "returns true when user changes buffer", ->
expect(buffer.isModified()).toBeFalsy()
buffer.insert([0,0], "hi")
expect(buffer.isModified()).toBe true
it "returns false after modified buffer is saved", ->
filePath = "/tmp/atom-tmp-file"
buffer = new Buffer(filePath)
expect(buffer.isModified()).toBe false
buffer.insert([0,0], "hi")
expect(buffer.isModified()).toBe true
buffer.save()
expect(buffer.isModified()).toBe false
describe '.deserialize(state, project)', ->
project = null
@@ -365,7 +402,7 @@ describe 'Buffer', ->
expect(ranges.length).toBe 2
describe "backwardsScanInRange(range, regex, fn)", ->
describe ".backwardsScanInRange(range, regex, fn)", ->
describe "when given a regex with no global flag", ->
it "calls the iterator with the last match for the given regex in the given range", ->
matches = []
@@ -446,11 +483,3 @@ describe 'Buffer', ->
expect(buffer.positionForCharacterIndex(30)).toEqual [1, 0]
expect(buffer.positionForCharacterIndex(61)).toEqual [2, 0]
expect(buffer.positionForCharacterIndex(408)).toEqual [12, 2]
describe "path-change event", ->
it "emits path-change event when path is changed", ->
eventHandler = jasmine.createSpy('eventHandler')
buffer.on 'path-change', eventHandler
buffer.setPath("moo.text")
expect(eventHandler).toHaveBeenCalledWith(buffer)

View File

@@ -1456,6 +1456,7 @@ describe "Editor", ->
expect(editor.buffer).toBe buffer
it "calls remove on the editor if there is one edit session and mini is false", ->
originalBuffer = editor.buffer
expect(editor.mini).toBeFalsy()
expect(editor.editSessions.length).toBe 1
spyOn(editor, 'remove')
@@ -1467,3 +1468,12 @@ describe "Editor", ->
spyOn(editor, 'remove')
editor.trigger 'close'
expect(editor.remove).not.toHaveBeenCalled()
describe "when buffer is modified", ->
it "triggers alert and does not close session", ->
spyOn(editor, 'remove')
spyOn($native, 'alert')
editor.insertText("I AM CHANGED!")
editor.trigger "close"
expect(editor.remove).not.toHaveBeenCalled()
expect($native.alert).toHaveBeenCalled()

View File

@@ -17,6 +17,20 @@ describe "Window", ->
$(window).trigger 'close'
expect(window.close).toHaveBeenCalled()
describe ".reload()", ->
it "returns false when no buffers are modified", ->
spyOn($native, "reload")
window.reload()
expect($native.reload).toHaveBeenCalled()
it "shows alert when a modifed buffer exists", ->
rootView.activeEditor().insertText("hi")
spyOn($native, "alert")
spyOn($native, "reload")
window.reload()
expect($native.reload).not.toHaveBeenCalled()
expect($native.alert).toHaveBeenCalled()
describe "requireStylesheet(path)", ->
it "synchronously loads the stylesheet at the given path and installs a style tag for it in the head", ->
$('head style[path*="atom.css"]').remove()

View File

@@ -8,16 +8,19 @@ UndoManager = require 'undo-manager'
module.exports =
class Buffer
@idCounter = 1
modified: null
lines: null
path: null
@deserialize: (state, project) ->
if state.path
project.open(state.path)
buffer = project.open(state.path)
else
buffer = project.bufferWithId(state.id) ? project.open()
buffer.setText(state.text)
buffer
buffer.modified = state.modified
buffer
constructor: (path) ->
@id = @constructor.idCounter++
@@ -28,12 +31,13 @@ class Buffer
else
@setText('')
@undoManager = new UndoManager(this)
@modified = false
serialize: ->
if @getPath()
{ path: @path }
else
{ text: @getText(), id: @id }
{ text: @getText(), id: @id , modified: @modified}
getPath: ->
@path
@@ -139,6 +143,8 @@ class Buffer
newTextLines[lastLineIndex] += suffix
@lines[oldRange.start.row..oldRange.end.row] = newTextLines
@modified = true
@trigger 'change', { oldRange, newRange, oldText, newText }
newRange
@@ -155,15 +161,19 @@ class Buffer
@undoManager.redo()
save: ->
if not @getPath() then throw new Error("Tried to save buffer with no file path")
if not @getPath() then throw new Error("Can't save buffer with no file path")
@trigger 'before-save'
fs.write @getPath(), @getText()
@modified = false
@trigger 'after-save'
saveAs: (path) ->
@setPath(path)
@save()
isModified: ->
@modified
getMode: ->
return @mode if @mode
extension = if @getPath() then @getPath().split('/').pop().split('.').pop() else null

View File

@@ -7,6 +7,8 @@ Range = require 'range'
EditSession = require 'edit-session'
CursorView = require 'cursor-view'
SelectionView = require 'selection-view'
Native = require 'native'
fs = require 'fs'
$ = require 'jquery'
_ = require 'underscore'
@@ -604,12 +606,14 @@ class Editor extends View
save: ->
if not @buffer.getPath()
path = $native.saveDialog()
return if not path
path = Native.saveDialog()
return false if not path
@buffer.saveAs(path)
else
@buffer.save()
true
clipScreenPosition: (screenPosition, options={}) ->
@renderer.clipScreenPosition(screenPosition, options)
@@ -778,7 +782,19 @@ class Editor extends View
close: ->
return if @mini
@removeActiveEditSession()
if @buffer.isModified()
filename = if @buffer.getPath() then fs.base(@buffer.getPath()) else "untitled buffer"
message = "'#{filename}' has changes, do you want to save them?"
detailedMessage = "Your changes will be lost if you don't save them"
buttons = [
["Save", => @save() and @removeActiveEditSession()]
["Cancel", =>]
["Don't save", => @removeActiveEditSession()]
]
Native.alert message, detailedMessage, buttons
else
@removeActiveEditSession()
unsubscribeFromBuffer: ->
@buffer.off ".editor#{@id}"

View File

@@ -123,6 +123,14 @@ class RootView extends View
editors: ->
@panes.find('.editor').map -> $(this).view()
modifiedBuffers: ->
modifiedBuffers = []
for editor in @editors()
for session in editor.editSessions
modifiedBuffers.push session.buffer if session.buffer.isModified()
modifiedBuffers
activeEditor: ->
if (editor = @panes.find('.editor.active')).length
editor.view()

View File

@@ -1,6 +1,7 @@
# This a weirdo file. We don't create a Window class, we just add stuff to
# the DOM window.
Native = require 'native'
fs = require 'fs'
_ = require 'underscore'
$ = require 'jquery'
@@ -60,6 +61,19 @@ windowAdditions =
return if $("head style[path='#{fullPath}']").length
$('head').append "<style path='#{fullPath}'>#{content}</style>"
reload: ->
if rootView.modifiedBuffers().length > 0
message = "There are unsaved buffers, reload anyway?"
detailedMessage = "You will lose all unsaved changes if you reload"
buttons = [
["Reload", -> Native.reload()]
["Cancel", ->]
]
Native.alert(message, detailedMessage, buttons)
else
Native.reload()
showConsole: ->
$native.showDevTools()

View File

@@ -2,4 +2,8 @@ module.exports =
class Native
@alert: (args...) -> $native.alert(args...)
@saveDialog: (args...) -> $native.saveDialog(args...)
@reload: -> $native.reload()
@moveToTrash: (args...) -> $native.moveToTrash(args...)