/* ***** 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/ext/rtl"); require("ace/multi_select"); require("./inline_editor"); var devUtil = 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 layout = require("./layout"); var util = require("./util"); var saveOption = util.saveOption; var ElasticTabstopsLite = require("ace/ext/elastic_tabstops_lite").ElasticTabstopsLite; var IncrementalSearch = require("ace/incremental_search").IncrementalSearch; var TokenTooltip = require("./token_tooltip").TokenTooltip; require("ace/config").defineOptions(Editor.prototype, "editor", { showTokenInfo: { set: function(val) { if (val) { this.tokenTooltip = this.tokenTooltip || new TokenTooltip(this); } else if (this.tokenTooltip) { this.tokenTooltip.destroy(); delete this.tokenTooltip; } }, get: function() { return !!this.tokenTooltip; }, handlesSet: true } }); 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: "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); } } }); /*********** 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 ***************************/ 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]; doclist.pickDocument(s); }; 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); } }; doclist.pickDocument = function(name) { doclist.loadDoc(name, function(session) { if (!session) return; doclist.addToHistory(session.name); session = env.split.setSession(session); whitespace.detectIndentation(session); optionsPanel.render(); env.editor.focus(); }); }; var OptionPanel = require("ace/ext/options").OptionPanel; var optionsPanel = new OptionPanel(env.editor); optionsPanel.add({ Main: { Document: { type: "select", path: "doc", items: doclist.all, position: -101, onchange: doclist.pickDocument, getValue: function() { return env.editor.session.name || "javascript"; } }, Split: { type: "buttonBar", path: "split", values: ["None", "Below", "Beside"], position: -100, onchange: function(value) { var sp = env.split; if (value == "Below" || value == "Beside") { 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; } } else { sp.setSplits(1); } }, getValue: function() { var sp = env.split; return sp.getSplits() == 1 ? "None" : sp.getOrientation() == sp.BELOW ? "Below" : "Beside"; } } }, More: { "RTL": { path: "rtl", position: 900 }, "Line based RTL switching": { path: "rtlText", position: 900 }, "Show token info": { path: "showTokenInfo", position: 2000 }, "Text Input Debugger": devUtil.textInputDebugger } }); var optionsPanelContainer = document.getElementById("optionsPanel"); optionsPanel.render(); optionsPanelContainer.insertBefore(optionsPanel.container, optionsPanelContainer.firstChild); optionsPanel.on("setOption", function(e) { util.saveOption(e.name, e.value); }); function updateUIEditorOptions() { optionsPanel.editor = env.editor; optionsPanel.render(); } optionsPanel.setOption("doc", util.getOption("doc") || "JavaScript"); for (var i in optionsPanel.options) { var value = util.getOption(i); if (value != undefined) { if ((i == "mode" || i == "theme") && !/[/]/.test(value)) value = "ace/" + i + "/" + value; optionsPanel.setOption(i, value); } } 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)}); } 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(); }; optionsPanelContainer.insertBefore( dom.buildDom(["div", {style: "text-align:right;margin-right: 60px"}, ["div", {}, ["button", {onclick: env.editSnippets}, "Edit Snippets"]], ["div", {}, ["button", {onclick: function() { var info = navigator.platform + "\n" + navigator.userAgent; if (env.editor.getValue() == info) return env.editor.undo(); env.editor.setValue(info, -1); env.editor.setOption("wrap", 80); }}, "Show Browser Info"]], devUtil.getUI() ]), optionsPanelContainer.children[1] ); require("ace/ext/language_tools"); env.editor.setOptions({ enableBasicAutocompletion: true, enableSnippets: true }); var beautify = require("ace/ext/beautify"); env.editor.commands.addCommands(beautify.commands); // global keybindings var KeyBinding = require("ace/keyboard/keybinding").KeyBinding; var CommandManager = require("ace/commands/command_manager").CommandManager; var commandManager = new CommandManager(); var kb = new KeyBinding({ commands: commandManager, fake: true }); event.addCommandKeyListener(document.documentElement, kb.onCommandKey.bind(kb)); event.addListener(document.documentElement, "keyup", function(e) { if (e.keyCode === 18) // do not trigger browser menu on windows e.preventDefault(); }); commandManager.addCommands([{ name: "window-left", bindKey: {win: "cmd-alt-left", mac: "ctrl-cmd-left"}, exec: function() { moveFocus(); } }, { name: "window-right", bindKey: {win: "cmd-alt-right", mac: "ctrl-cmd-right"}, exec: function() { moveFocus(); } }, { name: "window-up", bindKey: {win: "cmd-alt-up", mac: "ctrl-cmd-up"}, exec: function() { moveFocus(); } }, { name: "window-down", bindKey: {win: "cmd-alt-down", mac: "ctrl-cmd-down"}, exec: function() { moveFocus(); } }]); function moveFocus() { var el = document.activeElement; if (el == env.editor.textInput.getElement()) env.editor.cmdLine.focus(); else env.editor.focus(); } });