summaryrefslogtreecommitdiff
path: root/objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base
diff options
context:
space:
mode:
Diffstat (limited to 'objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base')
-rw-r--r--objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base431
1 files changed, 431 insertions, 0 deletions
diff --git a/objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base b/objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base
new file mode 100644
index 00000000..1265bc64
--- /dev/null
+++ b/objectapp/static/objectapp/js/Gnowmacs/src/js/.svn/text-base/ymacs-mode-js.js.svn-base
@@ -0,0 +1,431 @@
+//> This file is part of Ymacs, an Emacs-like editor for the Web
+//> http://www.ymacs.org/
+//>
+//> Copyright (c) 2009-2010, Mihai Bazon, Dynarch.com. 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 Dynarch.com 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 HOLDER “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 THE COPYRIGHT HOLDER 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.
+
+// @require ymacs-tokenizer.js
+
+/* -----[ This defines the tokenizer ]----- */
+
+(function(){
+
+ var KEYWORDS = "abstract break case catch class const \
+continue debugger default delete do else \
+enum export extends final finally for \
+function goto if implements import in \
+instanceof interface native new package \
+private protected public return static \
+super switch synchronized throw \
+throws transient try typeof var void let \
+yield volatile while with".qw();
+
+ var KEYWORDS_TYPE = "boolean byte char double float int long short void \
+Array Date Function Math Number Object RegExp String".qw();
+
+ var KEYWORDS_CONST = "false null undefined Infinity NaN true arguments this".qw();
+
+ var KEYWORDS_BUILTIN = "Infinity NaN \
+Packages decodeURI decodeURIComponent \
+encodeURI encodeURIComponent eval isFinite isNaN parseFloat \
+parseInt undefined window document alert prototype constructor".qw();
+
+ var ALLOW_REGEXP_AFTER = /[\[({,;+\-*=?&|!:][\x20\t\n\xa0]*$|return\s+$|typeof\s+$/;
+
+ function isLetter(ch) {
+ return ch.toLowerCase() != ch.toUpperCase();
+ };
+
+ function isNameStart(ch) {
+ return ch && (isLetter(ch) || /^[_$]$/.test(ch));
+ };
+
+ function isNameChar(ch) {
+ return ch && (isLetter(ch) || /^[0-9_$]$/.test(ch));
+ };
+
+ var OPEN_PAREN = {
+ "(" : ")",
+ "{" : "}",
+ "[" : "]"
+ };
+
+ var CLOSE_PAREN = {
+ ")" : "(",
+ "}" : "{",
+ "]" : "["
+ };
+
+ function isOpenParen(ch) {
+ return OPEN_PAREN[ch];
+ };
+
+ function isCloseParen(ch) {
+ return CLOSE_PAREN[ch];
+ };
+
+ function JS_PARSER(KEYWORDS, KEYWORDS_TYPE, KEYWORDS_CONST, KEYWORDS_BUILTIN, stream, tok) {
+
+ var $cont = [],
+ $parens = [],
+ $passedParens = [],
+ $inComment = null,
+ $inString = null,
+ PARSER = {
+ next : next,
+ copy : copy,
+ indentation : indentation
+ };
+
+ function INDENT_LEVEL() {
+ return stream.buffer.getq("indent_level");
+ };
+
+ function copy() {
+ var context = restore.context = {
+ cont : $cont.slice(0),
+ inComment : $inComment,
+ inString : $inString,
+ parens : $parens.slice(0),
+ passedParens : $passedParens.slice(0)
+ };
+ function restore() {
+ $cont = context.cont.slice(0);
+ $inComment = context.inComment;
+ $inString = context.inString;
+ $parens = context.parens.slice(0);
+ $passedParens = context.passedParens.slice(0);
+ return PARSER;
+ };
+ return restore;
+ };
+
+ function foundToken(c1, c2, type) {
+ tok.onToken(stream.line, c1, c2, type);
+ };
+
+ function readName() {
+ var col = stream.col, ch = stream.get(),
+ name = ch;
+ while (!stream.eol()) {
+ ch = stream.peek();
+ if (!isNameChar(ch))
+ break;
+ name += ch;
+ stream.nextCol();
+ }
+ return ch && { line: stream.line, c1: col, c2: stream.col, id: name };
+ };
+
+ function readComment() {
+ var line = stream.lineText(), pos = line.indexOf("*/", stream.col);
+ var m = /^\s*\*+/.exec(line.substr(stream.col));
+ if (m) {
+ foundToken(stream.col, stream.col += m[0].length, "mcomment-starter");
+ }
+ if (pos >= 0) {
+ $cont.pop();
+ $inComment = null;
+ foundToken(stream.col, pos, "mcomment");
+ foundToken(pos, pos += 2, "mcomment-stopper");
+ stream.col = pos;
+ } else {
+ foundToken(stream.col, line.length, "mcomment");
+ stream.col = line.length;
+ }
+ };
+
+ function readString(end, type) {
+ var ch, esc = false, start = stream.col;
+ while (!stream.eol()) {
+ ch = stream.peek();
+ if (ch === end && !esc) {
+ $cont.pop();
+ $inString = null;
+ foundToken(start, stream.col, type);
+ foundToken(stream.col, ++stream.col, type + "-stopper");
+ return true;
+ }
+ esc = !esc && ch === "\\";
+ stream.nextCol();
+ }
+ foundToken(start, stream.col, type);
+ };
+
+ // function readLiteralRegexp() {
+ // var m;
+ // if (readString("/", "regexp") && (m = stream.lookingAt(/^[gmsiy]+/)))
+ // foundToken(stream.col, stream.col += m[0].length, "regexp-modifier");
+ // };
+
+ function readLiteralRegexp() {
+ var ch, esc = false, inset = 0, start = stream.col;
+ while (!stream.eol()) {
+ ch = stream.peek();
+ if (isOpenParen(ch) && !esc && !inset)
+ inset++;
+ if (isCloseParen(ch) && !esc) {
+ inset--;
+ if (inset < 0)
+ inset = 0;
+ }
+ if (ch === "/" && !esc && !inset) {
+ $cont.pop();
+ $inString = null;
+ foundToken(start, stream.col, "regexp");
+ foundToken(stream.col, ++stream.col, "regexp-stopper");
+ var m = stream.lookingAt(/^[gmsiy]+/);
+ if (m)
+ foundToken(stream.col, stream.col += m[0].length, "regexp-modifier");
+ return true;
+ }
+ esc = !esc && ch === "\\";
+ stream.nextCol();
+ }
+ foundToken(start, stream.col, "regexp");
+ };
+
+ function next() {
+ stream.checkStop();
+ if ($cont.length > 0)
+ return $cont.peek()();
+ var ch = stream.peek(), m, tmp;
+ if (stream.lookingAt("/*")) {
+ $inComment = { line: stream.line, c1: stream.col };
+ foundToken(stream.col, stream.col += 2, "mcomment-starter");
+ $cont.push(readComment);
+ }
+ else if (stream.lookingAt("//")) {
+ foundToken(stream.col, stream.col += 2, "comment-starter");
+ foundToken(stream.col, stream.col = stream.lineLength(), "comment");
+ }
+ else if (ch === '"' || ch === "'") {
+ $inString = { line: stream.line, c1: stream.col };
+ foundToken(stream.col, ++stream.col, "string-starter");
+ $cont.push(readString.$C(ch, "string"));
+ }
+ else if ((m = stream.lookingAt(/^0x[0-9a-f]+|^[0-9]*\.?[0-9]+/))) {
+ foundToken(stream.col, stream.col += m[0].length, "number");
+ }
+ else if (isNameStart(ch) && (tmp = readName())) {
+ var type = tmp.id in KEYWORDS ? "keyword"
+ : tmp.id in KEYWORDS_TYPE ? "type"
+ : tmp.id in KEYWORDS_CONST ? "constant"
+ : tmp.id in KEYWORDS_BUILTIN ? "builtin"
+ : null;
+ foundToken(tmp.c1, tmp.c2, type);
+ }
+ else if ((tmp = isOpenParen(ch))) {
+ $parens.push({ line: stream.line, col: stream.col, type: ch });
+ foundToken(stream.col, ++stream.col, "open-paren");
+ }
+ else if ((tmp = isCloseParen(ch))) {
+ var p = $parens.pop();
+ if (!p || p.type != tmp) {
+ foundToken(stream.col, ++stream.col, "error");
+ } else {
+ // circular reference; poor browsers will leak. mwuhahahaha
+ p.closed = { line: stream.line, col: stream.col, opened: p };
+ $passedParens.push(p);
+ foundToken(stream.col, ++stream.col, "close-paren");
+ }
+ }
+ else if (ch === "/" && ALLOW_REGEXP_AFTER.test(stream.textBefore())) {
+ foundToken(stream.col, ++stream.col, "regexp-starter");
+ $cont.push(readLiteralRegexp);
+ }
+ else if ((m = stream.lookingAt(/^\s+$/))) {
+ foundToken(stream.col, stream.col += m[0].length, "trailing-whitespace");
+ }
+ else {
+ foundToken(stream.col, ++stream.col, null);
+ }
+ };
+
+ function indentation() {
+
+ // no indentation for continued strings
+ if ($inString)
+ return 0;
+
+ var row = stream.line;
+ var currentLine = stream.lineText();
+ var indent = 0;
+
+ if ($inComment) {
+ var commentStartLine = stream.lineText($inComment.line);
+ indent = $inComment.c1 + 1;
+ if (!/^\s*\*/.test(currentLine)) {
+ // align with the first non-whitespace and non-asterisk character in the comment
+ var re = /[^\s*]/g;
+ re.lastIndex = $inComment.c1 + 1;
+ var m = re.exec(commentStartLine);
+ if (m)
+ indent = m.index;
+ }
+ return indent;
+ }
+
+ var p = $parens.peek();
+ if (p) {
+ // check if the current line closes the paren
+ var re = new RegExp("^\\s*\\" + OPEN_PAREN[p.type]);
+ var thisLineCloses = re.test(currentLine);
+
+ // Check if there is text after the opening paren. If so, indent to that column.
+ var line = stream.lineText(p.line);
+ re = /\S/g;
+ re.lastIndex = p.col + 1;
+ var m = re.exec(line);
+ if (m) {
+ // but if this line closes the paren, better use the column of the open paren
+ indent = thisLineCloses ? p.col : m.index;
+ }
+ else {
+ // Otherwise we should indent to one level more than the indentation of the line
+ // containing the opening paren.
+ indent = stream.lineIndentation(p.line) + INDENT_LEVEL();
+
+ // but if this line closes the paren, then back one level
+ if (thisLineCloses)
+ indent -= INDENT_LEVEL();
+ }
+ }
+
+ // Some more adjustments for continued statements. Since we don't really have a
+ // rigorous parser, we have to rely on other regexps here, which sucks but will do for
+ // now.
+
+ if (row > 0) {
+ var before = stream.textBefore();
+ if (/\)\s*$/.test(before) && $passedParens.length > 0) {
+ // Ends in a paren, could be an if, while or for which demands smart
+ // indentation on the current line, let's check it out.
+
+ // Note that the passedParen saved for that close paren is actually
+ // the opening one, which suits us greatly.
+ p = $passedParens.peek();
+ var stmtLine = stream.lineText(p.line);
+ if (/^\s*(if|for|while)\W/.test(stmtLine))
+ indent += INDENT_LEVEL();
+ }
+ else if (/\Welse\s*$/.test(before)) {
+ indent += INDENT_LEVEL();
+ }
+ }
+
+ // switch labels use half the indent level, which is my favorite
+ if (/^\s*(case|default)\W/.test(currentLine))
+ indent -= INDENT_LEVEL() / 2;
+
+ return indent;
+ };
+
+ return PARSER;
+
+ };
+
+ Ymacs_Tokenizer.define("js", JS_PARSER.$C(
+ KEYWORDS.toHash(true),
+ KEYWORDS_TYPE.toHash(true),
+ KEYWORDS_CONST.toHash(true),
+ KEYWORDS_BUILTIN.toHash(true)
+ ));
+
+ /* -----[ DynarchLIB ]----- */
+
+ var DL_KEYWORDS_BUILTIN = KEYWORDS_BUILTIN.concat("\
+DEFINE_CLASS DEFINE_SINGLETON DEFINE_HIDDEN_CLASS \
+DEFAULT_ARGS DEFAULT_EVENTS \
+FIXARGS CONSTRUCT BEFORE_BASE FINISH_OBJECT_DEF \
+D P $".qw());
+
+ Ymacs_Tokenizer.define("js-dynarchlib", JS_PARSER.$C(
+ KEYWORDS.toHash(true),
+ KEYWORDS_TYPE.toHash(true),
+ KEYWORDS_CONST.toHash(true),
+ DL_KEYWORDS_BUILTIN.toHash(true)
+ ));
+
+})();
+
+/* -----[ Keymap for C-like language mode ]----- */
+
+DEFINE_SINGLETON("Ymacs_Keymap_CLanguages", Ymacs_Keymap, function(D, P){
+
+ D.KEYS = {
+ "ENTER" : "newline_and_indent",
+ "} && ) && ] && : && ; && { && ( && [ && *" : "c_insert_and_indent"
+ // "{" : "c_electric_block"
+ };
+
+});
+
+/* -----[ Mode entry point ]----- */
+
+Ymacs_Buffer.newMode("javascript_mode", function(useDL) {
+ var tok = this.tokenizer;
+ var keymap = Ymacs_Keymap_CLanguages();
+ this.setTokenizer(new Ymacs_Tokenizer({ buffer: this, type: useDL ? "js-dynarchlib" : "js" }));
+ this.pushKeymap(keymap);
+ var was_paren_match = this.cmd("paren_match_mode", true);
+
+ return function() {
+ this.setTokenizer(tok);
+ this.popKeymap(keymap);
+ if (!was_paren_match)
+ this.cmd("paren_match_mode", false);
+ };
+
+});
+
+Ymacs_Buffer.newCommands({
+
+ javascript_dl_mode: Ymacs_Interactive(function() {
+ return this.cmd("javascript_mode", true);
+ }),
+
+ c_electric_block: Ymacs_Interactive(function() {
+ this.cmd("indent_line");
+ this.cmd("insert", "{\n\n}");
+ this.cmd("indent_line");
+ this.cmd("backward_line", 1);
+ this.cmd("indent_line");
+ }),
+
+ c_insert_and_indent: Ymacs_Interactive(function() {
+ var ret;
+ if ((ret = this.cmd("self_insert_command"))) {
+ this.cmd("indent_line");
+ return ret;
+ }
+ })
+
+});