2016-02-23 15:41:22 +01:00

586 lines
18 KiB
JavaScript

/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2010, Ajax.org B.V.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
define(function(require, exports, module) {
"use strict";
require("ace/lib/fixoldbrowsers");
require("ace/multi_select");
require("ace/ext/spellcheck");
require("./inline_editor");
require("./dev_util");
require("./file_drop");
var config = require("ace/config");
config.init();
var env = {};
var dom = require("ace/lib/dom");
var net = require("ace/lib/net");
var lang = require("ace/lib/lang");
var useragent = require("ace/lib/useragent");
var event = require("ace/lib/event");
var theme = require("ace/theme/textmate");
var EditSession = require("ace/edit_session").EditSession;
var UndoManager = require("ace/undomanager").UndoManager;
var HashHandler = require("ace/keyboard/hash_handler").HashHandler;
var Renderer = require("ace/virtual_renderer").VirtualRenderer;
var Editor = require("ace/editor").Editor;
var whitespace = require("ace/ext/whitespace");
var doclist = require("./doclist");
var modelist = require("ace/ext/modelist");
var themelist = require("ace/ext/themelist");
var layout = require("./layout");
var TokenTooltip = require("./token_tooltip").TokenTooltip;
var util = require("./util");
var saveOption = util.saveOption;
var fillDropdown = util.fillDropdown;
var bindCheckbox = util.bindCheckbox;
var bindDropdown = util.bindDropdown;
var ElasticTabstopsLite = require("ace/ext/elastic_tabstops_lite").ElasticTabstopsLite;
var IncrementalSearch = require("ace/incremental_search").IncrementalSearch;
var workerModule = require("ace/worker/worker_client");
if (location.href.indexOf("noworker") !== -1) {
workerModule.WorkerClient = workerModule.UIWorkerClient;
}
/*********** create editor ***************************/
var container = document.getElementById("editor-container");
// Splitting.
var Split = require("ace/split").Split;
var split = new Split(container, theme, 1);
env.editor = split.getEditor(0);
split.on("focus", function(editor) {
env.editor = editor;
updateUIEditorOptions();
});
env.split = split;
window.env = env;
var consoleEl = dom.createElement("div");
container.parentNode.appendChild(consoleEl);
consoleEl.style.cssText = "position:fixed; bottom:1px; right:0;\
border:1px solid #baf; z-index:100";
var cmdLine = new layout.singleLineEditor(consoleEl);
cmdLine.editor = env.editor;
env.editor.cmdLine = cmdLine;
env.editor.showCommandLine = function(val) {
this.cmdLine.focus();
if (typeof val == "string")
this.cmdLine.setValue(val, 1);
};
/**
* This demonstrates how you can define commands and bind shortcuts to them.
*/
env.editor.commands.addCommands([{
name: "gotoline",
bindKey: {win: "Ctrl-L", mac: "Command-L"},
exec: function(editor, line) {
if (typeof line == "object") {
var arg = this.name + " " + editor.getCursorPosition().row;
editor.cmdLine.setValue(arg, 1);
editor.cmdLine.focus();
return;
}
line = parseInt(line, 10);
if (!isNaN(line))
editor.gotoLine(line);
},
readOnly: true
}, {
name: "snippet",
bindKey: {win: "Alt-C", mac: "Command-Alt-C"},
exec: function(editor, needle) {
if (typeof needle == "object") {
editor.cmdLine.setValue("snippet ", 1);
editor.cmdLine.focus();
return;
}
var s = snippetManager.getSnippetByName(needle, editor);
if (s)
snippetManager.insertSnippet(editor, s.content);
},
readOnly: true
}, {
name: "focusCommandLine",
bindKey: "shift-esc|ctrl-`",
exec: function(editor, needle) { editor.cmdLine.focus(); },
readOnly: true
}, {
name: "nextFile",
bindKey: "Ctrl-tab",
exec: function(editor) { doclist.cycleOpen(editor, 1); },
readOnly: true
}, {
name: "previousFile",
bindKey: "Ctrl-shift-tab",
exec: function(editor) { doclist.cycleOpen(editor, -1); },
readOnly: true
}, {
name: "execute",
bindKey: "ctrl+enter",
exec: function(editor) {
try {
var r = window.eval(editor.getCopyText() || editor.getValue());
} catch(e) {
r = e;
}
editor.cmdLine.setValue(r + "");
},
readOnly: true
}, {
name: "showKeyboardShortcuts",
bindKey: {win: "Ctrl-Alt-h", mac: "Command-Alt-h"},
exec: function(editor) {
config.loadModule("ace/ext/keybinding_menu", function(module) {
module.init(editor);
editor.showKeyboardShortcuts();
});
}
}, {
name: "increaseFontSize",
bindKey: "Ctrl-=|Ctrl-+",
exec: function(editor) {
var size = parseInt(editor.getFontSize(), 10) || 12;
editor.setFontSize(size + 1);
}
}, {
name: "decreaseFontSize",
bindKey: "Ctrl+-|Ctrl-_",
exec: function(editor) {
var size = parseInt(editor.getFontSize(), 10) || 12;
editor.setFontSize(Math.max(size - 1 || 1));
}
}, {
name: "resetFontSize",
bindKey: "Ctrl+0|Ctrl-Numpad0",
exec: function(editor) {
editor.setFontSize(12);
}
}]);
env.editor.commands.addCommands(whitespace.commands);
cmdLine.commands.bindKeys({
"Shift-Return|Ctrl-Return|Alt-Return": function(cmdLine) { cmdLine.insert("\n"); },
"Esc|Shift-Esc": function(cmdLine){ cmdLine.editor.focus(); },
"Return": function(cmdLine){
var command = cmdLine.getValue().split(/\s+/);
var editor = cmdLine.editor;
editor.commands.exec(command[0], editor, command[1]);
editor.focus();
}
});
cmdLine.commands.removeCommands(["find", "gotoline", "findall", "replace", "replaceall"]);
var commands = env.editor.commands;
commands.addCommand({
name: "save",
bindKey: {win: "Ctrl-S", mac: "Command-S"},
exec: function(arg) {
var session = env.editor.session;
var name = session.name.match(/[^\/]+$/);
localStorage.setItem(
"saved_file:" + name,
session.getValue()
);
env.editor.cmdLine.setValue("saved "+ name);
}
});
commands.addCommand({
name: "load",
bindKey: {win: "Ctrl-O", mac: "Command-O"},
exec: function(arg) {
var session = env.editor.session;
var name = session.name.match(/[^\/]+$/);
var value = localStorage.getItem("saved_file:" + name);
if (typeof value == "string") {
session.setValue(value);
env.editor.cmdLine.setValue("loaded "+ name);
} else {
env.editor.cmdLine.setValue("no previuos value saved for "+ name);
}
}
});
var keybindings = {
ace: null, // Null = use "default" keymapping
vim: require("ace/keyboard/vim").handler,
emacs: "ace/keyboard/emacs",
// This is a way to define simple keyboard remappings
custom: new HashHandler({
"gotoright": "Tab",
"indent": "]",
"outdent": "[",
"gotolinestart": "^",
"gotolineend": "$"
})
};
/*********** manage layout ***************************/
var consoleHeight = 20;
function onResize() {
var left = env.split.$container.offsetLeft;
var width = document.documentElement.clientWidth - left;
container.style.width = width + "px";
container.style.height = document.documentElement.clientHeight - consoleHeight + "px";
env.split.resize();
consoleEl.style.width = width + "px";
cmdLine.resize();
}
window.onresize = onResize;
onResize();
/*********** options panel ***************************/
var docEl = document.getElementById("doc");
var modeEl = document.getElementById("mode");
var wrapModeEl = document.getElementById("soft_wrap");
var themeEl = document.getElementById("theme");
var foldingEl = document.getElementById("folding");
var selectStyleEl = document.getElementById("select_style");
var highlightActiveEl = document.getElementById("highlight_active");
var showHiddenEl = document.getElementById("show_hidden");
var showGutterEl = document.getElementById("show_gutter");
var showPrintMarginEl = document.getElementById("show_print_margin");
var highlightSelectedWordE = document.getElementById("highlight_selected_word");
var showHScrollEl = document.getElementById("show_hscroll");
var showVScrollEl = document.getElementById("show_vscroll");
var animateScrollEl = document.getElementById("animate_scroll");
var softTabEl = document.getElementById("soft_tab");
var behavioursEl = document.getElementById("enable_behaviours");
fillDropdown(docEl, doclist.all);
fillDropdown(modeEl, modelist.modes);
var modesByName = modelist.modesByName;
bindDropdown("mode", function(value) {
env.editor.session.setMode(modesByName[value].mode || modesByName.text.mode);
env.editor.session.modeName = value;
});
doclist.history = doclist.docs.map(function(doc) {
return doc.name;
});
doclist.history.index = 0;
doclist.cycleOpen = function(editor, dir) {
var h = this.history;
h.index += dir;
if (h.index >= h.length)
h.index = 0;
else if (h.index <= 0)
h.index = h.length - 1;
var s = h[h.index];
docEl.value = s;
docEl.onchange();
};
doclist.addToHistory = function(name) {
var h = this.history;
var i = h.indexOf(name);
if (i != h.index) {
if (i != -1)
h.splice(i, 1);
h.index = h.push(name);
}
};
bindDropdown("doc", function(name) {
doclist.loadDoc(name, function(session) {
if (!session)
return;
doclist.addToHistory(session.name);
session = env.split.setSession(session);
whitespace.detectIndentation(session);
updateUIEditorOptions();
env.editor.focus();
});
});
function updateUIEditorOptions() {
var editor = env.editor;
var session = editor.session;
session.setFoldStyle(foldingEl.value);
saveOption(docEl, session.name);
saveOption(modeEl, session.modeName || "text");
saveOption(wrapModeEl, session.getUseWrapMode() ? session.getWrapLimitRange().min || "free" : "off");
saveOption(selectStyleEl, editor.getSelectionStyle() == "line");
saveOption(themeEl, editor.getTheme());
saveOption(highlightActiveEl, editor.getHighlightActiveLine());
saveOption(showHiddenEl, editor.getShowInvisibles());
saveOption(showGutterEl, editor.renderer.getShowGutter());
saveOption(showPrintMarginEl, editor.renderer.getShowPrintMargin());
saveOption(highlightSelectedWordE, editor.getHighlightSelectedWord());
saveOption(showHScrollEl, editor.renderer.getHScrollBarAlwaysVisible());
saveOption(animateScrollEl, editor.getAnimatedScroll());
saveOption(softTabEl, session.getUseSoftTabs());
saveOption(behavioursEl, editor.getBehavioursEnabled());
}
themelist.themes.forEach(function(x){ x.value = x.theme });
fillDropdown(themeEl, {
Bright: themelist.themes.filter(function(x){return !x.isDark}),
Dark: themelist.themes.filter(function(x){return x.isDark})
});
event.addListener(themeEl, "mouseover", function(e){
themeEl.desiredValue = e.target.value;
if (!themeEl.$timer)
themeEl.$timer = setTimeout(themeEl.updateTheme);
});
event.addListener(themeEl, "mouseout", function(e){
themeEl.desiredValue = null;
if (!themeEl.$timer)
themeEl.$timer = setTimeout(themeEl.updateTheme, 20);
});
themeEl.updateTheme = function(){
env.split.setTheme((themeEl.desiredValue || themeEl.selectedValue));
themeEl.$timer = null;
};
bindDropdown("theme", function(value) {
if (!value)
return;
env.editor.setTheme(value);
themeEl.selectedValue = value;
});
bindDropdown("keybinding", function(value) {
env.editor.setKeyboardHandler(keybindings[value]);
});
bindDropdown("fontsize", function(value) {
env.split.setFontSize(value);
});
bindDropdown("folding", function(value) {
env.editor.session.setFoldStyle(value);
env.editor.setShowFoldWidgets(value !== "manual");
});
bindDropdown("soft_wrap", function(value) {
env.editor.setOption("wrap", value);
});
bindCheckbox("select_style", function(checked) {
env.editor.setOption("selectionStyle", checked ? "line" : "text");
});
bindCheckbox("highlight_active", function(checked) {
env.editor.setHighlightActiveLine(checked);
});
bindCheckbox("show_hidden", function(checked) {
env.editor.setShowInvisibles(checked);
});
bindCheckbox("display_indent_guides", function(checked) {
env.editor.setDisplayIndentGuides(checked);
});
bindCheckbox("show_gutter", function(checked) {
env.editor.renderer.setShowGutter(checked);
});
bindCheckbox("show_print_margin", function(checked) {
env.editor.renderer.setShowPrintMargin(checked);
});
bindCheckbox("highlight_selected_word", function(checked) {
env.editor.setHighlightSelectedWord(checked);
});
bindCheckbox("show_hscroll", function(checked) {
env.editor.setOption("hScrollBarAlwaysVisible", checked);
});
bindCheckbox("show_vscroll", function(checked) {
env.editor.setOption("vScrollBarAlwaysVisible", checked);
});
bindCheckbox("animate_scroll", function(checked) {
env.editor.setAnimatedScroll(checked);
});
bindCheckbox("soft_tab", function(checked) {
env.editor.session.setUseSoftTabs(checked);
});
bindCheckbox("enable_behaviours", function(checked) {
env.editor.setBehavioursEnabled(checked);
});
bindCheckbox("fade_fold_widgets", function(checked) {
env.editor.setFadeFoldWidgets(checked);
});
bindCheckbox("read_only", function(checked) {
env.editor.setReadOnly(checked);
});
bindCheckbox("scrollPastEnd", function(checked) {
env.editor.setOption("scrollPastEnd", checked);
});
bindDropdown("split", function(value) {
var sp = env.split;
if (value == "none") {
sp.setSplits(1);
} else {
var newEditor = (sp.getSplits() == 1);
sp.setOrientation(value == "below" ? sp.BELOW : sp.BESIDE);
sp.setSplits(2);
if (newEditor) {
var session = sp.getEditor(0).session;
var newSession = sp.setSession(session, 1);
newSession.name = session.name;
}
}
});
bindCheckbox("elastic_tabstops", function(checked) {
env.editor.setOption("useElasticTabstops", checked);
});
var iSearchCheckbox = bindCheckbox("isearch", function(checked) {
env.editor.setOption("useIncrementalSearch", checked);
});
env.editor.addEventListener('incrementalSearchSettingChanged', function(event) {
iSearchCheckbox.checked = event.isEnabled;
});
function synchroniseScrolling() {
var s1 = env.split.$editors[0].session;
var s2 = env.split.$editors[1].session;
s1.on('changeScrollTop', function(pos) {s2.setScrollTop(pos)});
s2.on('changeScrollTop', function(pos) {s1.setScrollTop(pos)});
s1.on('changeScrollLeft', function(pos) {s2.setScrollLeft(pos)});
s2.on('changeScrollLeft', function(pos) {s1.setScrollLeft(pos)});
}
bindCheckbox("highlight_token", function(checked) {
var editor = env.editor;
if (editor.tokenTooltip && !checked) {
editor.tokenTooltip.destroy();
delete editor.tokenTooltip;
} else if (checked) {
editor.tokenTooltip = new TokenTooltip(editor);
}
});
var StatusBar = require("ace/ext/statusbar").StatusBar;
new StatusBar(env.editor, cmdLine.container);
var Emmet = require("ace/ext/emmet");
net.loadScript("https://cloud9ide.github.io/emmet-core/emmet.js", function() {
Emmet.setCore(window.emmet);
env.editor.setOption("enableEmmet", true);
});
// require("ace/placeholder").PlaceHolder;
var snippetManager = require("ace/snippets").snippetManager;
env.editSnippets = function() {
var sp = env.split;
if (sp.getSplits() == 2) {
sp.setSplits(1);
return;
}
sp.setSplits(1);
sp.setSplits(2);
sp.setOrientation(sp.BESIDE);
var editor = sp.$editors[1];
var id = sp.$editors[0].session.$mode.$id || "";
var m = snippetManager.files[id];
if (!doclist["snippets/" + id]) {
var text = m.snippetText;
var s = doclist.initDoc(text, "", {});
s.setMode("ace/mode/snippets");
doclist["snippets/" + id] = s;
}
editor.on("blur", function() {
m.snippetText = editor.getValue();
snippetManager.unregister(m.snippets);
m.snippets = snippetManager.parseSnippetFile(m.snippetText, m.scope);
snippetManager.register(m.snippets);
});
sp.$editors[0].once("changeMode", function() {
sp.setSplits(1);
});
editor.setSession(doclist["snippets/" + id], 1);
editor.focus();
};
require("ace/ext/language_tools");
env.editor.setOptions({
enableBasicAutocompletion: true,
enableLiveAutocompletion: false,
enableSnippets: true
});
var beautify = require("ace/ext/beautify");
env.editor.commands.addCommands(beautify.commands);
});