Caret/js/tab.js
Thomas Wilburn 2e847cda88 Fixes #169
2014-03-22 06:05:47 -07:00

170 lines
No EOL
4.5 KiB
JavaScript

define([
"command",
"storage/file",
"util/manos",
"settings!ace,user",
"util/template!templates/tab.html"
], function(command, File, M, Settings, inflate) {
/*
Tabs are just augmented versions of regular Ace sessions. We add properties
to track the attached file, detect syntax, render the tab UI, and fire events
when the tab is removed.
*/
var EditSession = ace.require("ace/edit_session").EditSession;
var Tab = function(contents, file) {
contents = contents || "";
EditSession.call(this, contents, "ace/mode/text");
if (contents) {
this.setValue(contents);
}
if (file) {
this.setFile(file);
} else {
this.fileName = "untitled.txt";
}
this.modified = false;
this.setUndoManager(new ace.UndoManager());
var self = this;
this.on("change", function() {
if (self.modified) return;
self.modified = true;
command.fire("session:render");
});
this.animationClass = "enter";
};
//hopefully this never screws up unaugmented Ace sessions.
Tab.prototype = EditSession.prototype;
Tab.prototype.setFile = function(file) {
this.file = file;
this.fileName = file.entry.name;
this.modifiedAt = new Date();
var self = this;
if (!this.file.virtual) file.getPath().then(function(path) {
self.path = path;
command.fire("session:render");
})
}
Tab.prototype.save = function(as, c) {
if (typeof as == "function") {
c = as;
as = false;
}
//strip final whitespace, if enabled
if (Settings.get("user").trimTrailingWhitespace) {
command.fire("ace:trim-whitespace");
}
var content = this.getValue();
var self = this;
var deferred = M.deferred();
var whenOpen = function() {
self.file.write(content).then(function() {
self.modifiedAt = new Date();
self.modified = false;
command.fire("session:render");
deferred.done();
}, deferred.fail.bind(deferred));
};
if (!self.file || as) {
var file = new File();
file.open("save")
.then(function() {
self.file = file;
self.fileName = file.entry.name;
delete self.syntaxMode;
self.detectSyntax();
}, function(err) {
dialog(err);
deferred.fail();
})
.then(whenOpen);
} else {
whenOpen();
}
if (c) M.pton(deferred, c);
return deferred.promise();
};
Tab.prototype.drop = function() {
//let listeners know, like the project manager
this._emit("close");
if (!this.file || !chrome.fileSystem.retainEntry) return;
var id = this.file.retain();
if (!id) return;
chrome.storage.local.get("retained", function(data) {
if (!data.retained) return;
var filtered = data.retained.filter(function(item) { return item != id });
chrome.storage.local.set({ retained: filtered });
});
};
Tab.prototype.render = function(index) {
var element = inflate.get("templates/tab.html", {
index: index,
fileName: this.fileName,
modified: this.modified,
animation: this.animationClass,
path: this.path
});
this.animationClass = "";
return element;
}
Tab.prototype.detectSyntax = function(userConfig) {
//settings are async
var self = this;
Settings.pull("user").then(function(data) {
var userConfig = data.user;
self.setUseSoftTabs(!userConfig.useTabs);
self.setTabSize(userConfig.indentation || 2);
self.setUseWrapMode(userConfig.wordWrap);
self.setWrapLimit(userConfig.wrapLimit || null);
self.setNewLineMode(userConfig.lineEnding || "auto");
self.setUseWorker(userConfig.useWorker);
});
//syntax, however, is sync
var syntaxValue = this.syntaxMode || "plain_text";
if (this.file) {
if (this.file.virtual) {
//settings files are special
syntaxValue = "javascript";
this.setMode("ace/mode/javascript");
} else if (this.file.entry) {
var extension = this.file.entry.name.split(".").pop();
//this won't ever change, safe to get each time
var aceConfig = Settings.get("ace");
for (var i = 0; i < aceConfig.modes.length; i++) {
var mode = aceConfig.modes[i];
if (mode.extensions.indexOf(extension) > -1) {
syntaxValue = mode.name;
break;
}
}
}
}
this.setMode("ace/mode/" + syntaxValue);
this.syntaxMode = syntaxValue;
return syntaxValue;
}
return Tab;
});