c9-core/plugins/c9.ide.scm/diff.split.js

365 wiersze
14 KiB
JavaScript

define(function(require, exports, module) {
main.consumes = [
"editors", "Editor", "ui", "scm", "layout", "settings",
"threewaymerge", "menus", "Menu", "MenuItem", "Divider", "ace"
];
main.provides = ["diff.split"];
return main;
function main(options, imports, register) {
var settings = imports.settings;
var editors = imports.editors;
var Editor = imports.Editor;
var scm = imports.scm;
var layout = imports.layout;
var MenuItem = imports.MenuItem;
var Divider = imports.Divider;
var merge = imports.threewaymerge;
var Menu = imports.Menu;
var ace = imports.ace;
var ui = imports.ui;
var dirname = require("path").dirname;
var basename = require("path").basename;
var DiffView = require("./diff/twoway").DiffView;
/***** Initialization *****/
var extensions = [];
// :(
var BGCOLOR = {
"flat-light": "#F1F1F1",
"flat-dark": "#3D3D3D",
"light": "#D3D3D3",
"light-gray": "#D3D3D3",
"dark": "#3D3D3D",
"dark-gray": "#3D3D3D"
};
var menuAce;
var menuGutter;
var handle = editors.register("diff.split", "Compare", DiffViewer, extensions);
function createMenu() {
menuAce = new Menu({
id: "menu",
items: [
new MenuItem({ position: 10, command: "cut", caption: "Cut" }, handle),
new MenuItem({ position: 20, command: "copy", caption: "Copy" }, handle),
new MenuItem({ position: 30, command: "paste", caption: "Paste" }, handle),
new Divider({ position: 40 }, handle),
new MenuItem({ position: 50, command: "selectall", caption: "Select All" }, handle),
new Divider({ position: 60 }, handle)
]
}, handle);
menuGutter = new Menu({
id: "menu-gutter",
items: [
]
}, handle);
}
function DiffViewer() {
// TODO it is too difficult to hook into initialization flow of ace plugin
// so we have to copy paste bunch of code here :(
// var Baseclass = editors.findEditor("ace");
// var plugin = new Baseclass(true, []);
var plugin = new Editor(true, []);
var emit = plugin.getEmitter();
var currentSession;
var diffview;
var lastAce;
var lblLeft, lblRight, btnNext, btnPrev, btnFold, container;
var toolbar;
plugin.on("draw", function(e) {
var tab = e.tab;
lblLeft = new ui.label({ flex: 1 });
lblRight = new ui.label({ flex: 1, class: "right" });
btnNext = new ui.button({
caption: ">",
height: 24,
skin: "c9-toolbarbutton-glossy",
onclick: function() {
diffview.gotoNext(1);
}
});
btnPrev = new ui.button({
caption: "<",
height: 24,
skin: "c9-toolbarbutton-glossy",
onclick: function() {
diffview.gotoNext(-1);
}
});
btnFold = new ui.button({
caption: "Fold",
height: 24,
skin: "c9-toolbarbutton-glossy",
onclick: function() {
if (diffview.orig.session.$foldData.length)
diffview.orig.session.unfold();
else
diffview.foldUnchanged();
}
});
container = new ui.bar({ flex: 1, class: "ace_diff-container" });
tab.appendChild(new ui.vsplitbox({
anchors: "0 0 0 0",
childNodes: [
toolbar = new ui.hbox({
class: "difftoolbar",
height: 36,
align: "center",
edge: "0 5 0 3",
padding: 3,
childNodes: [
lblLeft,
new ui.hbox({
padding: 3,
edge: 3,
margin: "0 7 0 7",
align: "center",
class: "buttons",
childNodes: [ btnPrev, btnFold, btnNext ]
}),
lblRight
]
}),
container
]
}));
diffview = new DiffView(container.$ext, {});
// temporary workaround for apf focus bugs
// only blur is needed sinse the rest is handled by tabManager
// todo remove this when there is proper focus manager
tab.$blur = function(e) {
var ace = plugin.ace; // can be null when called for destroyed tab
if (!ace || !e || !e.toElement || e.toElement.tagName == "menu")
return;
if (!ace.isFocused())
ace.renderer.visualizeBlur();
else
ace.textInput.blur();
};
function focusApf() {
var page = apf.findHost(diffview.container.parentElement.parentElement);
if (apf.activeElement != page)
page.focus();
}
function updateLastAce(e, ace) { lastAce = ace; }
diffview.edit.on("focus", focusApf);
diffview.orig.on("focus", focusApf);
diffview.edit.keyBinding.setDefaultHandler(null);
diffview.orig.keyBinding.setDefaultHandler(null);
diffview.edit.on("focus", updateLastAce);
diffview.orig.on("focus", updateLastAce);
lastAce = diffview.edit;
// createProgressIndicator(e.htmlNode);
tab.on("contextmenu", function(e) {
if (!menuAce) createMenu();
var target = e.htmlEvent.target;
var gutter = plugin.diffview.gutterEl;
// Set Gutter Context Menu
if (ui.isChildOf(gutter, target, true)) {
menuGutter.show(e.x, e.y);
}
// Set main Ace Context Menu
else {
menuAce.show(e.x, e.y);
}
return false;
});
});
/***** Method *****/
function getLabelValue(path) {
var hash;
if (path.indexOf(":") > -1) {
hash = path.split(":");
path = hash[1], hash = hash[0];
}
var dirpath = dirname(path);
return (hash ? "<span class='hash'>" + hash + "</span>" : "")
+ basename(dirpath) + "/" + basename(path)
+ "<span class='dirname'> - " + dirname(dirpath) + "</span>";
}
function loadSession(session) {
if (session.diffSession) {
diffview.setSession(session.diffSession);
return;
}
diffview.setSession(session.diffSession = {
orig: diffview.createSession(),
edit: diffview.createSession(),
chunks: []
});
var diff = session.diff || {};
if (typeof diff.patch == "string") {
diffview.setValueFromFullPatch(diff.patch);
} else {
diffview.orig.session.setValue(diff.orig || "");
diffview.edit.session.setValue(diff.edit || "");
}
diffview.orig.setReadOnly(true);
diffview.edit.setReadOnly(true);
var syntax = ace.getSyntaxForPath(session.newPath);
if (syntax && syntax.indexOf("/") == -1) syntax = "ace/mode/" + syntax;
if (syntax) {
diffview.orig.session.setMode(syntax);
diffview.edit.session.setMode(syntax);
}
diffview.orig.renderer.once("afterRender", function() {
if (diffview.session == session.diffSession) {
if (!diffview.chunks.length)
diffview.computeDiff();
diffview.foldUnchanged();
diffview.gotoNext(1);
}
});
}
/***** Lifecycle *****/
plugin.on("load", function() {
});
plugin.on("documentLoad", function(e) {
var doc = e.doc;
var session = e.doc.getSession();
if (e.state.oldPath)
session.oldPath = e.state.oldPath;
if (e.state.newPath)
session.newPath = e.state.newPath;
doc.title = "Compare Files...";
diffview.c9session = session;
diffview.orig.session.c9session = session;
diffview.edit.session.c9session = session;
function setTheme(e) {
var tab = doc.tab;
if (e.theme && BGCOLOR[e.theme]) {
var isDark = e.theme == "dark";
toolbar.$ext.style.backgroundColor =
tab.backgroundColor = BGCOLOR[e.theme];
if (isDark) tab.classList.add("dark");
else tab.classList.remove("dark");
}
diffview.setTheme(settings.get("user/ace/@theme"));
}
layout.on("themeChange", setTheme, doc);
settings.on("user/ace/@theme", setTheme, doc);
setTheme({ theme: settings.get("user/general/@skin") });
});
plugin.on("documentActivate", function(e) {
var session = currentSession = e.doc.getSession();
if (!session.newPath) return;
var newFilename = (session.newPath + "").split("/").pop();
e.doc.title = "Compare " + newFilename;
lblLeft.setAttribute("caption", getLabelValue(session.oldPath));
lblRight.setAttribute("caption", getLabelValue(session.newPath));
if (session.diff)
return loadSession(session);
var newPath = session.newPath
.replace(/MODIFIED:/, "")
.replace(/STAGED:/, ":");
var oldPath = session.oldPath
.replace(/PREVIOUS:/, ":");
session.request = scm.loadDiff({
oldPath: oldPath,
newPath: newPath
}, function(err, diff) {
if (err)
diff;
if (session.request == diff.request) {
session.diff = diff;
loadSession(session);
}
});
});
plugin.on("documentUnload", function(e) {
// var session = e.doc.getSession();
});
plugin.on("getState", function(e) {
var session = e.doc.getSession();
e.state.oldPath = session.oldPath;
e.state.newPath = session.newPath;
});
plugin.on("setState", function(e) {
var session = e.doc.getSession();
session.oldPath = e.state.oldPath;
session.newPath = e.state.newPath;
});
plugin.on("clear", function() {
});
plugin.on("focus", function() {
});
plugin.on("enable", function() {
});
plugin.on("disable", function() {
});
plugin.on("unload", function() {
});
plugin.on("resize", function(e) {
diffview && diffview.resize(e);
});
/***** Register and define API *****/
/**
* Read Only Image Editor
**/
plugin.freezePublicAPI({
get diffview() { return diffview; },
get ace () { return lastAce; }
});
plugin.load(null, "ace.repl");
return plugin;
}
register(null, {
"diff.split": handle
});
}
});