From ba420420133b32e686466da201a8543eda70ebcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gast=C3=B3n=20Kleiman?= Date: Fri, 4 Feb 2011 10:36:26 +0800 Subject: [PATCH] add C/C++ syntax highlighting --- Makefile.dryice.js | 4 +- demo/demo.js | 14 ++- editor.html | 17 +++ lib/ace/mode/c_cpp.js | 128 +++++++++++++++++++ lib/ace/mode/c_cpp_highlight_rules.js | 174 ++++++++++++++++++++++++++ 5 files changed, 333 insertions(+), 4 deletions(-) create mode 100644 lib/ace/mode/c_cpp.js create mode 100644 lib/ace/mode/c_cpp_highlight_rules.js diff --git a/Makefile.dryice.js b/Makefile.dryice.js index 28e23404..baeb43e7 100755 --- a/Makefile.dryice.js +++ b/Makefile.dryice.js @@ -169,7 +169,7 @@ copy({ // create modes project.assmeAllFilesLoaded(); -["css", "html", "javascript", "php", "python", "xml", "ruby", "java"].forEach(function(mode) { +["css", "html", "javascript", "php", "python", "xml", "ruby", "java", "c_cpp"].forEach(function(mode) { copy({ source: [ copy.source.commonjs({ @@ -314,4 +314,4 @@ copy({ //copy({ // source: aceHome + '/demo/logo.png', // dest: "build/demo/logo.png" -//}); \ No newline at end of file +//}); diff --git a/demo/demo.js b/demo/demo.js index 958e75e5..6ad4a8d1 100644 --- a/demo/demo.js +++ b/demo/demo.js @@ -54,6 +54,7 @@ exports.launch = function(env) { var PhpMode = require("ace/mode/php").Mode; var JavaMode = require("ace/mode/java").Mode; var RubyMode = require("ace/mode/ruby").Mode; + var CCPPMode = require("ace/mode/c_cpp").Mode; var TextMode = require("ace/mode/text").Mode; var UndoManager = require("ace/undomanager").UndoManager; @@ -103,7 +104,7 @@ exports.launch = function(env) { docs.php = new EditSession(document.getElementById("phptext").innerHTML); docs.php.setMode(new PhpMode()); docs.php.setUndoManager(new UndoManager()); - + docs.java = new EditSession(document.getElementById("javatext").innerHTML); docs.java.setMode(new JavaMode()); docs.java.setUndoManager(new UndoManager()); @@ -112,6 +113,9 @@ exports.launch = function(env) { docs.ruby.setMode(new RubyMode()); docs.ruby.setUndoManager(new UndoManager()); + docs.c_cpp = new EditSession(document.getElementById("cpptext").innerHTML); + docs.c_cpp.setMode(new CCPPMode()); + docs.c_cpp.setUndoManager(new UndoManager()); var container = document.getElementById("editor"); env.editor = new Editor(new Renderer(container, theme)); @@ -125,7 +129,8 @@ exports.launch = function(env) { python: new PythonMode(), php: new PhpMode(), java: new JavaMode(), - ruby: new RubyMode() + ruby: new RubyMode(), + c_cpp: new CCPPMode() }; function getMode() { @@ -164,6 +169,9 @@ exports.launch = function(env) { else if (mode instanceof RubyMode) { modeEl.value = "ruby"; } + else if (mode instanceof CCPPMode) { + modeEl.value = "c_cpp"; + } else { modeEl.value = "text"; } @@ -293,6 +301,8 @@ exports.launch = function(env) { mode = "java"; } else if (/^.*\.rb$/i.test(file.name)) { mode = "ruby"; + } else if (/^.*\.(c|cpp|h|hpp|cxx)$/i.test(file.name)) { + mode = "c_cpp"; } env.editor.onTextInput(reader.result); diff --git a/editor.html b/editor.html index e97eee32..35166209 100644 --- a/editor.html +++ b/editor.html @@ -21,6 +21,7 @@ + @@ -76,6 +77,7 @@ + @@ -221,6 +223,21 @@ def fact(n) end puts fact(ARGV[0].to_i) + + + diff --git a/lib/ace/mode/c_cpp.js b/lib/ace/mode/c_cpp.js new file mode 100644 index 00000000..986afbad --- /dev/null +++ b/lib/ace/mode/c_cpp.js @@ -0,0 +1,128 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * Gastón Kleiman + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var TextMode = require("ace/mode/text").Mode; +var Tokenizer = require("ace/tokenizer").Tokenizer; +var c_cppHighlightRules = require("ace/mode/c_cpp_highlight_rules").c_cppHighlightRules; +var MatchingBraceOutdent = require("ace/mode/matching_brace_outdent").MatchingBraceOutdent; +var Range = require("ace/range").Range; + +var Mode = function() { + this.$tokenizer = new Tokenizer(new c_cppHighlightRules().getRules()); + this.$outdent = new MatchingBraceOutdent(); +}; +oop.inherits(Mode, TextMode); + +(function() { + + this.toggleCommentLines = function(state, doc, startRow, endRow) { + var outdent = true; + var outentedRows = []; + var re = /^(\s*)\/\//; + + for (var i=startRow; i<= endRow; i++) { + if (!re.test(doc.getLine(i))) { + outdent = false; + break; + } + } + + if (outdent) { + var deleteRange = new Range(0, 0, 0, 0); + for (var i=startRow; i<= endRow; i++) + { + var line = doc.getLine(i).replace(re, "$1"); + deleteRange.start.row = i; + deleteRange.end.row = i; + deleteRange.end.column = line.length + 2; + doc.replace(deleteRange, line); + } + return -2; + } + else { + return doc.indentRows(startRow, endRow, "//"); + } + }; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + + var tokenizedLine = this.$tokenizer.getLineTokens(line, state); + var tokens = tokenizedLine.tokens; + var endState = tokenizedLine.state; + + if (tokens.length && tokens[tokens.length-1].type == "comment") { + return indent; + } + + if (state == "start") { + var match = line.match(/^.*[\{\(\[]\s*$/); + if (match) { + indent += tab; + } + } else if (state == "doc-start") { + if (endState == "start") { + return ""; + } + var match = line.match(/^\s*(\/?)\*/); + if (match) { + if (match[1]) { + indent += " "; + } + indent += "* "; + } + } + + return indent; + }; + + this.checkOutdent = function(state, line, input) { + return this.$outdent.checkOutdent(line, input); + }; + + this.autoOutdent = function(state, doc, row) { + return this.$outdent.autoOutdent(doc, row); + }; + +}).call(Mode.prototype); + +exports.Mode = Mode; +}); diff --git a/lib/ace/mode/c_cpp_highlight_rules.js b/lib/ace/mode/c_cpp_highlight_rules.js new file mode 100644 index 00000000..96d1a428 --- /dev/null +++ b/lib/ace/mode/c_cpp_highlight_rules.js @@ -0,0 +1,174 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (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.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Ajax.org Code Editor (ACE). + * + * The Initial Developer of the Original Code is + * Ajax.org B.V. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Fabian Jakobs + * Gastón Kleiman + * + * Based on Bespin's C/C++ Syntax Plugin by Marc McIntyre. + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +define(function(require, exports, module) { + +var oop = require("pilot/oop"); +var lang = require("pilot/lang"); +var DocCommentHighlightRules = require("ace/mode/doc_comment_highlight_rules").DocCommentHighlightRules; +var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; + +c_cppHighlightRules = function() { + + var docComment = new DocCommentHighlightRules(); + + var keywords = lang.arrayToMap( + ("and|double|not_eq|throw|and_eq|dynamic_cast|operator|true|" + + "asm|else|or|try|auto|enum|or_eq|typedef|bitand|explicit|private|" + + "typeid|bitor|extern|protected|typename|bool|false|public|union|" + + "break|float|register|unsigned|case|fro|reinterpret-cast|using|catch|" + + "friend|return|virtual|char|goto|short|void|class|if|signed|volatile|" + + "compl|inline|sizeof|wchar_t|const|int|static|while|const-cast|long|" + + "static_cast|xor|continue|mutable|struct|xor_eq|default|namespace|" + + "switch|delete|new|template|do|not|this|for").split("|") + ); + + var buildinConstants = lang.arrayToMap( + ("NULL").split("|") + ); + + // regexp must not have capturing parentheses. Use (?:) instead. + // regexps are ordered -> the first match is used + + this.$rules = { + "start" : [ + { + token : "comment", + regex : "\\/\\/.*$" + }, + docComment.getStartRule("doc-start"), + { + token : "comment", // multi line comment + regex : "\\/\\*", + next : "comment" + }, { + token : "string", // single line + regex : '["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]' + }, { + token : "string", // multi line string start + regex : '["].*\\\\$', + next : "qqstring" + }, { + token : "string", // single line + regex : "['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']" + }, { + token : "string", // multi line string start + regex : "['].*\\\\$", + next : "qstring" + }, { + token : "constant.numeric", // hex + regex : "0[xX][0-9a-fA-F]+\\b" + }, { + token : "constant.numeric", // float + regex : "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b" + }, { + token : "constant", // + regex : "<[a-zA-Z0-9.]+>" + }, { + token : "keyword", // pre-compiler directivs + regex : "(?:#include|#pragma|#line|#define|#undef|#ifdef|#else|#elif|#endif|#ifndef)" + }, { + token : function(value) { + if (value == "this") + return "variable.language"; + else if (keywords[value]) + return "keyword"; + else if (buildinConstants[value]) + return "constant.language"; + else if (value == "debugger") + return "invalid.deprecated"; + else + return "identifier"; + }, + regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" + }, { + token : "keyword.operator", + regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|==|=|!=|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|new|delete|typeof|void)" + }, { + token : "lparen", + regex : "[[({]" + }, { + token : "rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "comment" : [ + { + token : "comment", // closing comment + regex : ".*?\\*\\/", + next : "start" + }, { + token : "comment", // comment spanning whole line + regex : ".+" + } + ], + "qqstring" : [ + { + token : "string", + regex : '(?:(?:\\\\.)|(?:[^"\\\\]))*?"', + next : "start" + }, { + token : "string", + regex : '.+' + } + ], + "qstring" : [ + { + token : "string", + regex : "(?:(?:\\\\.)|(?:[^'\\\\]))*?'", + next : "start" + }, { + token : "string", + regex : '.+' + } + ] + }; + + this.addRules(docComment.getRules(), "doc-"); + this.$rules["doc-start"][0].next = "start"; +}; + +oop.inherits(c_cppHighlightRules, TextHighlightRules); + +exports.c_cppHighlightRules = c_cppHighlightRules; +});