2014-09-25 05:46:24 +04:00
|
|
|
|
var editors = {
|
|
|
|
|
data: [],
|
|
|
|
|
tabs: {},
|
|
|
|
|
init: function () {
|
|
|
|
|
editors._initAutocomplete();
|
|
|
|
|
editors.tabs = new Tabs({
|
|
|
|
|
id: ".edit-panel",
|
|
|
|
|
clickAfter: function (id) {
|
|
|
|
|
// set tree node selected
|
|
|
|
|
var node = tree.fileTree.getNodeByTId(id);
|
|
|
|
|
tree.fileTree.selectNode(node);
|
|
|
|
|
wide.curNode = node;
|
|
|
|
|
|
|
|
|
|
for (var i = 0, ii = editors.data.length; i < ii; i++) {
|
|
|
|
|
if (editors.data[i].id === id) {
|
|
|
|
|
wide.curEditor = editors.data[i].editor;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wide.curEditor.focus();
|
|
|
|
|
},
|
|
|
|
|
removeAfter: function (id, nextId) {
|
|
|
|
|
for (var i = 0, ii = editors.data.length; i < ii; i++) {
|
|
|
|
|
if (editors.data[i].id === id) {
|
|
|
|
|
editors.data.splice(i, 1);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!nextId) {
|
|
|
|
|
// 不存在打开的编辑器
|
|
|
|
|
// remove selected tree node
|
|
|
|
|
tree.fileTree.cancelSelectedNode();
|
|
|
|
|
wide.curNode = undefined;
|
|
|
|
|
|
|
|
|
|
wide.curEditor = undefined;
|
|
|
|
|
$(".toolbars").hide();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nextId === editors.tabs.getCurrentId()) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// set tree node selected
|
|
|
|
|
var node = tree.fileTree.getNodeByTId(nextId);
|
|
|
|
|
tree.fileTree.selectNode(node);
|
|
|
|
|
wide.curNode = node;
|
|
|
|
|
|
|
|
|
|
for (var i = 0, ii = editors.data.length; i < ii; i++) {
|
|
|
|
|
if (editors.data[i].id === nextId) {
|
|
|
|
|
wide.curEditor = editors.data[i].editor;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
2014-09-26 11:39:13 +04:00
|
|
|
|
$(".edit-panel .tabs").on("dblclick", function () {
|
|
|
|
|
if ($(".toolbars .ico-max").length === 1) {
|
|
|
|
|
windows.maxEditor();
|
|
|
|
|
} else {
|
|
|
|
|
windows.restoreEditor();
|
|
|
|
|
}
|
2014-09-25 05:46:24 +04:00
|
|
|
|
});
|
|
|
|
|
},
|
2014-09-26 11:39:13 +04:00
|
|
|
|
getCurrentId: function () {
|
|
|
|
|
return $(".edit-panel .tabs .current").data("index");
|
|
|
|
|
},
|
|
|
|
|
getCurrentPath: function () {
|
|
|
|
|
return $(".edit-panel .tabs .current span:eq(0)").attr("title");
|
2014-09-25 05:46:24 +04:00
|
|
|
|
},
|
|
|
|
|
_initAutocomplete: function () {
|
|
|
|
|
CodeMirror.registerHelper("hint", "go", function (editor) {
|
|
|
|
|
var word = /[\w$]+/;
|
|
|
|
|
|
|
|
|
|
var cur = editor.getCursor(), curLine = editor.getLine(cur.line);
|
|
|
|
|
|
|
|
|
|
var start = cur.ch, end = start;
|
|
|
|
|
while (end < curLine.length && word.test(curLine.charAt(end))) {
|
|
|
|
|
++end;
|
|
|
|
|
}
|
|
|
|
|
while (start && word.test(curLine.charAt(start - 1))) {
|
|
|
|
|
--start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var request = newWideRequest();
|
2014-09-25 12:40:05 +04:00
|
|
|
|
request.path = $(".edit-panel .tabs .current > span:eq(0)").attr("title");
|
2014-09-25 05:46:24 +04:00
|
|
|
|
request.code = editor.getValue();
|
|
|
|
|
request.cursorLine = cur.line;
|
|
|
|
|
request.cursorCh = cur.ch;
|
|
|
|
|
|
|
|
|
|
var autocompleteHints = [];
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
async: false, // 同步执行
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: '/autocomplete',
|
|
|
|
|
data: JSON.stringify(request),
|
|
|
|
|
dataType: "json",
|
|
|
|
|
success: function (data) {
|
|
|
|
|
var autocompleteArray = data[1];
|
|
|
|
|
|
|
|
|
|
if (autocompleteArray) {
|
|
|
|
|
for (var i = 0; i < autocompleteArray.length; i++) {
|
2014-10-09 19:04:02 +04:00
|
|
|
|
var displayText = '';
|
2014-10-10 07:18:52 +04:00
|
|
|
|
|
2014-10-10 14:04:03 +04:00
|
|
|
|
// TODO: 图标
|
2014-10-10 07:18:52 +04:00
|
|
|
|
switch (autocompleteArray[i].class) {
|
|
|
|
|
case "type":
|
|
|
|
|
case "const":
|
|
|
|
|
case "var":
|
|
|
|
|
case "package":
|
|
|
|
|
displayText = '<span class="fn-clear">'// + autocompleteArray[i].class
|
|
|
|
|
+ '<b class="fn-left">' + autocompleteArray[i].name + '</b> '
|
|
|
|
|
+ autocompleteArray[i].type + '</span>';
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
case "func":
|
|
|
|
|
displayText = '<span>'// + autocompleteArray[i].class
|
|
|
|
|
+ '<b>' + autocompleteArray[i].name + '</b>'
|
|
|
|
|
+ autocompleteArray[i].type.substring(4) + '</span>';
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
console.warn("Can't handle autocomplete [" + autocompleteArray[i].class + "]");
|
2014-10-10 14:04:03 +04:00
|
|
|
|
|
2014-10-10 07:18:52 +04:00
|
|
|
|
break;
|
2014-10-09 19:04:02 +04:00
|
|
|
|
}
|
2014-10-10 07:18:52 +04:00
|
|
|
|
|
2014-10-09 13:14:15 +04:00
|
|
|
|
autocompleteHints[i] = {
|
2014-10-09 19:04:02 +04:00
|
|
|
|
displayText: displayText,
|
2014-10-09 13:14:15 +04:00
|
|
|
|
text: autocompleteArray[i].name
|
|
|
|
|
};
|
2014-09-25 05:46:24 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return {list: autocompleteHints, from: CodeMirror.Pos(cur.line, start), to: CodeMirror.Pos(cur.line, end)};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
CodeMirror.commands.autocompleteAfterDot = function (cm) {
|
|
|
|
|
setTimeout(function () {
|
|
|
|
|
if (!cm.state.completionActive) {
|
|
|
|
|
cm.showHint({hint: CodeMirror.hint.go, completeSingle: false});
|
|
|
|
|
}
|
|
|
|
|
}, 50);
|
|
|
|
|
|
|
|
|
|
return CodeMirror.Pass;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CodeMirror.commands.autocompleteAnyWord = function (cm) {
|
|
|
|
|
cm.showHint({hint: CodeMirror.hint.auto});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CodeMirror.commands.gotoLine = function (cm) {
|
|
|
|
|
$("#dialogGoLinePrompt").dialog("open");
|
|
|
|
|
};
|
|
|
|
|
|
2014-10-10 07:27:17 +04:00
|
|
|
|
// 用于覆盖 cm 默认绑定的某些快捷键功能.
|
2014-09-25 05:46:24 +04:00
|
|
|
|
CodeMirror.commands.doNothing = function (cm) {
|
|
|
|
|
};
|
2014-10-10 14:04:03 +04:00
|
|
|
|
|
2014-10-10 07:18:52 +04:00
|
|
|
|
CodeMirror.commands.exprInfo = function (cm) {
|
|
|
|
|
var cur = wide.curEditor.getCursor();
|
|
|
|
|
|
|
|
|
|
var request = newWideRequest();
|
|
|
|
|
request.path = $(".edit-panel .tabs .current > span:eq(0)").attr("title");
|
|
|
|
|
request.code = wide.curEditor.getValue();
|
|
|
|
|
request.cursorLine = cur.line;
|
|
|
|
|
request.cursorCh = cur.ch;
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: '/exprinfo',
|
|
|
|
|
data: JSON.stringify(request),
|
|
|
|
|
dataType: "json",
|
|
|
|
|
success: function (data) {
|
|
|
|
|
if (!data.succ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2014-10-10 14:04:03 +04:00
|
|
|
|
var position = wide.curEditor.cursorCoords();
|
|
|
|
|
$("body").append('<div style="top:'
|
|
|
|
|
+ (position.top + 15) + 'px;left:' + position.left
|
|
|
|
|
+ 'px" class="edit-exprinfo">' + data.info + '</div>');
|
2014-10-10 07:18:52 +04:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
2014-09-25 05:46:24 +04:00
|
|
|
|
|
|
|
|
|
CodeMirror.commands.jumpToDecl = function (cm) {
|
|
|
|
|
var cur = wide.curEditor.getCursor();
|
|
|
|
|
|
|
|
|
|
var request = newWideRequest();
|
2014-09-25 12:40:05 +04:00
|
|
|
|
request.path = $(".edit-panel .tabs .current > span:eq(0)").attr("title");
|
2014-09-25 05:46:24 +04:00
|
|
|
|
request.code = wide.curEditor.getValue();
|
|
|
|
|
request.cursorLine = cur.line;
|
|
|
|
|
request.cursorCh = cur.ch;
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: '/find/decl',
|
|
|
|
|
data: JSON.stringify(request),
|
|
|
|
|
dataType: "json",
|
|
|
|
|
success: function (data) {
|
|
|
|
|
if (!data.succ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var cursorLine = data.cursorLine;
|
|
|
|
|
var cursorCh = data.cursorCh;
|
|
|
|
|
|
|
|
|
|
var request = newWideRequest();
|
|
|
|
|
request.path = data.path;
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: '/file',
|
|
|
|
|
data: JSON.stringify(request),
|
|
|
|
|
dataType: "json",
|
|
|
|
|
success: function (data) {
|
|
|
|
|
if (!data.succ) {
|
|
|
|
|
$("#dialogAlert").dialog("open", data.msg);
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var tId = tree.getTIdByPath(data.path);
|
|
|
|
|
wide.curNode = tree.fileTree.getNodeByTId(tId);
|
|
|
|
|
tree.fileTree.selectNode(wide.curNode);
|
|
|
|
|
|
|
|
|
|
data.cursorLine = cursorLine;
|
|
|
|
|
data.cursorCh = cursorCh;
|
|
|
|
|
editors.newEditor(data);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
CodeMirror.commands.findUsages = function (cm) {
|
|
|
|
|
var cur = wide.curEditor.getCursor();
|
|
|
|
|
|
|
|
|
|
var request = newWideRequest();
|
2014-10-10 07:18:52 +04:00
|
|
|
|
request.path = $(".edit-panel .tabs .current > span:eq(0)").attr("title");
|
2014-09-25 05:46:24 +04:00
|
|
|
|
request.code = wide.curEditor.getValue();
|
|
|
|
|
request.cursorLine = cur.line;
|
|
|
|
|
request.cursorCh = cur.ch;
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
type: 'POST',
|
|
|
|
|
url: '/find/usages',
|
|
|
|
|
data: JSON.stringify(request),
|
|
|
|
|
dataType: "json",
|
|
|
|
|
success: function (data) {
|
|
|
|
|
if (!data.succ) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-12 18:00:26 +04:00
|
|
|
|
editors.appendSearch(data.founds, 'usages', '');
|
2014-09-25 05:46:24 +04:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
},
|
2014-10-12 18:00:26 +04:00
|
|
|
|
appendSearch: function (data, type, key) {
|
|
|
|
|
var searcHTML = '<ul>';
|
|
|
|
|
|
|
|
|
|
for (var i = 0, ii = data.length; i < ii; i++) {
|
|
|
|
|
var contents = data[i].contents[0],
|
|
|
|
|
index = contents.indexOf(key);
|
|
|
|
|
contents = contents.substring(0, index)
|
|
|
|
|
+ '<b>' + key + '</b>'
|
|
|
|
|
+ contents.substring(index + key.length);
|
|
|
|
|
|
|
|
|
|
searcHTML += '<li title="' + data[i].path + '">'
|
|
|
|
|
+ contents + " <span class='path'>" + data[i].path
|
|
|
|
|
+ '<i class="position" data-line="'
|
|
|
|
|
+ data[i].line + '" data-ch="' + data[i].ch + '"> (' + data[i].line + ':'
|
|
|
|
|
+ data[i].ch + ')</i></span></li>';
|
|
|
|
|
}
|
|
|
|
|
searcHTML += '</ul>';
|
|
|
|
|
|
|
|
|
|
var $search = $('.bottom-window-group .search'),
|
|
|
|
|
title = config.label.usages;
|
|
|
|
|
if (type === "founds") {
|
|
|
|
|
title = config.label.search_text;
|
|
|
|
|
}
|
|
|
|
|
if ($search.find("ul").length === 0) {
|
|
|
|
|
wide.searchTab = new Tabs({
|
2014-10-12 09:40:07 +04:00
|
|
|
|
id: ".bottom-window-group .search",
|
|
|
|
|
removeAfter: function (id, prevId) {
|
2014-10-12 18:00:26 +04:00
|
|
|
|
if ($search.find("ul").length === 1) {
|
|
|
|
|
$search.find(".tabs").hide();
|
2014-10-12 09:40:07 +04:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2014-10-12 18:00:26 +04:00
|
|
|
|
$search.on("click", "li", function () {
|
|
|
|
|
$search.find("li").removeClass("selected");
|
|
|
|
|
$(this).addClass("selected");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$search.on("dblclick", "li", function () {
|
|
|
|
|
var $it = $(this),
|
|
|
|
|
tId = tree.getTIdByPath($it.attr("title"));
|
|
|
|
|
tree.openFile(tree.fileTree.getNodeByTId(tId));
|
|
|
|
|
tree.fileTree.selectNode(wide.curNode);
|
|
|
|
|
|
|
|
|
|
var cursor = CodeMirror.Pos($it.find(".position").data("line") - 1, $it.find(".position").data("ch") - 1);
|
|
|
|
|
wide.curEditor.setCursor(cursor);
|
|
|
|
|
wide.curEditor.focus();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
$search.find(".tabs-panel > div").append(searcHTML);
|
|
|
|
|
|
|
|
|
|
$search.find(".tabs .first").text(title);
|
|
|
|
|
} else {
|
|
|
|
|
$search.find(".tabs").show();
|
|
|
|
|
wide.searchTab.add({
|
|
|
|
|
"id": "search" + (new Date()).getTime(),
|
|
|
|
|
"title": title,
|
|
|
|
|
"content": searcHTML
|
2014-10-12 09:40:07 +04:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// focus
|
|
|
|
|
wide.bottomWindowTab.setCurrent("search");
|
|
|
|
|
windows.flowBottom();
|
|
|
|
|
$(".bottom-window-group .search").focus();
|
|
|
|
|
},
|
2014-09-25 05:46:24 +04:00
|
|
|
|
// 新建一个编辑器 Tab,如果已经存在 Tab 则切换到该 Tab.
|
|
|
|
|
newEditor: function (data) {
|
|
|
|
|
$(".toolbars").show();
|
|
|
|
|
var id = wide.curNode.tId;
|
|
|
|
|
|
|
|
|
|
// 光标位置
|
|
|
|
|
var cursor = CodeMirror.Pos(0, 0);
|
|
|
|
|
if (data.cursorLine && data.cursorCh) {
|
|
|
|
|
cursor = CodeMirror.Pos(data.cursorLine - 1, data.cursorCh - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (var i = 0, ii = editors.data.length; i < ii; i++) {
|
|
|
|
|
if (editors.data[i].id === id) {
|
|
|
|
|
editors.tabs.setCurrent(id);
|
|
|
|
|
wide.curEditor = editors.data[i].editor;
|
|
|
|
|
wide.curEditor.setCursor(cursor);
|
|
|
|
|
wide.curEditor.focus();
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
editors.tabs.add({
|
|
|
|
|
id: id,
|
|
|
|
|
title: '<span title="' + wide.curNode.path + '"><span class="'
|
|
|
|
|
+ wide.curNode.iconSkin + 'ico"></span>' + wide.curNode.name + '</span>',
|
|
|
|
|
content: '<textarea id="editor' + id + '"></textarea>'
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
var rulers = [];
|
|
|
|
|
rulers.push({color: "#ccc", column: 120, lineStyle: "dashed"});
|
|
|
|
|
|
|
|
|
|
var editor = CodeMirror.fromTextArea(document.getElementById("editor" + id), {
|
|
|
|
|
lineNumbers: true,
|
|
|
|
|
autofocus: true,
|
|
|
|
|
autoCloseBrackets: true,
|
|
|
|
|
matchBrackets: true,
|
|
|
|
|
highlightSelectionMatches: {showToken: /\w/},
|
|
|
|
|
rulers: rulers,
|
|
|
|
|
styleActiveLine: true,
|
|
|
|
|
theme: 'lesser-dark',
|
|
|
|
|
indentUnit: 4,
|
|
|
|
|
foldGutter: true,
|
|
|
|
|
extraKeys: {
|
|
|
|
|
"Ctrl-\\": "autocompleteAnyWord",
|
|
|
|
|
".": "autocompleteAfterDot",
|
2014-10-10 07:18:52 +04:00
|
|
|
|
"Ctrl-I": "exprInfo",
|
2014-09-25 05:46:24 +04:00
|
|
|
|
"Ctrl-G": "gotoLine",
|
|
|
|
|
"Ctrl-E": "deleteLine",
|
|
|
|
|
"Ctrl-D": "doNothing", // 取消默认的 deleteLine
|
|
|
|
|
"Ctrl-B": "jumpToDecl",
|
|
|
|
|
"Ctrl-S": function () {
|
|
|
|
|
wide.saveFile();
|
|
|
|
|
},
|
|
|
|
|
"Shift-Ctrl-S": function () {
|
|
|
|
|
wide.saveAllFiles();
|
|
|
|
|
},
|
|
|
|
|
"Shift-Alt-F": function () {
|
|
|
|
|
wide.fmt();
|
|
|
|
|
},
|
|
|
|
|
"Alt-F7": "findUsages"
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
editor.on('cursorActivity', function (cm) {
|
2014-10-10 14:04:03 +04:00
|
|
|
|
$(".edit-exprinfo").remove();
|
2014-09-25 05:46:24 +04:00
|
|
|
|
var cursor = cm.getCursor();
|
|
|
|
|
|
2014-09-25 12:03:14 +04:00
|
|
|
|
$(".footer .cursor").text('| ' + (cursor.line + 1) + ':' + (cursor.ch + 1) + ' |');
|
2014-09-25 05:46:24 +04:00
|
|
|
|
// TODO: 关闭 tab 的时候要重置
|
|
|
|
|
});
|
|
|
|
|
|
2014-09-26 11:39:13 +04:00
|
|
|
|
editor.on('focus', function (cm) {
|
2014-09-26 12:41:25 +04:00
|
|
|
|
windows.clearFloat();
|
2014-09-26 11:39:13 +04:00
|
|
|
|
});
|
|
|
|
|
|
2014-10-10 14:04:03 +04:00
|
|
|
|
editor.on('blur', function (cm) {
|
|
|
|
|
$(".edit-exprinfo").remove();
|
|
|
|
|
});
|
|
|
|
|
|
2014-09-25 11:56:26 +04:00
|
|
|
|
editor.setSize('100%', $(".edit-panel").height() - $(".edit-panel .tabs").height());
|
2014-09-25 05:46:24 +04:00
|
|
|
|
editor.setValue(data.content);
|
2014-10-10 14:04:03 +04:00
|
|
|
|
editor.setOption("mode", data.mode);
|
2014-09-25 05:46:24 +04:00
|
|
|
|
editor.setOption("gutters", ["CodeMirror-lint-markers", "CodeMirror-foldgutter"]);
|
|
|
|
|
|
|
|
|
|
if ("text/x-go" === data.mode || "application/json" === data.mode) {
|
|
|
|
|
editor.setOption("lint", true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ("application/xml" === data.mode || "text/html" === data.mode) {
|
|
|
|
|
editor.setOption("autoCloseTags", true);
|
|
|
|
|
}
|
2014-10-10 14:04:03 +04:00
|
|
|
|
|
2014-10-10 07:27:17 +04:00
|
|
|
|
editor.setCursor(cursor);
|
2014-09-25 05:46:24 +04:00
|
|
|
|
|
|
|
|
|
wide.curEditor = editor;
|
|
|
|
|
editors.data.push({
|
|
|
|
|
"editor": editor,
|
|
|
|
|
"id": id
|
|
|
|
|
});
|
|
|
|
|
}
|
2014-09-26 11:39:13 +04:00
|
|
|
|
};
|