You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by ch...@apache.org on 2013/07/22 08:58:04 UTC
svn commit: r1505607 [3/3] - in
/felix/trunk/webconsole-plugins/script-console: ./ src/ src/main/
src/main/appended-resources/ src/main/appended-resources/META-INF/
src/main/java/ src/main/java/org/ src/main/java/org/apache/
src/main/java/org/apache/fe...
Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/groovy.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/groovy.js?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/groovy.js (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/groovy/groovy.js Mon Jul 22 06:58:03 2013
@@ -0,0 +1,210 @@
+CodeMirror.defineMode("groovy", function(config) {
+ function words(str) {
+ var obj = {}, words = str.split(" ");
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
+ return obj;
+ }
+ var keywords = words(
+ "abstract as assert boolean break byte case catch char class const continue def default " +
+ "do double else enum extends final finally float for goto if implements import in " +
+ "instanceof int interface long native new package private protected public return " +
+ "short static strictfp super switch synchronized threadsafe throw throws transient " +
+ "try void volatile while");
+ var blockKeywords = words("catch class do else finally for if switch try while enum interface def");
+ var atoms = words("null true false this");
+
+ var curPunc;
+ function tokenBase(stream, state) {
+ var ch = stream.next();
+ if (ch == '"' || ch == "'") {
+ return startString(ch, stream, state);
+ }
+ if (/[\[\]{}\(\),;\:\.]/.test(ch)) {
+ curPunc = ch;
+ return null;
+ }
+ if (/\d/.test(ch)) {
+ stream.eatWhile(/[\w\.]/);
+ if (stream.eat(/eE/)) { stream.eat(/\+\-/); stream.eatWhile(/\d/); }
+ return "number";
+ }
+ if (ch == "/") {
+ if (stream.eat("*")) {
+ state.tokenize.push(tokenComment);
+ return tokenComment(stream, state);
+ }
+ if (stream.eat("/")) {
+ stream.skipToEnd();
+ return "comment";
+ }
+ if (expectExpression(state.lastToken)) {
+ return startString(ch, stream, state);
+ }
+ }
+ if (ch == "-" && stream.eat(">")) {
+ curPunc = "->";
+ return null;
+ }
+ if (/[+\-*&%=<>!?|\/~]/.test(ch)) {
+ stream.eatWhile(/[+\-*&%=<>|~]/);
+ return "operator";
+ }
+ stream.eatWhile(/[\w\$_]/);
+ if (ch == "@") { stream.eatWhile(/[\w\$_\.]/); return "meta"; }
+ if (state.lastToken == ".") return "property";
+ if (stream.eat(":")) { curPunc = "proplabel"; return "property"; }
+ var cur = stream.current();
+ if (atoms.propertyIsEnumerable(cur)) { return "atom"; }
+ if (keywords.propertyIsEnumerable(cur)) {
+ if (blockKeywords.propertyIsEnumerable(cur)) curPunc = "newstatement";
+ return "keyword";
+ }
+ return "variable";
+ }
+ tokenBase.isBase = true;
+
+ function startString(quote, stream, state) {
+ var tripleQuoted = false;
+ if (quote != "/" && stream.eat(quote)) {
+ if (stream.eat(quote)) tripleQuoted = true;
+ else return "string";
+ }
+ function t(stream, state) {
+ var escaped = false, next, end = !tripleQuoted;
+ while ((next = stream.next()) != null) {
+ if (next == quote && !escaped) {
+ if (!tripleQuoted) { break; }
+ if (stream.match(quote + quote)) { end = true; break; }
+ }
+ if (quote == '"' && next == "$" && !escaped && stream.eat("{")) {
+ state.tokenize.push(tokenBaseUntilBrace());
+ return "string";
+ }
+ escaped = !escaped && next == "\\";
+ }
+ if (end) state.tokenize.pop();
+ return "string";
+ }
+ state.tokenize.push(t);
+ return t(stream, state);
+ }
+
+ function tokenBaseUntilBrace() {
+ var depth = 1;
+ function t(stream, state) {
+ if (stream.peek() == "}") {
+ depth--;
+ if (depth == 0) {
+ state.tokenize.pop();
+ return state.tokenize[state.tokenize.length-1](stream, state);
+ }
+ } else if (stream.peek() == "{") {
+ depth++;
+ }
+ return tokenBase(stream, state);
+ }
+ t.isBase = true;
+ return t;
+ }
+
+ function tokenComment(stream, state) {
+ var maybeEnd = false, ch;
+ while (ch = stream.next()) {
+ if (ch == "/" && maybeEnd) {
+ state.tokenize.pop();
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return "comment";
+ }
+
+ function expectExpression(last) {
+ return !last || last == "operator" || last == "->" || /[\.\[\{\(,;:]/.test(last) ||
+ last == "newstatement" || last == "keyword" || last == "proplabel";
+ }
+
+ function Context(indented, column, type, align, prev) {
+ this.indented = indented;
+ this.column = column;
+ this.type = type;
+ this.align = align;
+ this.prev = prev;
+ }
+ function pushContext(state, col, type) {
+ return state.context = new Context(state.indented, col, type, null, state.context);
+ }
+ function popContext(state) {
+ var t = state.context.type;
+ if (t == ")" || t == "]" || t == "}")
+ state.indented = state.context.indented;
+ return state.context = state.context.prev;
+ }
+
+ // Interface
+
+ return {
+ startState: function(basecolumn) {
+ return {
+ tokenize: [tokenBase],
+ context: new Context((basecolumn || 0) - config.indentUnit, 0, "top", false),
+ indented: 0,
+ startOfLine: true,
+ lastToken: null
+ };
+ },
+
+ token: function(stream, state) {
+ var ctx = state.context;
+ if (stream.sol()) {
+ if (ctx.align == null) ctx.align = false;
+ state.indented = stream.indentation();
+ state.startOfLine = true;
+ // Automatic semicolon insertion
+ if (ctx.type == "statement" && !expectExpression(state.lastToken)) {
+ popContext(state); ctx = state.context;
+ }
+ }
+ if (stream.eatSpace()) return null;
+ curPunc = null;
+ var style = state.tokenize[state.tokenize.length-1](stream, state);
+ if (style == "comment") return style;
+ if (ctx.align == null) ctx.align = true;
+
+ if ((curPunc == ";" || curPunc == ":") && ctx.type == "statement") popContext(state);
+ // Handle indentation for {x -> \n ... }
+ else if (curPunc == "->" && ctx.type == "statement" && ctx.prev.type == "}") {
+ popContext(state);
+ state.context.align = false;
+ }
+ else if (curPunc == "{") pushContext(state, stream.column(), "}");
+ else if (curPunc == "[") pushContext(state, stream.column(), "]");
+ else if (curPunc == "(") pushContext(state, stream.column(), ")");
+ else if (curPunc == "}") {
+ while (ctx.type == "statement") ctx = popContext(state);
+ if (ctx.type == "}") ctx = popContext(state);
+ while (ctx.type == "statement") ctx = popContext(state);
+ }
+ else if (curPunc == ctx.type) popContext(state);
+ else if (ctx.type == "}" || ctx.type == "top" || (ctx.type == "statement" && curPunc == "newstatement"))
+ pushContext(state, stream.column(), "statement");
+ state.startOfLine = false;
+ state.lastToken = curPunc || style;
+ return style;
+ },
+
+ indent: function(state, textAfter) {
+ if (!state.tokenize[state.tokenize.length-1].isBase) return 0;
+ var firstChar = textAfter && textAfter.charAt(0), ctx = state.context;
+ if (ctx.type == "statement" && !expectExpression(state.lastToken)) ctx = ctx.prev;
+ var closing = firstChar == ctx.type;
+ if (ctx.type == "statement") return ctx.indented + (firstChar == "{" ? 0 : config.indentUnit);
+ else if (ctx.align) return ctx.column + (closing ? 0 : 1);
+ else return ctx.indented + (closing ? 0 : config.indentUnit);
+ },
+
+ electricChars: "{}"
+ };
+});
+
+CodeMirror.defineMIME("text/x-groovy", "groovy");
Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/javascript.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/javascript.js?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/javascript.js (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/codemirror/mode/javascript/javascript.js Mon Jul 22 06:58:03 2013
@@ -0,0 +1,476 @@
+// TODO actually recognize syntax of TypeScript constructs
+
+CodeMirror.defineMode("javascript", function(config, parserConfig) {
+ var indentUnit = config.indentUnit;
+ var statementIndent = parserConfig.statementIndent;
+ var jsonMode = parserConfig.json;
+ var isTS = parserConfig.typescript;
+
+ // Tokenizer
+
+ var keywords = function(){
+ function kw(type) {return {type: type, style: "keyword"};}
+ var A = kw("keyword a"), B = kw("keyword b"), C = kw("keyword c");
+ var operator = kw("operator"), atom = {type: "atom", style: "atom"};
+
+ var jsKeywords = {
+ "if": kw("if"), "while": A, "with": A, "else": B, "do": B, "try": B, "finally": B,
+ "return": C, "break": C, "continue": C, "new": C, "delete": C, "throw": C,
+ "var": kw("var"), "const": kw("var"), "let": kw("var"),
+ "function": kw("function"), "catch": kw("catch"),
+ "for": kw("for"), "switch": kw("switch"), "case": kw("case"), "default": kw("default"),
+ "in": operator, "typeof": operator, "instanceof": operator,
+ "true": atom, "false": atom, "null": atom, "undefined": atom, "NaN": atom, "Infinity": atom,
+ "this": kw("this")
+ };
+
+ // Extend the 'normal' keywords with the TypeScript language extensions
+ if (isTS) {
+ var type = {type: "variable", style: "variable-3"};
+ var tsKeywords = {
+ // object-like things
+ "interface": kw("interface"),
+ "class": kw("class"),
+ "extends": kw("extends"),
+ "constructor": kw("constructor"),
+
+ // scope modifiers
+ "public": kw("public"),
+ "private": kw("private"),
+ "protected": kw("protected"),
+ "static": kw("static"),
+
+ "super": kw("super"),
+
+ // types
+ "string": type, "number": type, "bool": type, "any": type
+ };
+
+ for (var attr in tsKeywords) {
+ jsKeywords[attr] = tsKeywords[attr];
+ }
+ }
+
+ return jsKeywords;
+ }();
+
+ var isOperatorChar = /[+\-*&%=<>!?|~^]/;
+
+ function chain(stream, state, f) {
+ state.tokenize = f;
+ return f(stream, state);
+ }
+
+ function nextUntilUnescaped(stream, end) {
+ var escaped = false, next;
+ while ((next = stream.next()) != null) {
+ if (next == end && !escaped)
+ return false;
+ escaped = !escaped && next == "\\";
+ }
+ return escaped;
+ }
+
+ // Used as scratch variables to communicate multiple values without
+ // consing up tons of objects.
+ var type, content;
+ function ret(tp, style, cont) {
+ type = tp; content = cont;
+ return style;
+ }
+
+ function jsTokenBase(stream, state) {
+ var ch = stream.next();
+ if (ch == '"' || ch == "'")
+ return chain(stream, state, jsTokenString(ch));
+ else if (/[\[\]{}\(\),;\:\.]/.test(ch))
+ return ret(ch);
+ else if (ch == "0" && stream.eat(/x/i)) {
+ stream.eatWhile(/[\da-f]/i);
+ return ret("number", "number");
+ }
+ else if (/\d/.test(ch) || ch == "-" && stream.eat(/\d/)) {
+ stream.match(/^\d*(?:\.\d*)?(?:[eE][+\-]?\d+)?/);
+ return ret("number", "number");
+ }
+ else if (ch == "/") {
+ if (stream.eat("*")) {
+ return chain(stream, state, jsTokenComment);
+ }
+ else if (stream.eat("/")) {
+ stream.skipToEnd();
+ return ret("comment", "comment");
+ }
+ else if (state.lastType == "operator" || state.lastType == "keyword c" ||
+ /^[\[{}\(,;:]$/.test(state.lastType)) {
+ nextUntilUnescaped(stream, "/");
+ stream.eatWhile(/[gimy]/); // 'y' is "sticky" option in Mozilla
+ return ret("regexp", "string-2");
+ }
+ else {
+ stream.eatWhile(isOperatorChar);
+ return ret("operator", null, stream.current());
+ }
+ }
+ else if (ch == "#") {
+ stream.skipToEnd();
+ return ret("error", "error");
+ }
+ else if (isOperatorChar.test(ch)) {
+ stream.eatWhile(isOperatorChar);
+ return ret("operator", null, stream.current());
+ }
+ else {
+ stream.eatWhile(/[\w\$_]/);
+ var word = stream.current(), known = keywords.propertyIsEnumerable(word) && keywords[word];
+ return (known && state.lastType != ".") ? ret(known.type, known.style, word) :
+ ret("variable", "variable", word);
+ }
+ }
+
+ function jsTokenString(quote) {
+ return function(stream, state) {
+ if (!nextUntilUnescaped(stream, quote))
+ state.tokenize = jsTokenBase;
+ return ret("string", "string");
+ };
+ }
+
+ function jsTokenComment(stream, state) {
+ var maybeEnd = false, ch;
+ while (ch = stream.next()) {
+ if (ch == "/" && maybeEnd) {
+ state.tokenize = jsTokenBase;
+ break;
+ }
+ maybeEnd = (ch == "*");
+ }
+ return ret("comment", "comment");
+ }
+
+ // Parser
+
+ var atomicTypes = {"atom": true, "number": true, "variable": true, "string": true, "regexp": true, "this": true};
+
+ function JSLexical(indented, column, type, align, prev, info) {
+ this.indented = indented;
+ this.column = column;
+ this.type = type;
+ this.prev = prev;
+ this.info = info;
+ if (align != null) this.align = align;
+ }
+
+ function inScope(state, varname) {
+ for (var v = state.localVars; v; v = v.next)
+ if (v.name == varname) return true;
+ }
+
+ function parseJS(state, style, type, content, stream) {
+ var cc = state.cc;
+ // Communicate our context to the combinators.
+ // (Less wasteful than consing up a hundred closures on every call.)
+ cx.state = state; cx.stream = stream; cx.marked = null, cx.cc = cc;
+
+ if (!state.lexical.hasOwnProperty("align"))
+ state.lexical.align = true;
+
+ while(true) {
+ var combinator = cc.length ? cc.pop() : jsonMode ? expression : statement;
+ if (combinator(type, content)) {
+ while(cc.length && cc[cc.length - 1].lex)
+ cc.pop()();
+ if (cx.marked) return cx.marked;
+ if (type == "variable" && inScope(state, content)) return "variable-2";
+ return style;
+ }
+ }
+ }
+
+ // Combinator utils
+
+ var cx = {state: null, column: null, marked: null, cc: null};
+ function pass() {
+ for (var i = arguments.length - 1; i >= 0; i--) cx.cc.push(arguments[i]);
+ }
+ function cont() {
+ pass.apply(null, arguments);
+ return true;
+ }
+ function register(varname) {
+ function inList(list) {
+ for (var v = list; v; v = v.next)
+ if (v.name == varname) return true;
+ return false;
+ }
+ var state = cx.state;
+ if (state.context) {
+ cx.marked = "def";
+ if (inList(state.localVars)) return;
+ state.localVars = {name: varname, next: state.localVars};
+ } else {
+ if (inList(state.globalVars)) return;
+ state.globalVars = {name: varname, next: state.globalVars};
+ }
+ }
+
+ // Combinators
+
+ var defaultVars = {name: "this", next: {name: "arguments"}};
+ function pushcontext() {
+ cx.state.context = {prev: cx.state.context, vars: cx.state.localVars};
+ cx.state.localVars = defaultVars;
+ }
+ function popcontext() {
+ cx.state.localVars = cx.state.context.vars;
+ cx.state.context = cx.state.context.prev;
+ }
+ function pushlex(type, info) {
+ var result = function() {
+ var state = cx.state, indent = state.indented;
+ if (state.lexical.type == "stat") indent = state.lexical.indented;
+ state.lexical = new JSLexical(indent, cx.stream.column(), type, null, state.lexical, info);
+ };
+ result.lex = true;
+ return result;
+ }
+ function poplex() {
+ var state = cx.state;
+ if (state.lexical.prev) {
+ if (state.lexical.type == ")")
+ state.indented = state.lexical.indented;
+ state.lexical = state.lexical.prev;
+ }
+ }
+ poplex.lex = true;
+
+ function expect(wanted) {
+ return function(type) {
+ if (type == wanted) return cont();
+ else if (wanted == ";") return pass();
+ else return cont(arguments.callee);
+ };
+ }
+
+ function statement(type) {
+ if (type == "var") return cont(pushlex("vardef"), vardef1, expect(";"), poplex);
+ if (type == "keyword a") return cont(pushlex("form"), expression, statement, poplex);
+ if (type == "keyword b") return cont(pushlex("form"), statement, poplex);
+ if (type == "{") return cont(pushlex("}"), block, poplex);
+ if (type == ";") return cont();
+ if (type == "if") return cont(pushlex("form"), expression, statement, poplex, maybeelse(cx.state.indented));
+ if (type == "function") return cont(functiondef);
+ if (type == "for") return cont(pushlex("form"), expect("("), pushlex(")"), forspec1, expect(")"),
+ poplex, statement, poplex);
+ if (type == "variable") return cont(pushlex("stat"), maybelabel);
+ if (type == "switch") return cont(pushlex("form"), expression, pushlex("}", "switch"), expect("{"),
+ block, poplex, poplex);
+ if (type == "case") return cont(expression, expect(":"));
+ if (type == "default") return cont(expect(":"));
+ if (type == "catch") return cont(pushlex("form"), pushcontext, expect("("), funarg, expect(")"),
+ statement, poplex, popcontext);
+ return pass(pushlex("stat"), expression, expect(";"), poplex);
+ }
+ function expression(type) {
+ return expressionInner(type, false);
+ }
+ function expressionNoComma(type) {
+ return expressionInner(type, true);
+ }
+ function expressionInner(type, noComma) {
+ var maybeop = noComma ? maybeoperatorNoComma : maybeoperatorComma;
+ if (atomicTypes.hasOwnProperty(type)) return cont(maybeop);
+ if (type == "function") return cont(functiondef);
+ if (type == "keyword c") return cont(noComma ? maybeexpressionNoComma : maybeexpression);
+ if (type == "(") return cont(pushlex(")"), maybeexpression, expect(")"), poplex, maybeop);
+ if (type == "operator") return cont(noComma ? expressionNoComma : expression);
+ if (type == "[") return cont(pushlex("]"), commasep(expressionNoComma, "]"), poplex, maybeop);
+ if (type == "{") return cont(pushlex("}"), commasep(objprop, "}"), poplex, maybeop);
+ return cont();
+ }
+ function maybeexpression(type) {
+ if (type.match(/[;\}\)\],]/)) return pass();
+ return pass(expression);
+ }
+ function maybeexpressionNoComma(type) {
+ if (type.match(/[;\}\)\],]/)) return pass();
+ return pass(expressionNoComma);
+ }
+
+ function maybeoperatorComma(type, value) {
+ if (type == ",") return cont(expression);
+ return maybeoperatorNoComma(type, value, maybeoperatorComma);
+ }
+ function maybeoperatorNoComma(type, value, me) {
+ if (!me) me = maybeoperatorNoComma;
+ if (type == "operator") {
+ if (/\+\+|--/.test(value)) return cont(me);
+ if (value == "?") return cont(expression, expect(":"), expression);
+ return cont(expression);
+ }
+ if (type == ";") return;
+ if (type == "(") return cont(pushlex(")", "call"), commasep(expressionNoComma, ")"), poplex, me);
+ if (type == ".") return cont(property, me);
+ if (type == "[") return cont(pushlex("]"), expression, expect("]"), poplex, me);
+ }
+ function maybelabel(type) {
+ if (type == ":") return cont(poplex, statement);
+ return pass(maybeoperatorComma, expect(";"), poplex);
+ }
+ function property(type) {
+ if (type == "variable") {cx.marked = "property"; return cont();}
+ }
+ function objprop(type, value) {
+ if (type == "variable") {
+ cx.marked = "property";
+ if (value == "get" || value == "set") return cont(getterSetter);
+ } else if (type == "number" || type == "string") {
+ cx.marked = type + " property";
+ }
+ if (atomicTypes.hasOwnProperty(type)) return cont(expect(":"), expressionNoComma);
+ }
+ function getterSetter(type) {
+ if (type == ":") return cont(expression);
+ if (type != "variable") return cont(expect(":"), expression);
+ cx.marked = "property";
+ return cont(functiondef);
+ }
+ function commasep(what, end) {
+ function proceed(type) {
+ if (type == ",") {
+ var lex = cx.state.lexical;
+ if (lex.info == "call") lex.pos = (lex.pos || 0) + 1;
+ return cont(what, proceed);
+ }
+ if (type == end) return cont();
+ return cont(expect(end));
+ }
+ return function(type) {
+ if (type == end) return cont();
+ else return pass(what, proceed);
+ };
+ }
+ function block(type) {
+ if (type == "}") return cont();
+ return pass(statement, block);
+ }
+ function maybetype(type) {
+ if (type == ":") return cont(typedef);
+ return pass();
+ }
+ function typedef(type) {
+ if (type == "variable"){cx.marked = "variable-3"; return cont();}
+ return pass();
+ }
+ function vardef1(type, value) {
+ if (type == "variable") {
+ register(value);
+ return isTS ? cont(maybetype, vardef2) : cont(vardef2);
+ }
+ return pass();
+ }
+ function vardef2(type, value) {
+ if (value == "=") return cont(expressionNoComma, vardef2);
+ if (type == ",") return cont(vardef1);
+ }
+ function maybeelse(indent) {
+ return function(type, value) {
+ if (type == "keyword b" && value == "else") {
+ cx.state.lexical = new JSLexical(indent, 0, "form", null, cx.state.lexical);
+ return cont(statement, poplex);
+ }
+ return pass();
+ };
+ }
+ function forspec1(type) {
+ if (type == "var") return cont(vardef1, expect(";"), forspec2);
+ if (type == ";") return cont(forspec2);
+ if (type == "variable") return cont(formaybein);
+ return pass(expression, expect(";"), forspec2);
+ }
+ function formaybein(_type, value) {
+ if (value == "in") return cont(expression);
+ return cont(maybeoperatorComma, forspec2);
+ }
+ function forspec2(type, value) {
+ if (type == ";") return cont(forspec3);
+ if (value == "in") return cont(expression);
+ return pass(expression, expect(";"), forspec3);
+ }
+ function forspec3(type) {
+ if (type != ")") cont(expression);
+ }
+ function functiondef(type, value) {
+ if (type == "variable") {register(value); return cont(functiondef);}
+ if (type == "(") return cont(pushlex(")"), pushcontext, commasep(funarg, ")"), poplex, statement, popcontext);
+ }
+ function funarg(type, value) {
+ if (type == "variable") {register(value); return isTS ? cont(maybetype) : cont();}
+ }
+
+ // Interface
+
+ return {
+ startState: function(basecolumn) {
+ return {
+ tokenize: jsTokenBase,
+ lastType: null,
+ cc: [],
+ lexical: new JSLexical((basecolumn || 0) - indentUnit, 0, "block", false),
+ localVars: parserConfig.localVars,
+ globalVars: parserConfig.globalVars,
+ context: parserConfig.localVars && {vars: parserConfig.localVars},
+ indented: 0
+ };
+ },
+
+ token: function(stream, state) {
+ if (stream.sol()) {
+ if (!state.lexical.hasOwnProperty("align"))
+ state.lexical.align = false;
+ state.indented = stream.indentation();
+ }
+ if (state.tokenize != jsTokenComment && stream.eatSpace()) return null;
+ var style = state.tokenize(stream, state);
+ if (type == "comment") return style;
+ state.lastType = type == "operator" && (content == "++" || content == "--") ? "incdec" : type;
+ return parseJS(state, style, type, content, stream);
+ },
+
+ indent: function(state, textAfter) {
+ if (state.tokenize == jsTokenComment) return CodeMirror.Pass;
+ if (state.tokenize != jsTokenBase) return 0;
+ var firstChar = textAfter && textAfter.charAt(0), lexical = state.lexical;
+ if (lexical.type == "stat" && firstChar == "}") lexical = lexical.prev;
+ if (statementIndent && lexical.type == ")" && lexical.prev.type == "stat")
+ lexical = lexical.prev;
+ var type = lexical.type, closing = firstChar == type;
+
+ if (type == "vardef") return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? 4 : 0);
+ else if (type == "form" && firstChar == "{") return lexical.indented;
+ else if (type == "form") return lexical.indented + indentUnit;
+ else if (type == "stat")
+ return lexical.indented + (state.lastType == "operator" || state.lastType == "," ? statementIndent || indentUnit : 0);
+ else if (lexical.info == "switch" && !closing && parserConfig.doubleIndentSwitch != false)
+ return lexical.indented + (/^(?:case|default)\b/.test(textAfter) ? indentUnit : 2 * indentUnit);
+ else if (lexical.align) return lexical.column + (closing ? 0 : 1);
+ else return lexical.indented + (closing ? 0 : indentUnit);
+ },
+
+ electricChars: ":{}",
+ blockCommentStart: jsonMode ? null : "/*",
+ blockCommentEnd: jsonMode ? null : "*/",
+ lineComment: jsonMode ? null : "//",
+
+ jsonMode: jsonMode
+ };
+});
+
+CodeMirror.defineMIME("text/javascript", "javascript");
+CodeMirror.defineMIME("text/ecmascript", "javascript");
+CodeMirror.defineMIME("application/javascript", "javascript");
+CodeMirror.defineMIME("application/ecmascript", "javascript");
+CodeMirror.defineMIME("application/json", {name: "javascript", json: true});
+CodeMirror.defineMIME("application/x-json", {name: "javascript", json: true});
+CodeMirror.defineMIME("text/typescript", { name: "javascript", typescript: true });
+CodeMirror.defineMIME("application/typescript", { name: "javascript", typescript: true });
Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.css
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.css?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.css (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.css Mon Jul 22 06:58:03 2013
@@ -0,0 +1,4 @@
+.CodeMirror {
+ /*border-top: 1px solid black;*/
+ border-bottom: 1px solid black;
+}
\ No newline at end of file
Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.js
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.js?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.js (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/res/ui/script-console.js Mon Jul 22 06:58:03 2013
@@ -0,0 +1,104 @@
+//Codemirror editor
+var inputEditor
+var outputEditor
+
+function sendData(url, data) {
+ $.ajax({
+ type:"POST",
+ url:url,
+ data:data,
+// dataType:"json",
+ timeout:30000, //In millis
+ beforeSend:function () {
+ $('#ajaxSpinner').show();
+ },
+ /* error: function() {
+ $('#status').text('Update failed�try again.').slideDown('slow');
+ },*/
+ complete:function () {
+ $('#ajaxSpinner').hide();
+ },
+ success:function (data) {
+ renderData(data)
+ }
+ });
+}
+
+function renderData(data){
+ $('#code-output').show();
+ outputEditor.setValue(data)
+}
+
+function setUpCodeMirror() {
+ CodeMirror.modeURL = pluginRoot + "/res/ui/codemirror/mode/%N/%N.js";
+ inputEditor = CodeMirror.fromTextArea(document.getElementById("code"), {
+ lineNumbers:true,
+ extraKeys: {
+ 'Ctrl-Q':clearOutput,
+ 'Ctrl-F9':executeScript
+ }
+ });
+ outputEditor = CodeMirror.fromTextArea(document.getElementById("result"), {
+ lineNumbers:true,
+ readOnly:"nocursor"
+ });
+}
+
+function updateWithOption(opt){
+ setLangMode(inputEditor,getProp(opt,'langMode'))
+ $('[name=lang]').val(opt.val())
+}
+
+function setLangMode(editor, modeName) {
+ if(!modeName){
+ modeName = "text/plain"
+ }else{
+ CodeMirror.autoLoadMode(inputEditor, modeName);
+ }
+ editor.setOption("mode", modeName);
+}
+
+function getProp(obj,propName){
+ if(obj != null){
+ return obj.prop ? obj.prop(propName) : obj.attr(propName)
+ }
+}
+
+function setUpLangOptions() {
+ var codeLang = $('#codeLang')
+ var options = getProp(codeLang,'options');
+ codeLang.empty()
+
+ for(var i in scriptConfig){
+ var config = scriptConfig[i]
+ var opt = new Option(config.langName,config.langCode);
+ if(config.mode){
+ opt.langMode = config.mode;
+ }
+ options[options.length] = opt
+ }
+ codeLang.change(function(){
+ var opt = $(this).find(":selected");
+ updateWithOption(opt)
+ });
+
+ codeLang.find('option:eq(0)').attr('selected','selected')
+ updateWithOption($(options[0]))
+}
+
+function executeScript(){
+ inputEditor.save() //Copy the contents to textarea form field
+ sendData(pluginRoot, $("#consoleForm").serialize());
+}
+
+function clearOutput(){
+ outputEditor.setValue('')
+}
+
+$(document).ready(function () {
+ $("#executeButton").click(executeScript);
+ $('#ajaxSpinner').hide();
+ $('#code-output').hide();
+ setUpCodeMirror();
+ setUpLangOptions();
+});
Added: felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/script-console.html
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/script-console.html?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/script-console.html (added)
+++ felix/trunk/webconsole-plugins/script-console/src/main/resources/templates/script-console.html Mon Jul 22 06:58:03 2013
@@ -0,0 +1,34 @@
+<script type="text/javascript" src="${pluginRoot}/res/ui/codemirror/lib/codemirror.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/codemirror/addon/runmode/runmode.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/codemirror/addon/mode/loadmode.js"></script>
+<script type="text/javascript" src="${pluginRoot}/res/ui/script-console.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+var scriptConfig = ${__scriptConfig__};
+// ]]>
+</script>
+
+<!-- status line -->
+<p class="statline"> </p>
+<div class="ui-widget-header ">
+ <img id="ajaxSpinner" src="${appRoot}/res/imgs/loading.gif" tile="Working..." />
+ <button type="button" id="executeButton">${console.execute}</button>
+ <button type="button" id="langButton">${console.lang}</button>
+ <select id="codeLang">
+ <option></option>
+ </select>
+</div>
+<div id="splitter" >
+ <div id="code-input">
+ <form method="post" action="${pluginRoot}" id="consoleForm">
+ <textarea id="code" name="code"
+ style="width: 90%; height: 7em; "></textarea>
+ <input type="hidden" name="client" value="webconsole" />
+ <input type="hidden" name="lang" value="" />
+ </form>
+ </div>
+ <div id="code-output">
+ <textarea id="result" style="width: 90%;" readonly="yes"></textarea>
+ </div>
+</div>
+
Added: felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ITScriptConsolePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ITScriptConsolePlugin.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ITScriptConsolePlugin.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ITScriptConsolePlugin.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.integration;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.HttpEntity;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.entity.mime.MultipartEntity;
+import org.apache.http.entity.mime.content.ContentBody;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.sling.testing.tools.http.RequestBuilder;
+import org.apache.sling.testing.tools.http.RequestExecutor;
+import org.junit.Test;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ITScriptConsolePlugin
+{
+ private DefaultHttpClient httpClient = new DefaultHttpClient();
+ private RequestExecutor executor = new RequestExecutor(httpClient);
+
+ @Test
+ public void testScriptExecution() throws Exception
+ {
+ //Somehow multipart data based invocation does not work in with old webconsole
+// execute(new InputStreamBody(getClass().getResourceAsStream("/test.groovy"),
+// "test.groovy"));
+// execute(new StringBody("def a = 2+2; assert a == 4;"));
+ InputStream is = getClass().getResourceAsStream("/test.groovy");
+ try{
+ execute2(IOUtils.toString(is, "utf-8"));
+ }finally {
+ IOUtils.closeQuietly(is);
+ }
+ execute2("def a = 2+2; assert a == 4;");
+ }
+
+ private void execute(ContentBody code) throws Exception
+ {
+ RequestBuilder rb = new RequestBuilder(ServerConfiguration.getServerUrl());
+
+ final MultipartEntity entity = new MultipartEntity();
+ // Add Sling POST options
+ entity.addPart("lang", new StringBody("groovy"));
+ entity.addPart("code", code);
+ executor.execute(
+ rb.buildPostRequest("/system/console/sc").withEntity(entity).withCredentials(
+ "admin", "admin")).assertStatus(200);
+ }
+
+ private void execute2(String code) throws Exception
+ {
+ RequestBuilder rb = new RequestBuilder(ServerConfiguration.getServerUrl());
+
+ List<NameValuePair> params = new ArrayList<NameValuePair>();
+ params.add(new BasicNameValuePair("lang","groovy"));
+ params.add(new BasicNameValuePair("code",code));
+
+ final HttpEntity entity = new UrlEncodedFormEntity(params);
+ // Add Sling POST options
+ executor.execute(
+ rb.buildPostRequest("/system/console/sc")
+ .withEntity(entity)
+ .withCredentials("admin", "admin"))
+ .assertStatus(200);
+ }
+
+}
Added: felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ServerConfiguration.java
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ServerConfiguration.java?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ServerConfiguration.java (added)
+++ felix/trunk/webconsole-plugins/script-console/src/test/java/org/apache/felix/webconsole/plugins/scriptconsole/integration/ServerConfiguration.java Mon Jul 22 06:58:03 2013
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.felix.webconsole.plugins.scriptconsole.integration;
+
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.OptionUtils;
+
+import java.io.File;
+
+import static org.ops4j.pax.exam.CoreOptions.*;
+
+public class ServerConfiguration
+{
+
+ // the name of the system property providing the bundle file to be installed and tested
+ protected static final String BUNDLE_JAR_SYS_PROP = "project.bundle.file";
+
+ // the name of the system property which captures the jococo coverage agent command
+ //if specified then agent would be specified otherwise ignored
+ protected static final String COVERAGE_COMMAND = "coverage.command";
+
+ //Name of the property for port of server
+ public static final String HTTP_PORT_PROP = "http.port";
+
+ public static final String HTTP_SERVER__URL_PROP = "serverUrl";
+
+ // the default bundle jar file name
+ protected static final String BUNDLE_JAR_DEFAULT = "target/scriptconsole.jar";
+
+ // the JVM option to set to enable remote debugging
+ @SuppressWarnings("UnusedDeclaration")
+ protected static final String DEBUG_VM_OPTION = "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=31313";
+
+ // the actual JVM option set, extensions may implement a static
+ // initializer overwriting this value to have the configuration()
+ // method include it when starting the OSGi framework JVM
+ protected static String paxRunnerVmOption = null;
+// protected static String paxRunnerVmOption = DEBUG_VM_OPTION;
+
+ protected static String DEFAULT_PORT = "8080";
+
+ @Configuration
+ public Option[] config()
+ {
+ final String bundleFileName = System.getProperty(BUNDLE_JAR_SYS_PROP,
+ BUNDLE_JAR_DEFAULT);
+ final File bundleFile = new File(bundleFileName);
+ if (!bundleFile.canRead())
+ {
+ throw new IllegalArgumentException("Cannot read from bundle file "
+ + bundleFileName + " specified in the " + BUNDLE_JAR_SYS_PROP
+ + " system property");
+ }
+ Option[] base = options(
+ // the current project (the bundle under test)
+ CoreOptions.bundle(bundleFile.toURI().toString()),
+ mavenBundle("org.ops4j.pax.logging", "pax-logging-api", "1.7.0").startLevel(2),
+ mavenBundle("org.ops4j.pax.logging", "pax-logging-service", "1.7.0").startLevel(2),
+ mavenBundle("org.apache.felix", "org.apache.felix.configadmin").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.http.jetty").versionAsInProject(),
+ mavenBundle("org.apache.felix", "org.apache.felix.webconsole").versionAsInProject(),
+ mavenBundle("commons-io", "commons-io").versionAsInProject(),
+ wrappedBundle(mavenBundle("commons-fileupload", "commons-fileupload").versionAsInProject()),
+ wrappedBundle(mavenBundle("org.json", "json").versionAsInProject()),
+ mavenBundle("org.codehaus.groovy", "groovy-all", "2.1.0"),
+ frameworkProperty("osgi.clean").value("true"),
+// systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),
+ systemProperty("pax.exam.osgi.unresolved.fail").value("fail"),
+ systemProperty("org.osgi.service.http.port").value(getServerPort()),
+ cleanCaches(),
+ addCodeCoverageOption());
+ final Option vmOption = (paxRunnerVmOption != null) ? CoreOptions.vmOption(paxRunnerVmOption)
+ : null;
+ return OptionUtils.combine(base, vmOption);
+ }
+
+ private static String getServerPort()
+ {
+ return System.getProperty(HTTP_PORT_PROP, DEFAULT_PORT);
+ }
+
+ private Option addCodeCoverageOption()
+ {
+ String coverageCommand = System.getProperty(COVERAGE_COMMAND);
+ if (coverageCommand != null)
+ {
+ return CoreOptions.vmOption(coverageCommand);
+ }
+ return null;
+ }
+
+ public static String getServerUrl()
+ {
+ String serverUrl = System.getProperty(HTTP_SERVER__URL_PROP);
+ if (serverUrl != null)
+ {
+ return serverUrl;
+ }
+
+ return String.format("http://localhost:%s", getServerPort());
+ }
+}
Added: felix/trunk/webconsole-plugins/script-console/src/test/resources/test.groovy
URL: http://svn.apache.org/viewvc/felix/trunk/webconsole-plugins/script-console/src/test/resources/test.groovy?rev=1505607&view=auto
==============================================================================
--- felix/trunk/webconsole-plugins/script-console/src/test/resources/test.groovy (added)
+++ felix/trunk/webconsole-plugins/script-console/src/test/resources/test.groovy Mon Jul 22 06:58:03 2013
@@ -0,0 +1,2 @@
+def httpService = osgi.getService(org.osgi.service.http.HttpService.class)
+assert httpService
\ No newline at end of file