Syntax: Diff
jQuery.Syntax Diff
diff --git a/ex.ruby.html b/ex.ruby.html
index a02a04e..7d42db0 100644
--- a/ex.ruby.html
+++ b/ex.ruby.html
@@ -21,6 +21,8 @@
<body>
<h1>Syntax: Ruby</h1>
+ <h2>Ruby Script #1</h2>
+
<pre class="ruby">#!/usr/bin/env ruby
# Copyright (c) 2009 Samuel Williams. Released under the GNU GPLv3.
@@ -104,5 +106,257 @@ end
# RExec daemon runner
Server.daemonize</pre>
+ <h2>Ruby Script #2</h2>
+
+ <pre class="ruby">#!/usr/bin/env ruby
+# Simple Operator Expression Parser
+
+require 'set'
+
+DEBUG = false
+
+class Array
+ def map_to(with)
+ r = {}
+
+ each_with_index { |v,i| r[v] = with[i] }
+
+ return r
+ end
+end
+
+module Expression
+ class Context
+ def initialize(operators, values)
+ @values = values
+ @operators = operators
+ end
+
+ def value_of (key)
+ @values[key]
+ end
+
+ def call (op, args)
+ @operators.call(op, args)
+ end
+ end
+
+ class Constant
+ def initialize(value)
+ @value = value
+ end
+
+ def evaluate (ctx)
+ return @value
+ end
+ end
+
+ class Identifier
+ def initialize(name)
+ @name = name
+ end
+
+ def evaluate (ctx)
+ ctx.value_of(@name)
+ end
+ end
+
+ class Operator
+ def initialize(name, args = [])
+ @name = name
+ @args = args
+ end
+
+ def name
+ @name
+ end
+
+ def evaluate (ctx)
+ ctx.call(@name, @args.collect { |a| a.evaluate(ctx) })
+ end
+
+ def args
+ @args
+ end
+ end
+
+ class Brackets
+ def initialize(node)
+ @node = node
+ end
+
+ def evaluate (ctx)
+ @node.evaluate(ctx)
+ end
+ end
+
+ class Parser
+ def initialize(ops, expr)
+ @identifiers = []
+ @operators = ops
+
+ # Tokens and expressions line up
+ @expressions = []
+ @tokens = []
+
+ @top = nil
+
+ parse(expr)
+ end
+
+ def evaluate (ctx)
+ @expressions.collect do |expr|
+ expr != nil ? expr.evaluate(ctx) : nil
+ end
+ end
+
+ def identifiers
+ @identifiers
+ end
+
+ def tokens
+ @tokens
+ end
+ private
+ def parse(expr)
+ symbols = @operators.keys + ["(", ")"]
+ tokenizer = Regexp.union(Regexp.union(*symbols), /[A-Z]+/)
+
+ @tokens = expr.scan(tokenizer)
+ @expressions = [nil] * @tokens.size
+
+ @identifiers = Set.new(expr.scan(/[A-Z]+/))
+
+ @top, i = process_expression
+
+ if DEBUG
+ puts "Processed #{i} tokens..."
+ puts "Tokens: " + @tokens.join(" ")
+ puts @top.inspect
+ puts @expressions.inspect
+ end
+ end
+
+ def process_expression(i = 0)
+ ast = []
+ ops = {}
+ while i < @tokens.size
+ t = @tokens[i]
+
+ if t == "("
+ result, i = process_expression(i+1)
+ ast += result
+ elsif t == ")"
+ break
+ else
+ result = process_token(i)
+ ast << result
+ end
+
+ if result.class == Operator
+ ops[result.name] ||= []
+ # Store the index
+ ops[result.name] << (ast.size - 1)
+ end
+
+ i += 1
+ end
+
+ #puts ast.inspect
+
+ # We need to sort the list of operators now
+ # [c, infix, prefix, c]
+
+ @operators.order.each do |name|
+ op_kind = @operators.kind(name)
+ next unless ops[name]
+
+ ops[name].each do |loc|
+ op = ast[loc]
+
+ if op_kind == :prefix
+ rhs = find_subexpression(ast, loc, RHS_SEARCH)
+ op.args << ast[rhs]
+ ast[rhs] = nil
+ elsif op_kind == :infix
+ lhs = find_subexpression(ast, loc, LHS_SEARCH)
+ rhs = find_subexpression(ast, loc, RHS_SEARCH)
+ op.args << ast[lhs]
+ op.args << ast[rhs]
+ ast[lhs] = ast[rhs] = nil
+ elsif op_kind == :postfix
+ lhs = find_subexpression(ast, loc, LHS_SEARCH)
+ op.args << ast[lhs]
+ ast[rhs] = nil
+ end
+ end
+ end
+
+ return [ast.uniq, i]
+ end
+
+ RHS_SEARCH = 1
+ LHS_SEARCH = -1
+
+ def find_subexpression(ast, loc, dir)
+ while loc >= 0 && loc < ast.size
+ loc += dir
+ return loc if ast[loc] != nil
+ end
+
+ return nil
+ end
+
+ def process_token(i)
+ t = @tokens[i]
+
+ if @operators.key? t
+ tok = Operator.new(t)
+ elsif t.match /[A-Z]+/
+ tok = Identifier.new(t)
+ else
+ tok = Constant.new(t)
+ end
+
+ @expressions[i] = tok
+ return tok
+ end
+ end
+
+ TYPE = 0
+ FUNC = 1
+ class Operators
+ def initialize
+ @operators = {}
+ @order = []
+ end
+
+ def add(sym, kind, &block)
+ @operators[sym] = [kind, block]
+ @order << sym
+ end
+
+ def order
+ @order
+ end
+
+ def keys
+ @operators.keys
+ end
+
+ def key? k
+ @operators.key? k
+ end
+
+ def kind k
+ @operators[k][0]
+ end
+
+ def call(k, args)
+ @operators[k][1].call(*args)
+ end
+ end
+end</pre>
+
</body>
</html>
\ No newline at end of file
diff --git a/example.css b/example.css
index e69de29..4ece63a 100644
--- a/example.css
+++ b/example.css
@@ -0,0 +1,3 @@
+body {
+ font-size: 70%;
+}
\ No newline at end of file
diff --git a/example.html b/example.html
deleted file mode 100644
index 7ac7cd5..0000000
--- a/example.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
-
- <link rel="stylesheet" href="jquery.syntax.css" type="text/css" media="screen" />
- <link rel="stylesheet" href="example.css" type="text/css" media="screen" />
-
- <script src="jquery-1.4.1.js" type="text/javascript" charset="utf-8"></script>
-
- <script src="jquery.syntax.js" type="text/javascript" charset="utf-8"></script>
- <script src="jquery.syntax.cache.js" type="text/javascript" charset='utf-8'></script>
-
- <script type="text/javascript" language="JavaScript">
- //<!--
- $(function() {
- $('#highlight').click(function() {
- $('pre.clang').syntax({brush: 'clang', layout: 'table', replace: true}, function(options, html, container) {
- //$('.function', html).replaceWith(function(){
- // return $('<a>').addClass('function').attr('href', '#' + $(this).text()).html($(this).html());
- //})
- });
- });
- });
- //-->
- </script>
-
- </head>
- <body>
- <h1>Syntax Highlighting Example</h1>
-
- <button id="highlight">Highlight</button>
-
- <pre class="clang">#include <iostream>
-/* Multi line c comment
-
- Hello World
-*/
-
- const char * s = "My name is computer!\n\n"
-int main (int argv, char ** argv) {
- return EXIT_SUCCESS;
-}
-</pre>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/example2.html b/example2.html
deleted file mode 100644
index f5f1d8c..0000000
--- a/example2.html
+++ /dev/null
@@ -1,81 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
-
- <link rel="stylesheet" href="jquery.syntax.css" type="text/css" media="screen" />
- <link rel="stylesheet" href="example.css" type="text/css" media="screen" />
-
- <script src="jquery-1.4.1.js" type="text/javascript"></script>
-
- <script src="jquery.syntax.js" type="text/javascript"></script>
- <script src="jquery.syntax.cache.js" type="text/javascript" charset='utf-8'></script>
-
- <script src="jquery.syntax.brush.clang.js" type="text/javascript"></script>
- <script src="jquery.syntax.layout.table.js" type="text/javascript"></script>
-
- <link rel="stylesheet" href="jquery.syntax.layout.table.css" type="text/css" media="screen">
-
- <script type="text/javascript" language="JavaScript">
- //<!--
- $(function() {
- $('#highlight').click(function() {
- window.console.profile("Syntax Highlighting");
- start = new Date();
-
- $('pre.clang').syntax({brush: 'clang', layout: 'table', replace: true}, function(options, html, container) {
- //$('.function', html).replaceWith(function(){
- // return $('<a>').addClass('function').attr('href', '#' + $(this).text()).html($(this).html());
- //})
-
- finish = new Date();
- window.console.profileEnd();
- window.console.log(finish - start);
- });
- });
- });
- //-->
- </script>
-
- </head>
- <body>
- <h1>Syntax Highlighting Example</h1>
-
- <button id="highlight">Highlight</button>
-
- <pre class="clang">#include <iostream>
-
-// If we increase row by 1, the offset will increase by sz (number of elements per row i.e. number of columns)
-// If we increase col by 1, the offset will increase by 1
-unsigned rowMajorOffset(unsigned row, unsigned col, unsigned sz)
-{
- return col + row * sz;
-}
-
-// If we increase col by 1, the offset will increase by sz (number of elements per column i.e. number of rows)
-// If we increase row by 1, the offset will increase by 1
-unsigned columnMajorOffset(unsigned row, unsigned col, unsigned sz)
-{
- return row + col * sz;
-}
-
-int main (int argc, char * const argv[]) {
- Matrix<float, 4, 2, false> rowMajorMatrix;
- Matrix<float, 4, 2, true> columnMajorMatrix;
-
- rowMajorMatrix.loadTestPattern();
- rowMajorMatrix.debug();
-
- columnMajorMatrix.loadTestPattern();
- columnMajorMatrix.debug();
-
- rowMajorMatrix = columnMajorMatrix.transposeStorage();
- rowMajorMatrix.debug();
-
- Matrix<float, 2, 4, false> transposedMatrix = columnMajorMatrix.transposeMatrix();
- transposedMatrix.debug();
-
- return 0;
-}</pre>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/example3.html b/example3.html
deleted file mode 100644
index d559b68..0000000
--- a/example3.html
+++ /dev/null
@@ -1,171 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
-
- <link rel="stylesheet" href="jquery.syntax.css" type="text/css" media="screen" />
- <link rel="stylesheet" href="example.css" type="text/css" media="screen" />
-
- <script src="jquery-1.4.1.js" type="text/javascript"></script>
-
- <script src="jquery.syntax.js" type="text/javascript"></script>
- <script src="jquery.syntax.cache.js" type="text/javascript" charset='utf-8'></script>
-
- <script src="jquery.syntax.brush.clang.js" type="text/javascript"></script>
- <script src="jquery.syntax.layout.table.js" type="text/javascript"></script>
-
- <link rel="stylesheet" href="jquery.syntax.layout.table.css" type="text/css" media="screen">
-
- <script type="text/javascript" language="JavaScript">
- //<!--
- $(function() {
- $('#highlight').click(function() {
- window.console.profile("Syntax Highlighting");
- start = new Date();
-
- $('pre.clang').syntax({brush: 'clang', layout: 'table', replace: true}, function(options, html, container) {
- //$('.function', html).replaceWith(function(){
- // return $('<a>').addClass('function').attr('href', '#' + $(this).text()).html($(this).html());
- //})
-
- finish = new Date();
- window.console.profileEnd();
- window.console.log(finish - start);
- });
- });
- });
- //-->
- </script>
-
- </head>
- <body>
- <h1>Syntax Highlighting Example</h1>
-
- <button id="highlight">Highlight</button>
-
- <pre class="clang">#include <iostream>
-
-// If we increase row by 1, the offset will increase by sz (number of elements per row i.e. number of columns)
-// If we increase col by 1, the offset will increase by 1
-unsigned rowMajorOffset(unsigned row, unsigned col, unsigned sz)
-{
- return col + row * sz;
-}
-
-// If we increase col by 1, the offset will increase by sz (number of elements per column i.e. number of rows)
-// If we increase row by 1, the offset will increase by 1
-unsigned columnMajorOffset(unsigned row, unsigned col, unsigned sz)
-{
- return row + col * sz;
-}
-
-template <typename _ValueT, unsigned _R, unsigned _C, bool _ColumnMajor>
-class Matrix {
-protected:
- enum { ColumnMajor = _ColumnMajor };
- enum { R = _R };
- enum { C = _C };
-
- typedef _ValueT ValueT;
-
- ValueT m_values[C*R];
-
-public:
- const ValueT & at (unsigned r, unsigned c) const
- {
- if (ColumnMajor)
- return m_values[columnMajorOffset(r, c, R)];
- else
- return m_values[rowMajorOffset(r, c, C)];
- }
-
- ValueT & at (unsigned r, unsigned c)
- {
- if (ColumnMajor)
- return m_values[columnMajorOffset(r, c, R)];
- else
- return m_values[rowMajorOffset(r, c, C)];
- }
-
- void loadTestPattern ()
- {
- for (unsigned r = 0; r < R; r += 1)
- for (unsigned c = 0; c < C; c += 1)
- at(r, c) = (r+1) * 1000 + (c+1);
- }
-
- void debug ()
- {
- using namespace std;
-
- if (ColumnMajor)
- cout << "Column-Major Matrix " << "(" << R << "," << C << ")" << " @ " << this << endl;
- else
- cout << "Row-Major Matrix " << "(" << R << "," << C << ")" << " @ " << this << endl;
-
- cout << "Memory Offset: ";
- for (unsigned i = 0; i < (R*C); i += 1)
- cout << i << " ";
- cout << endl;
-
- cout << " Values: ";
- for (unsigned i = 0; i < (R*C); i += 1)
- cout << m_values[i] << " ";
- cout << endl;
-
- cout << "Standard Mathematical Notation:" << endl;
- cout << " ";
- for (unsigned c = 0; c < C; c += 1)
- cout << "Col " << c << " ";
- cout << endl;
-
- for (unsigned r = 0; r < R; r += 1) {
- cout << "Row " << r << " ";
- for (unsigned c = 0; c < C; c += 1)
- cout << at(r, c) << " ";
- cout << endl;
- }
- cout << endl;
- }
-
- Matrix<ValueT, R, C, !ColumnMajor> transposeStorage () const
- {
- Matrix<ValueT, R, C, !ColumnMajor> result;
-
- for (unsigned r = 0; r < R; r += 1)
- for (unsigned c = 0; c < C; c += 1)
- result.at(r, c) = at(r, c);
-
- return result;
- }
-
- Matrix<ValueT, C, R, !ColumnMajor> transposeMatrix () const
- {
- Matrix<ValueT, C, R, !ColumnMajor> result;
-
- memcpy(&result.at(0,0), m_values, sizeof(m_values));
-
- return result;
- }
-};
-
-int main (int argc, char * const argv[]) {
- Matrix<float, 4, 2, false> rowMajorMatrix;
- Matrix<float, 4, 2, true> columnMajorMatrix;
-
- rowMajorMatrix.loadTestPattern();
- rowMajorMatrix.debug();
-
- columnMajorMatrix.loadTestPattern();
- columnMajorMatrix.debug();
-
- rowMajorMatrix = columnMajorMatrix.transposeStorage();
- rowMajorMatrix.debug();
-
- Matrix<float, 2, 4, false> transposedMatrix = columnMajorMatrix.transposeMatrix();
- transposedMatrix.debug();
-
- return 0;
-}</pre>
-
- </body>
-</html>
\ No newline at end of file
diff --git a/jquery.syntax.brush.clang.js b/jquery.syntax.brush.clang.js
index dcbebbc..3c10a29 100644
--- a/jquery.syntax.brush.clang.js
+++ b/jquery.syntax.brush.clang.js
@@ -1,16 +1,19 @@
// brush: "clang" aliases: ["cpp", "c", "objective-c"]
Syntax.register('clang', function(brush) {
- var keywords = ["@interface", "@implementation", "@protocol", "@end", "@private", "@protected", "@public", "@try", "@throw", "@catch", "@finally", "@class", "@selector", "@encode", "@synchronized", "struct", "break", "continue", "else", "for", "switch", "case", "default", "enum", "goto", "register", "sizeof", "typedef", "volatile", "do", "extern", "if", "return", "static", "union", "while", "asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", "explicit", "static_cast", "typeid", "catch", "operator", "template", "class", "friend", "private", "using", "const_cast", "inline", "public", "throw", "virtual", "mutable", "protected", "wchar_t"];
+ var keywords = ["@interface", "@implementation", "@protocol", "@end", "@private", "@protected", "@public", "@try", "@throw", "@catch", "@finally", "@class", "@selector", "@encode", "@synchronized", "@property", "struct", "break", "continue", "else", "for", "switch", "case", "default", "enum", "goto", "register", "sizeof", "typedef", "volatile", "do", "extern", "if", "return", "static", "union", "while", "asm", "dynamic_cast", "namespace", "reinterpret_cast", "try", "explicit", "static_cast", "typeid", "catch", "operator", "template", "class", "friend", "private", "using", "const_cast", "inline", "public", "throw", "virtual", "mutable", "protected", "wchar_t"];
- var types = ["auto", "const", "double", "float", "int", "short", "char", "long", "signed", "unsigned", "bool", "void", "typename"];
- var operators = ["+", "*", "/", "-", "&", "|", "~", "!", "%", "<", "=", ">", "new", "delete"];
+ var types = ["auto", "const", "double", "float", "int", "short", "char", "long", "signed", "unsigned", "bool", "void", "typename", "id"];
+ var operators = ["+", "*", "/", "-", "&", "|", "~", "!", "%", "<", "=", ">", "[", "]", "new", "delete"];
var values = ["this", "true", "false", /[0-9]+(\.[0-9]+)?/g];
- brush.push(values, {klass: 'constant', children: null});
- brush.push(types, {klass: 'type', children: null})
- brush.push(keywords, {klass: 'keyword', children: null})
- brush.push(operators, {klass: 'operator', children: null})
+ brush.push(values, {klass: 'constant', children: []});
+ brush.push(types, {klass: 'type', children: []})
+ brush.push(keywords, {klass: 'keyword', children: []})
+ brush.push(operators, {klass: 'operator', children: []})
+
+ // Objective-C classes
+ brush.push({pattern: /\b[A-Z][\w]*\b/g, klass: 'type', children: []})
brush.push({
pattern: /#.*$/gmi,
@@ -21,6 +24,15 @@ Syntax.register('clang', function(brush) {
brush.push(Syntax.lib.cStyleComment);
brush.push(Syntax.lib.cppStyleComment);
+ // Objective-C style functions
+ brush.push({pattern: /\w+:/g, klass: 'function', children: []});
+ brush.push({
+ pattern: /[^:\[]\s+(\w+)(?=])/g,
+ klass: 'function',
+ matches: Syntax.singleMatchFunction(1, {klass: 'function', children: []})
+ })
+
+ // Strings
brush.push({pattern: /".+?"/g, klass: 'string', children: 'escape'});
brush.push({pattern: /\\./g, klass: 'escape'});
diff --git a/jquery.syntax.brush.ruby.js b/jquery.syntax.brush.ruby.js
index 71fdeaf..64a4626 100644
--- a/jquery.syntax.brush.ruby.js
+++ b/jquery.syntax.brush.ruby.js
@@ -1,34 +1,30 @@
// brush: "ruby" aliases: []
-/*
- # This ruby code will generate a list of classes.
- classes = []
-
- ObjectSpace.each_object(Class) do |c|
- classes << c
- end
-
- puts classes.collect{|cls| cls.name}.inspect
-*/
+Syntax.lib.rubyStyleFunction = {pattern: /(?:def\s+|\.)([a-z_][a-z0-9_]+)/gi, matches: Syntax.singleMatchFunction(1, {klass: 'function', children: null})}
+Syntax.lib.rubyStyleSymbol = {pattern: /:[\w]+/, klass: 'constant', children: null}
Syntax.register('ruby', function(brush) {
var keywords = ["alias", "and", "begin", "break", "case", "class", "def", "define_method", "defined", "do", "each", "else", "elsif", "end", "ensure", "false", "for", "if", "in", "module", "new", "next", "nil", "not", "or", "raise", "redo", "rescue", "retry", "return", "self", "super", "then", "throw", "true", "undef", "unless", "until", "when", "while", "yield"];
- var types = ["Socket", "UNIXServer", "UNIXSocket", "UDPSocket", "TCPServer", "TCPSocket", "IPSocket", "BasicSocket", "SocketError", "Pathname", "StopIteration", "Enumerable::Enumerator", "Binding", "UnboundMethod", "Method", "Proc", "SystemStackError", "LocalJumpError", "Struct::Tms", "Process::Status", "Time", "Dir", "File::Stat", "File", "IO", "EOFError", "IOError", "Range", "MatchData", "Regexp", "RegexpError", "Struct", "Hash", "Array", "Errno::EDQUOT", "Errno::ESTALE", "Errno::EINPROGRESS", "Errno::EALREADY", "Errno::EHOSTUNREACH", "Errno::EHOSTDOWN", "Errno::ECONNREFUSED", "Errno::ETIMEDOUT", "Errno::ETOOMANYREFS", "Errno::ESHUTDOWN", "Errno::ENOTCONN", "Errno::EISCONN", "Errno::ENOBUFS", "Errno::ECONNRESET", "Errno::ECONNABORTED", "Errno::ENETRESET", "Errno::ENETUNREACH", "Errno::ENETDOWN", "Errno::EADDRNOTAVAIL", "Errno::EADDRINUSE", "Errno::EAFNOSUPPORT", "Errno::EPFNOSUPPORT", "Errno::EOPNOTSUPP", "Errno::ESOCKTNOSUPPORT", "Errno::EPROTONOSUPPORT", "Errno::ENOPROTOOPT", "Errno::EPROTOTYPE", "Errno::EMSGSIZE", "Errno::EDESTADDRREQ", "Errno::ENOTSOCK", "Errno::EUSERS", "Errno::EILSEQ", "Errno::EOVERFLOW", "Errno::EBADMSG", "Errno::EMULTIHOP", "Errno::EPROTO", "Errno::ENOLINK", "Errno::EREMOTE", "Errno::ENOSR", "Errno::ETIME", "Errno::ENODATA", "Errno::ENOSTR", "Errno::EIDRM", "Errno::ENOMSG", "Errno::ELOOP", "Errno::ENOTEMPTY", "Errno::ENOSYS", "Errno::ENOLCK", "Errno::ENAMETOOLONG", "Errno::EDEADLK", "Errno::ERANGE", "Errno::EDOM", "Errno::EPIPE", "Errno::EMLINK", "Errno::EROFS", "Errno::ESPIPE", "Errno::ENOSPC", "Errno::EFBIG", "Errno::ETXTBSY", "Errno::ENOTTY", "Errno::EMFILE", "Errno::ENFILE", "Errno::EINVAL", "Errno::EISDIR", "Errno::ENOTDIR", "Errno::ENODEV", "Errno::EXDEV", "Errno::EEXIST", "Errno::EBUSY", "Errno::ENOTBLK", "Errno::EFAULT", "Errno::EACCES", "Errno::ENOMEM", "Errno::EAGAIN", "Errno::ECHILD", "Errno::EBADF", "Errno::ENOEXEC", "Errno::E2BIG", "Errno::ENXIO", "Errno::EIO", "Errno::EINTR", "Errno::ESRCH", "Errno::ENOENT", "Errno::EPERM", "Bignum", "Float", "Fixnum", "Integer", "Numeric", "FloatDomainError", "ZeroDivisionError", "ThreadGroup", "Continuation", "Thread", "ThreadError", "SystemCallError", "NoMemoryError", "SecurityError", "RuntimeError", "NotImplementedError", "LoadError", "SyntaxError", "ScriptError", "NoMethodError", "NameError::message", "NameError", "RangeError", "IndexError", "ArgumentError", "TypeError", "StandardError", "Interrupt", "SignalException", "fatal", "SystemExit", "Exception", "String", "FalseClass", "TrueClass", "Data", "Symbol", "NilClass", "Class", "Module", "Object"];
-
var operators = ["+", "*", "/", "-", "&", "|", "~", "!", "%", "<", "=", ">"];
var values = ["this", "true", "false", "nil", /[0-9]+(\.[0-9]+)?/g];
brush.push(values, {klass: 'constant', children: null});
- brush.push(types, {klass: 'type', children: null})
+
+ brush.push({pattern: /(@+|\$)[\w]+/g, klass: 'variable', children: null})
+
+ brush.push({pattern: /[A-Z_][\w:]+/g, klass: 'type', children: null})
brush.push(keywords, {klass: 'keyword', children: null})
brush.push(operators, {klass: 'operator', children: null})
brush.push(Syntax.lib.perlStyleComment)
+ brush.push(Syntax.lib.webLink)
brush.push({pattern: /".+?"/g, klass: 'string', children: ['escape']});
+ brush.push({pattern: /'.+?'/g, klass: 'string', children: ['escape']});
brush.push({pattern: /\\./g, klass: 'escape'});
brush.push(Syntax.lib.rubyStyleFunction);
+ brush.push(Syntax.lib.cStyleFunction);
});
diff --git a/jquery.syntax.css b/jquery.syntax.css
index 0c4d657..2423173 100644
--- a/jquery.syntax.css
+++ b/jquery.syntax.css
@@ -14,12 +14,12 @@
.syntax .keyword {
color: #3c3;
- font-weight: bold;
}
.syntax .type,
.syntax .template {
- color: #3c3;
+ color: #191;
+ font-weight: bold;
}
.syntax .typename {
@@ -44,7 +44,12 @@
color: #c00;
}
-.syntax .template {
+.syntax .href {
+ color: #00f;
+ text-decoration: underline;
+}
+
+.syntax .variable {
font-style: italic;
}
diff --git a/jquery.syntax.js b/jquery.syntax.js
index 7dfc642..07fc8a1 100644
--- a/jquery.syntax.js
+++ b/jquery.syntax.js
@@ -73,9 +73,8 @@ ResourceLoader.prototype._finish = function (name) {
if (!resource)
window.console.log("Could not load resource named ", name)
else {
- for (var i in loading) {
+ for (var i = 0; i < loading.length; i += 1)
loading[i](resource)
- }
}
}
@@ -100,11 +99,9 @@ Syntax = {
Syntax.getResource('jquery.syntax.brush', name, callback)
}),
-
layouts: new ResourceLoader(function(name, callback) {
Syntax.getResource('jquery.syntax.layout', name, callback)
- }),
-
+ }),
getStyles: function (path) {
var link = $('<link>')
$("head").append(link)
@@ -115,7 +112,6 @@ Syntax = {
href: path
})
},
-
getScript: function (path, callback) {
$.ajax({
async: 'true',
@@ -128,7 +124,6 @@ Syntax = {
cache: true
})
},
-
getResource: function (prefix, name, callback) {
var basename = prefix + "." + name
@@ -137,25 +132,22 @@ Syntax = {
Syntax.getScript(this.root + basename + '.js', callback)
},
-
register: function (name, callback) {
- brush = Syntax.brushes[name] = new Syntax.Brush()
+ var brush = Syntax.brushes[name] = new Syntax.Brush()
window.console.log("Registering brush", name, Syntax.brushes)
brush.klass = name
callback(brush)
},
-
alias: function (name, aliases) {
- for (var i in aliases)
+ for (var i = 0; i < aliases.length; i += 1)
Syntax.aliases[aliases[i]] = name
},
-
getMatches: function (text, expr) {
//window.console.log("getMatches: ", text, expr)
- var matches = []
+ var matches = [], match = null
while((match = expr.pattern.exec(text)) != null) {
if (expr.matches)
@@ -168,23 +160,23 @@ Syntax = {
}
}
-// Default layout
Syntax.layouts.plain = function (options, html, container) {
return html
}
Syntax.singleMatchFunction = function(index, rule) {
- return function(token) {
+ return function(match) {
return new Syntax.Match(RegExp.indexOf(match, index), match[index].length, rule, match[index])
}
}
-Syntax.lib.cStyleComment = {pattern: /\/\*[\s\S]*?\*\//gm, klass: 'comment', children: null}
-Syntax.lib.cppStyleComment = {pattern: /\/\/.*$/gm, klass: 'comment', children: null}
-Syntax.lib.perlStyleComment = {pattern: /#.*$/gm, klass: 'comment', children: null}
-Syntax.lib.cStyleFunction = {pattern: /([a-z_][a-z0-9_]+)\s*\(/gi, matches: Syntax.singleMatchFunction(1, {klass: 'function', children: null})}
-Syntax.lib.rubyStyleFunction = {pattern: /\.([a-z_][a-z0-9_]+)/gi, matches: Syntax.singleMatchFunction(1, {klass: 'function', children: null})}
-Syntax.lib.rubyStyleSymbol = {pattern: /:[\w]+/, klass: 'constant', children: null}
+Syntax.lib.cStyleComment = {pattern: /\/\*[\s\S]*?\*\//gm, klass: 'comment', children: ['href']}
+Syntax.lib.cppStyleComment = {pattern: /\/\/.*$/gm, klass: 'comment', children: ['href']}
+Syntax.lib.perlStyleComment = {pattern: /#.*$/gm, klass: 'comment', children: ['href']}
+
+Syntax.lib.cStyleFunction = {pattern: /([a-z_][a-z0-9_]+)\s*\(/gi, matches: Syntax.singleMatchFunction(1, {klass: 'function', children: []})}
+
+Syntax.lib.webLink = {pattern: /https?:\/\/([-\w~!$?&#\/+|.,=]|%[a-f\d]{2})+/g, klass: 'href'}
Syntax.Match = function (offset, length, expr, value) {
this.offset = offset
@@ -199,16 +191,11 @@ Syntax.Match = function (offset, length, expr, value) {
}
Syntax.Match.sort = function (a,b) {
- var diff = a.offset - b.offset
-
- if (diff != 0)
- return diff
- else
- return b.length - a.length
+ return (a.offset - b.offset) || (b.length - a.length)
}
Syntax.Match.prototype.contains = function (match) {
- return (this.offset <= match.offset) && (match.endOffset <= this.endOffset)
+ return (match.offset >= this.offset) && (match.endOffset <= this.endOffset)
}
Syntax.Match.defaultReduceCallback = function (node, container) {
@@ -237,9 +224,8 @@ Syntax.Match.prototype.reduce = function (append) {
if (this.expression && this.expression.klass)
container.addClass(this.expression.klass)
- for (var i in this.children) {
+ for (var i = 0; i < this.children.length; i += 1) {
//window.console.log(i, this.children[i], text)
-
var child = this.children[i]
var end = child.offset
@@ -256,56 +242,59 @@ Syntax.Match.prototype.reduce = function (append) {
else if (start < this.endOffset)
append(this.value.substr(start - this.offset, this.endOffset - start), container)
else if (start > this.endOffset)
- window.console.log("Start position", start, "exceeds length of value", this)
+ window.console.log("Start position", start, "exceeds length of value", this.offset, this.length)
return container
}
-// This function is by far the biggest overal cost in terms of run-time. This is not because
-// it is slow, but mostly because it is called many times. It already has as much of the logic
-// folded into it (few function calls). I considered making it non-recursive, but after testing,
-// I found that less than 64 out of 500 function calls recursed at all, so it wouldn't be worth
-// it - it might even get slower.
-Syntax.Match.prototype.insert = function (match) {
+// This is not a general tree insertion function. It is optimised to run in almost constant
+// time, but data must be inserted in sorted order, otherwise you will have problems.
+Syntax.Match.prototype.insertAtEnd = function (match) {
+ if (!this.contains(match)) {
+ window.console.log(this, "does not contain", match)
+ return null;
+ }
+
// We have explicitly said: no children
if (this.expression.children === null)
return null
-
- if (this.expression.children) {
- // window.console.log(this.expression.children, match.expression.klass, $.inArray(match.expression.klass, this.expression.children))
+ else if (this.expression.children) {
if ($.inArray(match.expression.klass, this.expression.children) == -1)
return null
}
- if (!this.contains(match))
- return null
-
if (this.children.length > 0) {
- for (var i in this.children) {
- var child = this.children[i]
-
- if (match.offset < child.offset) {
- if (match.endOffset <= child.offset) {
- this.children.splice(i, 0, match)
- return this
- } else {
- window.console.log("Match " + match.toString() + " " + displacement + " existing child: " + this.children[i].toString())
- return null
- }
- } else if (match.offset < child.endOffset) {
- if (match.endOffset <= child.endOffset) {
- // Recursive step
- return child.insert(match)
- } else {
- var parts = match.halfBisect(child.endOffset)
- child.insert(parts[0])
- match = parts[1]
- }
+ var i = this.children.length-1
+ var child = this.children[i]
+
+ if (match.offset < child.offset) {
+ if (match.endOffset <= child.offset) {
+ // displacement = 'before'
+ this.children.splice(i, 0, match)
+ return this
+ } else {
+ // displacement = 'left-overlap'
+ return null
+ }
+ } else if (match.offset < child.endOffset) {
+ if (match.endOffset <= child.endOffset) {
+ // displacement = 'contains'
+ var result = child.insertAtEnd(match)
+ return result
} else {
- if (i == this.children.length-1) {
- this.children.splice(i+1, 0, match)
- return this
- }
+ // displacement = 'right-overlap'
+ // This code should work, but right now I don't think its useful.
+ window.console.error("Cannot add match", match, "into", this, "it right-overlaps!")
+ //var parts = match.halfBisect(child.endOffset)
+ // child.insertAtEnd(parts[0])
+ // this.insertAtEnd(parts[1])
+ return null;
+ }
+ } else {
+ // displacement = 'after'
+ if (i == this.children.length-1) {
+ this.children.splice(i+1, 0, match)
+ return this
}
}
@@ -328,7 +317,14 @@ Syntax.Match.prototype.halfBisect = function(offset) {
Syntax.Match.prototype.bisectAtOffsets = function(splits) {
var parts = [], start = this.offset, prev = null, children = $.merge([], this.children)
- for (var i in splits) {
+ // Copy the array so we can modify it.
+ splits = splits.slice(0)
+
+ // We need to split including the last part.
+ splits.push(this.endOffset)
+ splits.sort(function(a,b){return a-b})
+
+ for (var i = 0; i < splits.length; i += 1) {
var offset = splits[i]
if (offset < this.offset || offset > this.endOffset) {
@@ -336,7 +332,7 @@ Syntax.Match.prototype.bisectAtOffsets = function(splits) {
}
var match = new Syntax.Match(start, offset - start, this.expression)
- match.value = this.value.substr(start, match.length)
+ match.value = this.value.substr(start - this.offset, match.length)
if (prev)
prev.next = match
@@ -351,7 +347,7 @@ Syntax.Match.prototype.bisectAtOffsets = function(splits) {
splits.length = parts.length
for (var i = 0; i < parts.length; i += 1) {
- var offset = splits.shift()
+ var offset = splits[0]
while (children.length > 0) {
if (children[0].endOffset <= parts[i].endOffset)
@@ -362,15 +358,18 @@ Syntax.Match.prototype.bisectAtOffsets = function(splits) {
if (children.length) {
// We may have an intersection
- if (children[0].offset < parts[i].offset) {
- children_parts = children.shift().bisectAtOffsets(splits)
+ if (children[0].offset < parts[i].endOffset) {
+ var children_parts = children.shift().bisectAtOffsets(splits), j = 0
- for (var j in children_parts)
+ for (; j < children_parts.length; j += 1)
parts[i+j].children.push(children_parts[j])
- // i += (j-1)
+ // Skip any parts which have been populated already
+ // i += (children_parts.length-1)
}
}
+
+ splits.shift();
}
if (children.length)
@@ -380,14 +379,11 @@ Syntax.Match.prototype.bisectAtOffsets = function(splits) {
}
Syntax.Match.prototype.split = function(pattern) {
- var splits = []
+ var splits = [], match
while ((match = pattern.exec(this.value)) != null)
splits.push(pattern.lastIndex)
- // We need to have a fake split at the end.
- splits.push(this.endOffset)
-
return this.bisectAtOffsets(splits)
}
@@ -400,14 +396,24 @@ Syntax.Brush.prototype.push = function () {
if ($.isArray(arguments[0])) {
var patterns = arguments[0], rule = arguments[1]
- for (var i in patterns)
+ for (var i = 0; i < patterns.length; i += 1)
this.push($.extend({pattern: patterns[i]}, rule))
} else {
var rule = arguments[0]
if (typeof(rule.pattern) == 'string') {
rule.string = rule.pattern
- rule.pattern = new RegExp(RegExp.escape(rule.pattern), rule.options || 'g')
+ var prefix = "\\b", postfix = "\\b"
+
+ if (!rule.pattern.match(/^\w/)) {
+ if (!rule.pattern.match(/\w$/))
+ prefix = postfix = ""
+ else
+ prefix = "\\B"
+ }
+
+
+ rule.pattern = rule.pattern = new RegExp(prefix + RegExp.escape(rule.pattern) + postfix, rule.options || 'g')
}
if (rule.pattern.global)
@@ -420,9 +426,8 @@ Syntax.Brush.prototype.push = function () {
Syntax.Brush.prototype.getMatches = function(text) {
var matches = []
- for (var i in this.rules) {
+ for (var i = 0; i < this.rules.length; i += 1)
matches = matches.concat(Syntax.getMatches(text, this.rules[i]))
- }
return matches
}
@@ -434,15 +439,14 @@ Syntax.Brush.prototype.process = function(text) {
// This sort is absolutely key to the functioning of the tree insertion algorithm.
matches.sort(Syntax.Match.sort)
- for (var i in matches) {
- top.insert(matches[i])
- }
+ for (var i = 0; i < matches.length; i += 1)
+ top.insertAtEnd(matches[i])
var lines = top.split(/\n/g)
var html = $('<pre>').addClass('syntax')
- for (var i in lines) {
+ for (var i = 0; i < lines.length; i += 1) {
var line = lines[i].reduce()
html.append(line)
}
diff --git a/jquery.syntax.layout.table.css b/jquery.syntax.layout.table.css
index 6e12646..043f721 100644
--- a/jquery.syntax.layout.table.css
+++ b/jquery.syntax.layout.table.css
@@ -11,6 +11,10 @@ table.syntax {
-webkit-box-shadow: 5px 5px 5px #eee;
}
+table.syntax tr.alt td.source {
+ background-color: #f6f6f6;
+}
+
table.syntax td {
padding-left: 0.4em;
padding-right: 0.4em;
@@ -22,5 +26,5 @@ table.syntax td.number {
width: 2.5em;
color: #555;
- background-color: #dadada;
+ background-color: #e0e0e0;
}
\ No newline at end of file
diff --git a/jquery.syntax.layout.table.js b/jquery.syntax.layout.table.js
index 9cd68c3..14967c4 100644
--- a/jquery.syntax.layout.table.js
+++ b/jquery.syntax.layout.table.js
@@ -1,16 +1,14 @@
-Syntax.layouts.table = function(options, code, container) {
- var table = $('<table>'), tr = null, td = null;
+Syntax.layouts.tableJQ = function(options, code, container) {
+ var table = $('<table class="syntax">'), tr = null, td = null;
var line = 1;
- table.addClass('syntax');
-
code.children().each(function() {
- tr = $('<tr>').addClass('line', 'line-' + line);
+ tr = $('<tr class="line ln' + line + '">')
- td = $('<td>').addClass('number').text(line);
+ td = $('<td class="number">' + line + '</td>')
tr.append(td);
- td = $('<td>').addClass('source');
+ td = $('<td class="source">')
td.append(this);
tr.append(td);
@@ -19,4 +17,57 @@ Syntax.layouts.table = function(options, code, container) {
});
return table;
-}
\ No newline at end of file
+}
+
+Syntax.layouts.tableDOM = function(options, code, container) {
+ var table = $('<table>'), tr = null, td = null;
+ var line = 1;
+
+ table.addClass('syntax');
+
+ code.children().each(function() {
+ tr = document.createElement('tr')
+ tr.className = "line ln" + line
+
+ if (line % 2)
+ tr.className += " alt"
+
+ td = document.createElement('td')
+ td.className = "number"
+ td.innerHTML = line
+ tr.appendChild(td)
+
+ td = document.createElement('td')
+ td.className = "source"
+ td.innerHTML = this.innerHTML
+ tr.appendChild(td)
+
+ table[0].appendChild(tr)
+ line = line + 1;
+ });
+
+ $('span.href', table).each(function(){
+ $(this).replaceWith($('<a>').attr('href', this.innerHTML).text(this.innerHTML))
+ })
+
+ return table;
+}
+
+Syntax.layouts.tableSTR = function(options, code, container) {
+ var table = "<table class='syntax'>", tr = null, td = null;
+ var line = 1;
+
+ code.children().each(function() {
+ table += "<tr class='line ln" + line + "'><td class='number'></td><td class='source'>" + this.innerHTML + "</td></tr>"
+
+ line = line + 1;
+ });
+
+ table += "</table>"
+
+ window.console.log(table.length)
+
+ return $(table);
+}
+
+Syntax.layouts.table = Syntax.layouts.tableDOM
\ No newline at end of file