163 changes: 163 additions & 0 deletions mode/nginx/nginx.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
CodeMirror.defineMode("nginx", 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(
/* ngxDirectiveControl */ "break return rewrite set" +
/* ngxDirective */ " accept_mutex accept_mutex_delay access_log add_after_body add_before_body add_header addition_types aio alias allow ancient_browser ancient_browser_value auth_basic auth_basic_user_file auth_http auth_http_header auth_http_timeout autoindex autoindex_exact_size autoindex_localtime charset charset_types client_body_buffer_size client_body_in_file_only client_body_in_single_buffer client_body_temp_path client_body_timeout client_header_buffer_size client_header_timeout client_max_body_size connection_pool_size create_full_put_path daemon dav_access dav_methods debug_connection debug_points default_type degradation degrade deny devpoll_changes devpoll_events directio directio_alignment empty_gif env epoll_events error_log eventport_events expires fastcgi_bind fastcgi_buffer_size fastcgi_buffers fastcgi_busy_buffers_size fastcgi_cache fastcgi_cache_key fastcgi_cache_methods fastcgi_cache_min_uses fastcgi_cache_path fastcgi_cache_use_stale fastcgi_cache_valid fastcgi_catch_stderr fastcgi_connect_timeout fastcgi_hide_header fastcgi_ignore_client_abort fastcgi_ignore_headers fastcgi_index fastcgi_intercept_errors fastcgi_max_temp_file_size fastcgi_next_upstream fastcgi_param fastcgi_pass_header fastcgi_pass_request_body fastcgi_pass_request_headers fastcgi_read_timeout fastcgi_send_lowat fastcgi_send_timeout fastcgi_split_path_info fastcgi_store fastcgi_store_access fastcgi_temp_file_write_size fastcgi_temp_path fastcgi_upstream_fail_timeout fastcgi_upstream_max_fails flv geoip_city geoip_country google_perftools_profiles gzip gzip_buffers gzip_comp_level gzip_disable gzip_hash gzip_http_version gzip_min_length gzip_no_buffer gzip_proxied gzip_static gzip_types gzip_vary gzip_window if_modified_since ignore_invalid_headers image_filter image_filter_buffer image_filter_jpeg_quality image_filter_transparency imap_auth imap_capabilities imap_client_buffer index ip_hash keepalive_requests keepalive_timeout kqueue_changes kqueue_events large_client_header_buffers limit_conn limit_conn_log_level limit_rate limit_rate_after limit_req limit_req_log_level limit_req_zone limit_zone lingering_time lingering_timeout lock_file log_format log_not_found log_subrequest map_hash_bucket_size map_hash_max_size master_process memcached_bind memcached_buffer_size memcached_connect_timeout memcached_next_upstream memcached_read_timeout memcached_send_timeout memcached_upstream_fail_timeout memcached_upstream_max_fails merge_slashes min_delete_depth modern_browser modern_browser_value msie_padding msie_refresh multi_accept open_file_cache open_file_cache_errors open_file_cache_events open_file_cache_min_uses open_file_cache_valid open_log_file_cache output_buffers override_charset perl perl_modules perl_require perl_set pid pop3_auth pop3_capabilities port_in_redirect postpone_gzipping postpone_output protocol proxy proxy_bind proxy_buffer proxy_buffer_size proxy_buffering proxy_buffers proxy_busy_buffers_size proxy_cache proxy_cache_key proxy_cache_methods proxy_cache_min_uses proxy_cache_path proxy_cache_use_stale proxy_cache_valid proxy_connect_timeout proxy_headers_hash_bucket_size proxy_headers_hash_max_size proxy_hide_header proxy_ignore_client_abort proxy_ignore_headers proxy_intercept_errors proxy_max_temp_file_size proxy_method proxy_next_upstream proxy_pass_error_message proxy_pass_header proxy_pass_request_body proxy_pass_request_headers proxy_read_timeout proxy_redirect proxy_send_lowat proxy_send_timeout proxy_set_body proxy_set_header proxy_ssl_session_reuse proxy_store proxy_store_access proxy_temp_file_write_size proxy_temp_path proxy_timeout proxy_upstream_fail_timeout proxy_upstream_max_fails random_index read_ahead real_ip_header recursive_error_pages request_pool_size reset_timedout_connection resolver resolver_timeout rewrite_log rtsig_overflow_events rtsig_overflow_test rtsig_overflow_threshold rtsig_signo satisfy secure_link_secret send_lowat send_timeout sendfile sendfile_max_chunk server_name_in_redirect server_names_hash_bucket_size server_names_hash_max_size server_tokens set_real_ip_from smtp_auth smtp_capabilities smtp_client_buffer smtp_greeting_delay so_keepalive source_charset ssi ssi_ignore_recycled_buffers ssi_min_file_chunk ssi_silent_errors ssi_types ssi_value_length ssl ssl_certificate ssl_certificate_key ssl_ciphers ssl_client_certificate ssl_crl ssl_dhparam ssl_engine ssl_prefer_server_ciphers ssl_protocols ssl_session_cache ssl_session_timeout ssl_verify_client ssl_verify_depth starttls stub_status sub_filter sub_filter_once sub_filter_types tcp_nodelay tcp_nopush thread_stack_size timeout timer_resolution types_hash_bucket_size types_hash_max_size underscores_in_headers uninitialized_variable_warn use user userid userid_domain userid_expires userid_mark userid_name userid_p3p userid_path userid_service valid_referers variables_hash_bucket_size variables_hash_max_size worker_connections worker_cpu_affinity worker_priority worker_processes worker_rlimit_core worker_rlimit_nofile worker_rlimit_sigpending worker_threads working_directory xclient xml_entities xslt_stylesheet xslt_typesdrew@li229-23"
);

var keywords_block = words(
/* ngxDirectiveBlock */ "http mail events server types location upstream charset_map limit_except if geo map"
);

var keywords_important = words(
/* ngxDirectiveImportant */ "include root server server_name listen internal proxy_pass memcached_pass fastcgi_pass try_files"
);

var indentUnit = config.indentUnit, type;
function ret(style, tp) {type = tp; return style;}

function tokenBase(stream, state) {


stream.eatWhile(/[\w\$_]/);

var cur = stream.current();


if (keywords.propertyIsEnumerable(cur)) {
return "keyword";
}
else if (keywords_block.propertyIsEnumerable(cur)) {
return "variable-2";
}
else if (keywords_important.propertyIsEnumerable(cur)) {
return "string-2";
}
/**/

var ch = stream.next();
if (ch == "@") {stream.eatWhile(/[\w\\\-]/); return ret("meta", stream.current());}
else if (ch == "/" && stream.eat("*")) {
state.tokenize = tokenCComment;
return tokenCComment(stream, state);
}
else if (ch == "<" && stream.eat("!")) {
state.tokenize = tokenSGMLComment;
return tokenSGMLComment(stream, state);
}
else if (ch == "=") ret(null, "compare");
else if ((ch == "~" || ch == "|") && stream.eat("=")) return ret(null, "compare");
else if (ch == "\"" || ch == "'") {
state.tokenize = tokenString(ch);
return state.tokenize(stream, state);
}
else if (ch == "#") {
stream.skipToEnd();
return ret("comment", "comment");
}
else if (ch == "!") {
stream.match(/^\s*\w*/);
return ret("keyword", "important");
}
else if (/\d/.test(ch)) {
stream.eatWhile(/[\w.%]/);
return ret("number", "unit");
}
else if (/[,.+>*\/]/.test(ch)) {
return ret(null, "select-op");
}
else if (/[;{}:\[\]]/.test(ch)) {
return ret(null, ch);
}
else {
stream.eatWhile(/[\w\\\-]/);
return ret("variable", "variable");
}
}

function tokenCComment(stream, state) {
var maybeEnd = false, ch;
while ((ch = stream.next()) != null) {
if (maybeEnd && ch == "/") {
state.tokenize = tokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}

function tokenSGMLComment(stream, state) {
var dashes = 0, ch;
while ((ch = stream.next()) != null) {
if (dashes >= 2 && ch == ">") {
state.tokenize = tokenBase;
break;
}
dashes = (ch == "-") ? dashes + 1 : 0;
}
return ret("comment", "comment");
}

function tokenString(quote) {
return function(stream, state) {
var escaped = false, ch;
while ((ch = stream.next()) != null) {
if (ch == quote && !escaped)
break;
escaped = !escaped && ch == "\\";
}
if (!escaped) state.tokenize = tokenBase;
return ret("string", "string");
};
}

return {
startState: function(base) {
return {tokenize: tokenBase,
baseIndent: base || 0,
stack: []};
},

token: function(stream, state) {
if (stream.eatSpace()) return null;
type = null;
var style = state.tokenize(stream, state);

var context = state.stack[state.stack.length-1];
if (type == "hash" && context == "rule") style = "atom";
else if (style == "variable") {
if (context == "rule") style = "number";
else if (!context || context == "@media{") style = "tag";
}

if (context == "rule" && /^[\{\};]$/.test(type))
state.stack.pop();
if (type == "{") {
if (context == "@media") state.stack[state.stack.length-1] = "@media{";
else state.stack.push("{");
}
else if (type == "}") state.stack.pop();
else if (type == "@media") state.stack.push("@media");
else if (context == "{" && type != "comment") state.stack.push("rule");
return style;
},

indent: function(state, textAfter) {
var n = state.stack.length;
if (/^\}/.test(textAfter))
n -= state.stack[state.stack.length-1] == "rule" ? 2 : 1;
return state.baseIndent + n * indentUnit;
},

electricChars: "}"
};
});

CodeMirror.defineMIME("text/nginx", "text/x-nginx-conf");
46 changes: 43 additions & 3 deletions mode/python/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
</head>
<body>
<h1>CodeMirror: Python mode</h1>

<h2>Python mode</h2>
<div><textarea id="code" name="code">
# Literals
1234
Expand Down Expand Up @@ -102,6 +102,34 @@ <h1>CodeMirror: Python mode</h1>
self.mixin = mixin

</textarea></div>


<h2>Cython mode</h2>

<div><textarea id="code-cython" name="code-cython">

import numpy as np
cimport cython
from libc.math cimport sqrt

@cython.boundscheck(False)
@cython.wraparound(False)
def pairwise_cython(double[:, ::1] X):
cdef int M = X.shape[0]
cdef int N = X.shape[1]
cdef double tmp, d
cdef double[:, ::1] D = np.empty((M, M), dtype=np.float64)
for i in range(M):
for j in range(M):
d = 0.0
for k in range(N):
tmp = X[i, k] - X[j, k]
d += tmp * tmp
D[i, j] = sqrt(d)
return np.asarray(D)

</textarea></div>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
mode: {name: "python",
Expand All @@ -111,9 +139,19 @@ <h1>CodeMirror: Python mode</h1>
indentUnit: 4,
tabMode: "shift",
matchBrackets: true
});

CodeMirror.fromTextArea(document.getElementById("code-cython"), {
mode: {name: "text/x-cython",
version: 2,
singleLineStringErrors: false},
lineNumbers: true,
indentUnit: 4,
tabMode: "shift",
matchBrackets: true
});
</script>
<h2>Configuration Options:</h2>
<h2>Configuration Options for Python mode:</h2>
<ul>
<li>version - 2/3 - The version of Python to recognize. Default is 2.</li>
<li>singleLineStringErrors - true/false - If you have a single-line string that is not terminated at the end of the line, this will show subsequent lines as errors if true, otherwise it will consider the newline as the end of the string. Default is false.</li>
Expand All @@ -127,9 +165,11 @@ <h2>Advanced Configuration Options:</h2>
<li>doubleDelimiters - RegEx - Regular Expressoin for double delimiters matching, default : <pre>^((\\+=)|(\\-=)|(\\*=)|(%=)|(/=)|(&amp;=)|(\\|=)|(\\^=))</pre></li>
<li>tripleDelimiters - RegEx - Regular Expression for triple delimiters matching, default : <pre>^((//=)|(&gt;&gt;=)|(&lt;&lt;=)|(\\*\\*=))</pre></li>
<li>identifiers - RegEx - Regular Expression for identifier, default : <pre>^[_A-Za-z][_A-Za-z0-9]*</pre></li>
<li>extra_keywords - list of string - List of extra words ton consider as keywords</li>
<li>extra_builtins - list of string - List of extra words ton consider as builtins</li>
</ul>


<p><strong>MIME types defined:</strong> <code>text/x-python</code>.</p>
<p><strong>MIME types defined:</strong> <code>text/x-python</code> and <code>text/x-cython</code>.</p>
</body>
</html>
21 changes: 19 additions & 2 deletions mode/python/python.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
var py3 = {'builtins': ['ascii', 'bytes', 'exec', 'print'],
'keywords': ['nonlocal', 'False', 'True', 'None']};

if(parserConf.extra_keywords != undefined){
commonkeywords = commonkeywords.concat(parserConf.extra_keywords);
}
if(parserConf.extra_builtins != undefined){
commonBuiltins = commonBuiltins.concat(parserConf.extra_builtins);
}
if (!!parserConf.version && parseInt(parserConf.version, 10) === 3) {
commonkeywords = commonkeywords.concat(py3.keywords);
commonBuiltins = commonBuiltins.concat(py3.builtins);
Expand Down Expand Up @@ -318,7 +324,7 @@ CodeMirror.defineMode("python", function(conf, parserConf) {

state.lastToken = style;

if (stream.eol() && stream.lambda) {
if (stream.eol() && state.lambda) {
state.lambda = false;
}

Expand All @@ -333,9 +339,20 @@ CodeMirror.defineMode("python", function(conf, parserConf) {
return state.scopes[0].offset;
},

lineComment: "#"
lineComment: "#",
fold: "indent"
};
return external;
});

CodeMirror.defineMIME("text/x-python", "python");

var words = function(str){return str.split(' ');};


CodeMirror.defineMIME("text/x-cython", {
name: "python",
extra_keywords: words("by cdef cimport cpdef ctypedef enum except"+
"extern gil include nogil property public"+
"readonly struct union DEF IF ELIF ELSE")
});
2 changes: 1 addition & 1 deletion mode/rst/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License

Copyright (c) 2013 Hasan Karahan
Copyright (c) 2013 Hasan Karahan <hasan.karahan81@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
49 changes: 30 additions & 19 deletions mode/rst/rst.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,11 @@ CodeMirror.defineMode('rst-base', function (config) {
var TAIL = "(?:\\s*|\\W|$)",
rx_TAIL = new RegExp(format('^{0}', TAIL));

var NAME = "(?:[^\\W\\d_](?:[\\w\\+\\.\\-:]*[^\\W_])?)",
var NAME =
"(?:[^\\W\\d_](?:[\\w!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)",
rx_NAME = new RegExp(format('^{0}', NAME));
var NAME_WWS = "(?:[^\\W\\d_](?:[\\w\\s\\+\\.\\-:]*[^\\W_])?)";
var NAME_WWS =
"(?:[^\\W\\d_](?:[\\w\\s!\"#$%&'()\\*\\+,\\-\\.\/:;<=>\\?]*[^\\W_])?)";
var REF_NAME = format('(?:{0}|`{1}`)', NAME, NAME_WWS);

var TEXT1 = "(?:[^\\s\\|](?:[^\\|]*[^\\s\\|])?)";
Expand Down Expand Up @@ -480,7 +482,9 @@ CodeMirror.defineMode('rst-base', function (config) {
},

innerMode: function (state) {
return {state: state.ctx.local, mode: state.ctx.mode};
return state.tmp ? {state: state.tmp.local, mode: state.tmp.mode}
: state.ctx ? {state: state.ctx.local, mode: state.ctx.mode}
: null;
},

token: function (stream, state) {
Expand All @@ -494,40 +498,47 @@ CodeMirror.defineMode('rst-base', function (config) {

CodeMirror.defineMode('rst', function (config, options) {

var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*/;
var rx_emphasis = /^\*[^\*\s](?:[^\*]*[^\*\s])?\*/;
var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``/;

var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;

var rx_uri_protocol = "[Hh][Tt][Tt][Pp][Ss]?://";
var rx_uri_domain = "(?:[\\d\\w.-]+)\\.(?:\\w{2,6})";
var rx_uri_path = "(?:/[\\d\\w\\#\\%\\&\\-\\.\\,\\/\\:\\=\\?\\~]+)*";
var rx_uri = new RegExp("^" +
rx_uri_protocol + rx_uri_domain + rx_uri_path
);

var rx_strong = /^\*\*[^\*\s](?:[^\*]*[^\*\s])?\*\*(\s+|$)/;
var rx_emphasis = /^[^\*]\*[^\*\s](?:[^\*]*[^\*\s])?\*(\s+|$)/;
var rx_literal = /^``[^`\s](?:[^`]*[^`\s])``(\s+|$)/;

var rx_number = /^(?:[\d]+(?:[\.,]\d+)*)/;
var rx_positive = /^(?:\s\+[\d]+(?:[\.,]\d+)*)/;
var rx_negative = /^(?:\s\-[\d]+(?:[\.,]\d+)*)/;

var overlay = {
token: function (stream) {

if (stream.match(rx_uri)) return 'link';
if (stream.match(rx_strong)) return 'strong';
if (stream.match(rx_emphasis)) return 'em';
if (stream.match(rx_literal)) return 'string-2';
if (stream.match(rx_number)) return 'number';
if (stream.match(rx_positive)) return 'positive';
if (stream.match(rx_negative)) return 'negative';
if (stream.match(rx_strong) && stream.match (/\W+|$/, false))
return 'strong';
if (stream.match(rx_emphasis) && stream.match (/\W+|$/, false))
return 'em';
if (stream.match(rx_literal) && stream.match (/\W+|$/, false))
return 'string-2';
if (stream.match(rx_number))
return 'number';
if (stream.match(rx_positive))
return 'positive';
if (stream.match(rx_negative))
return 'negative';
if (stream.match(rx_uri))
return 'link';

while (stream.next() != null) {
if (stream.match(rx_uri, false)) break;
if (stream.match(rx_strong, false)) break;
if (stream.match(rx_emphasis, false)) break;
if (stream.match(rx_literal, false)) break;
if (stream.match(rx_number, false)) break;
if (stream.match(rx_positive, false)) break;
if (stream.match(rx_negative, false)) break;
if (stream.match(rx_uri, false)) break;
}

return null;
Expand Down
8 changes: 4 additions & 4 deletions mode/ruby/ruby.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ CodeMirror.defineMode("ruby", function(config) {
} else if (ch == "/" && !stream.eol() && stream.peek() != " ") {
return chain(readQuoted(ch, "string-2", true), stream, state);
} else if (ch == "%") {
var style = "string", embed = false;
var style = "string", embed = true;
if (stream.eat("s")) style = "atom";
else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; }
else if (stream.eat(/[r]/)) { style = "string-2"; embed = true; }
else if (stream.eat(/[wxq]/)) style = "string";
else if (stream.eat(/[WQ]/)) style = "string";
else if (stream.eat(/[r]/)) style = "string-2";
else if (stream.eat(/[wxq]/)) { style = "string"; embed = false; }
var delim = stream.eat(/[^\w\s]/);
if (!delim) return "operator";
if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
Expand Down
3 changes: 2 additions & 1 deletion mode/rust/rust.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,8 @@ CodeMirror.defineMode("rust", function() {
electricChars: "{}",
blockCommentStart: "/*",
blockCommentEnd: "*/",
lineComment: "//"
lineComment: "//",
fold: "brace"
};
});

Expand Down
14 changes: 12 additions & 2 deletions mode/smalltalk/smalltalk.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,13 @@ CodeMirror.defineMode('smalltalk', function(config) {
token = nextString(stream, new Context(nextString, context));

} else if (aChar === '#') {
stream.eatWhile(/[^ .\[\]()]/);
token.name = 'string-2';
if (stream.peek() === '\'') {
stream.next();
token = nextSymbol(stream, new Context(nextSymbol, context));
} else {
stream.eatWhile(/[^ .\[\]()]/);
token.name = 'string-2';
}

} else if (aChar === '$') {
if (stream.next() === '<') {
Expand Down Expand Up @@ -89,6 +94,11 @@ CodeMirror.defineMode('smalltalk', function(config) {
return new Token('string', stream.eat('\'') ? context.parent : context, false);
};

var nextSymbol = function(stream, context) {
stream.eatWhile(/[^']/);
return new Token('string-2', stream.eat('\'') ? context.parent : context, false);
};

var nextTemporaries = function(stream, context) {
var token = new Token(null, context, false);
var aChar = stream.next();
Expand Down
107 changes: 107 additions & 0 deletions mode/smartymixed/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>CodeMirror: Smarty mixed mode</title>
<link rel="stylesheet" href="../../lib/codemirror.css">
<script src="../../lib/codemirror.js"></script>
<link rel="stylesheet" href="../../doc/docs.css">

<!-- smartymixed dependencies -->
<script src="../../mode/xml/xml.js"></script>
<script src="../../mode/javascript/javascript.js"></script>
<script src="../../mode/css/css.js"></script>
<script src="../../mode/htmlmixed/htmlmixed.js"></script>
<script src="../../mode/smarty/smarty.js"></script>

<!-- smartymixed -->
<script src="../../mode/smartymixed/smartymixed.js"></script>
</head>
<body>
<h1>CodeMirror: Smarty mixed mode</h1>
<form><textarea id="code" name="code">
{**
* @brief Smarty mixed mode
* @author Ruslan Osmanov
* @date 29.06.2013
*}
<html>
<head>
<title>{$title|htmlspecialchars|truncate:30}</title>
</head>
<body>
{* Multiline smarty
* comment, no {$variables} here
*}
{literal}
{literal} is just an HTML text.
<script type="text/javascript">//<![CDATA[
var a = {$just_a_normal_js_object : "value"};
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("code"), {
mode : "smartymixed",
tabSize : 2,
indentUnit : 2,
indentWithTabs : false,
lineNumbers : true,
smartyVersion : 3
});
// ]]>
</script>
<style>
/* CSS content
{$no_smarty} */
.some-class { font-weight: bolder; color: "orange"; }
</style>
{/literal}

{extends file="parent.tpl"}
{include file="template.tpl"}

{* some example Smarty content *}
{if isset($name) && $name == 'Blog'}
This is a {$var}.
{$integer = 4511}, {$array[] = "a"}, {$stringvar = "string"}
{$integer = 4512} {$array[] = "a"} {$stringvar = "string"}
{assign var='bob' value=$var.prop}
{elseif $name == $foo}
{function name=menu level=0}
{foreach $data as $entry}
{if is_array($entry)}
- {$entry@key}
{menu data=$entry level=$level+1}
{else}
{$entry}
{* One
* Two
* Three
*}
{/if}
{/foreach}
{/function}
{/if}
</body>
<!-- R.O. -->
</html>
</textarea></form>

<script type="text/javascript">
var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("code"), {
mode : "smartymixed",
tabSize : 2,
indentUnit : 2,
indentWithTabs : false,
lineNumbers : true,
smartyVersion : 3,
matchBrackets : true,
});
</script>

<p>The Smarty mixed mode depends on the Smarty and HTML mixed modes. HTML
mixed mode itself depends on XML, JavaScript, and CSS modes.</p>

<p>It takes the same options, as Smarty and HTML mixed modes.</p>

<p><strong>MIME types defined:</strong> <code>text/x-smarty</code>.</p>
</body>
</html>
<!-- vim: set ft=html ts=2 sts=2 sw=2 et: -->
170 changes: 170 additions & 0 deletions mode/smartymixed/smartymixed.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/**
* @file smartymixed.js
* @brief Smarty Mixed Codemirror mode (Smarty + Mixed HTML)
* @author Ruslan Osmanov <rrosmanov at gmail dot com>
* @version 3.0
* @date 05.07.2013
*/
CodeMirror.defineMode("smartymixed", function(config) {
var settings, regs, helpers, parsers,
htmlMixedMode = CodeMirror.getMode(config, "htmlmixed"),
smartyMode = CodeMirror.getMode(config, "smarty"),

settings = {
rightDelimiter: '}',
leftDelimiter: '{'
};

if (config.hasOwnProperty("leftDelimiter")) {
settings.leftDelimiter = config.leftDelimiter;
}
if (config.hasOwnProperty("rightDelimiter")) {
settings.rightDelimiter = config.rightDelimiter;
}

regs = {
smartyComment: new RegExp("^" + settings.leftDelimiter + "\\*"),
literalOpen: new RegExp(settings.leftDelimiter + "literal" + settings.rightDelimiter),
literalClose: new RegExp(settings.leftDelimiter + "\/literal" + settings.rightDelimiter),
hasLeftDelimeter: new RegExp(".*" + settings.leftDelimiter),
htmlHasLeftDelimeter: new RegExp("[^<>]*" + settings.leftDelimiter)
};

helpers = {
chain: function(stream, state, parser) {
state.tokenize = parser;
return parser(stream, state);
},

cleanChain: function(stream, state, parser) {
state.tokenize = null;
state.localState = null;
state.localMode = null;
return (typeof parser == "string") ? (parser ? parser : null) : parser(stream, state);
},

maybeBackup: function(stream, pat, style) {
var cur = stream.current();
var close = cur.search(pat),
m;
if (close > - 1) stream.backUp(cur.length - close);
else if (m = cur.match(/<\/?$/)) {
stream.backUp(cur.length);
if (!stream.match(pat, false)) stream.match(cur[0]);
}
return style;
}
};

parsers = {
html: function(stream, state) {
if (!state.inLiteral && stream.match(regs.htmlHasLeftDelimeter, false)) {
state.tokenize = parsers.smarty;
state.localMode = smartyMode;
state.localState = smartyMode.startState(htmlMixedMode.indent(state.htmlMixedState, ""));
return helpers.maybeBackup(stream, settings.leftDelimiter, smartyMode.token(stream, state.localState));
}
return htmlMixedMode.token(stream, state.htmlMixedState);
},

smarty: function(stream, state) {
if (stream.match(settings.leftDelimiter, false)) {
if (stream.match(regs.smartyComment, false)) {
return helpers.chain(stream, state, parsers.inBlock("comment", "*" + settings.rightDelimiter));
}
} else if (stream.match(settings.rightDelimiter, false)) {
stream.eat(settings.rightDelimiter);
state.tokenize = parsers.html;
state.localMode = htmlMixedMode;
state.localState = state.htmlMixedState;
return "tag";
}

return helpers.maybeBackup(stream, settings.rightDelimiter, smartyMode.token(stream, state.localState));
},

inBlock: function(style, terminator) {
return function(stream, state) {
while (!stream.eol()) {
if (stream.match(terminator)) {
helpers.cleanChain(stream, state, "");
break;
}
stream.next();
}
return style;
};
}
};

return {
startState: function() {
var state = htmlMixedMode.startState();
return {
token: parsers.html,
localMode: null,
localState: null,
htmlMixedState: state,
tokenize: null,
inLiteral: false
};
},

copyState: function(state) {
var local = null, tok = (state.tokenize || state.token);
if (state.localState) {
local = CodeMirror.copyState((tok != parsers.html ? smartyMode : htmlMixedMode), state.localState);
}
return {
token: state.token,
tokenize: state.tokenize,
localMode: state.localMode,
localState: local,
htmlMixedState: CodeMirror.copyState(htmlMixedMode, state.htmlMixedState),
inLiteral: state.inLiteral
};
},

token: function(stream, state) {
if (stream.match(settings.leftDelimiter, false)) {
if (!state.inLiteral && stream.match(regs.literalOpen, true)) {
state.inLiteral = true;
return "keyword";
} else if (state.inLiteral && stream.match(regs.literalClose, true)) {
state.inLiteral = false;
return "keyword";
}
}
if (state.inLiteral && state.localState != state.htmlMixedState) {
state.tokenize = parsers.html;
state.localMode = htmlMixedMode;
state.localState = state.htmlMixedState;
}

var style = (state.tokenize || state.token)(stream, state);
return style;
},

indent: function(state, textAfter) {
if (state.localMode == smartyMode
|| (state.inLiteral && !state.localMode)
|| regs.hasLeftDelimeter.test(textAfter)) {
return CodeMirror.Pass;
}
return htmlMixedMode.indent(state.htmlMixedState, textAfter);
},

electricChars: "/{}:",

innerMode: function(state) {
return {
state: state.localState || state.htmlMixedState,
mode: state.localMode || htmlMixedMode
};
}
};
},
"htmlmixed");

CodeMirror.defineMIME("text/x-smarty", "smartymixed");
// vim: et ts=2 sts=2 sw=2
6 changes: 4 additions & 2 deletions mode/sparql/sparql.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ CodeMirror.defineMode("sparql", function(config) {
return new RegExp("^(?:" + words.join("|") + ")$", "i");
}
var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri",
"isblank", "isliteral", "union", "a"]);
"isblank", "isliteral", "a"]);
var keywords = wordRegexp(["base", "prefix", "select", "distinct", "reduced", "construct", "describe",
"ask", "from", "named", "where", "order", "limit", "offset", "filter", "optional",
"graph", "by", "asc", "desc"]);
"graph", "by", "asc", "desc", "as", "having", "undef", "values", "group",
"minus", "in", "not", "service", "silent", "using", "insert", "delete", "union",
"data", "copy", "to", "move", "add", "create", "drop", "clear", "load"]);
var operatorChars = /[*+\-<>=&|]/;

function tokenBase(stream, state) {
Expand Down
3 changes: 2 additions & 1 deletion mode/vbscript/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ <h1>CodeMirror: VBScript mode</h1>

<script>
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true
lineNumbers: true,
indentUnit: 4
});
</script>

Expand Down
352 changes: 330 additions & 22 deletions mode/vbscript/vbscript.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,334 @@
CodeMirror.defineMode("vbscript", function() {
var regexVBScriptKeyword = /^(?:Call|Case|CDate|Clear|CInt|CLng|Const|CStr|Description|Dim|Do|Each|Else|ElseIf|End|Err|Error|Exit|False|For|Function|If|LCase|Loop|LTrim|Next|Nothing|Now|Number|On|Preserve|Quit|ReDim|Resume|RTrim|Select|Set|Sub|Then|To|Trim|True|UBound|UCase|Until|VbCr|VbCrLf|VbLf|VbTab)$/im;

return {
token: function(stream) {
if (stream.eatSpace()) return null;
var ch = stream.next();
if (ch == "'") {
stream.skipToEnd();
return "comment";
}
if (ch == '"') {
stream.skipTo('"');
return "string";
}

if (/\w/.test(ch)) {
stream.eatWhile(/\w/);
if (regexVBScriptKeyword.test(stream.current())) return "keyword";
}
return null;
/*
For extra ASP classic objects, initialize CodeMirror instance with this option:
isASP: true
E.G.:
var editor = CodeMirror.fromTextArea(document.getElementById("code"), {
lineNumbers: true,
isASP: true
});
*/
CodeMirror.defineMode("vbscript", function(conf, parserConf) {
var ERRORCLASS = 'error';

function wordRegexp(words) {
return new RegExp("^((" + words.join(")|(") + "))\\b", "i");
}

var singleOperators = new RegExp("^[\\+\\-\\*/&\\\\\\^<>=]");
var doubleOperators = new RegExp("^((<>)|(<=)|(>=))");
var singleDelimiters = new RegExp('^[\\.,]');
var brakets = new RegExp('^[\\(\\)]');
var identifiers = new RegExp("^[A-Za-z][_A-Za-z0-9]*");

var openingKeywords = ['class','sub','select','while','if','function', 'property', 'with', 'for'];
var middleKeywords = ['else','elseif','case'];
var endKeywords = ['next','loop','wend'];

var wordOperators = wordRegexp(['and', 'or', 'not', 'xor', 'is', 'mod', 'eqv', 'imp']);
var commonkeywords = ['dim', 'redim', 'then', 'until', 'randomize',
'byval','byref','new','property', 'exit', 'in',
'const','private', 'public',
'get','set','let', 'stop', 'on error resume next', 'on error goto 0', 'option explicit', 'call', 'me'];

//This list was from: http://msdn.microsoft.com/en-us/library/f8tbc79x(v=vs.84).aspx
var atomWords = ['true', 'false', 'nothing', 'empty', 'null'];
//This list was from: http://msdn.microsoft.com/en-us/library/3ca8tfek(v=vs.84).aspx
var builtinFuncsWords = ['abs', 'array', 'asc', 'atn', 'cbool', 'cbyte', 'ccur', 'cdate', 'cdbl', 'chr', 'cint', 'clng', 'cos', 'csng', 'cstr', 'date', 'dateadd', 'datediff', 'datepart',
'dateserial', 'datevalue', 'day', 'escape', 'eval', 'execute', 'exp', 'filter', 'formatcurrency', 'formatdatetime', 'formatnumber', 'formatpercent', 'getlocale', 'getobject',
'getref', 'hex', 'hour', 'inputbox', 'instr', 'instrrev', 'int', 'fix', 'isarray', 'isdate', 'isempty', 'isnull', 'isnumeric', 'isobject', 'join', 'lbound', 'lcase', 'left',
'len', 'loadpicture', 'log', 'ltrim', 'rtrim', 'trim', 'maths', 'mid', 'minute', 'month', 'monthname', 'msgbox', 'now', 'oct', 'replace', 'rgb', 'right', 'rnd', 'round',
'scriptengine', 'scriptenginebuildversion', 'scriptenginemajorversion', 'scriptengineminorversion', 'second', 'setlocale', 'sgn', 'sin', 'space', 'split', 'sqr', 'strcomp',
'string', 'strreverse', 'tan', 'time', 'timer', 'timeserial', 'timevalue', 'typename', 'ubound', 'ucase', 'unescape', 'vartype', 'weekday', 'weekdayname', 'year'];

//This list was from: http://msdn.microsoft.com/en-us/library/ydz4cfk3(v=vs.84).aspx
var builtinConsts = ['vbBlack', 'vbRed', 'vbGreen', 'vbYellow', 'vbBlue', 'vbMagenta', 'vbCyan', 'vbWhite', 'vbBinaryCompare', 'vbTextCompare',
'vbSunday', 'vbMonday', 'vbTuesday', 'vbWednesday', 'vbThursday', 'vbFriday', 'vbSaturday', 'vbUseSystemDayOfWeek', 'vbFirstJan1', 'vbFirstFourDays', 'vbFirstFullWeek',
'vbGeneralDate', 'vbLongDate', 'vbShortDate', 'vbLongTime', 'vbShortTime', 'vbObjectError',
'vbOKOnly', 'vbOKCancel', 'vbAbortRetryIgnore', 'vbYesNoCancel', 'vbYesNo', 'vbRetryCancel', 'vbCritical', 'vbQuestion', 'vbExclamation', 'vbInformation', 'vbDefaultButton1', 'vbDefaultButton2',
'vbDefaultButton3', 'vbDefaultButton4', 'vbApplicationModal', 'vbSystemModal', 'vbOK', 'vbCancel', 'vbAbort', 'vbRetry', 'vbIgnore', 'vbYes', 'vbNo',
'vbCr', 'VbCrLf', 'vbFormFeed', 'vbLf', 'vbNewLine', 'vbNullChar', 'vbNullString', 'vbTab', 'vbVerticalTab', 'vbUseDefault', 'vbTrue', 'vbFalse',
'vbEmpty', 'vbNull', 'vbInteger', 'vbLong', 'vbSingle', 'vbDouble', 'vbCurrency', 'vbDate', 'vbString', 'vbObject', 'vbError', 'vbBoolean', 'vbVariant', 'vbDataObject', 'vbDecimal', 'vbByte', 'vbArray'];
//This list was from: http://msdn.microsoft.com/en-us/library/hkc375ea(v=vs.84).aspx
var builtinObjsWords = ['WScript', 'err', 'debug', 'RegExp'];
var knownProperties = ['description', 'firstindex', 'global', 'helpcontext', 'helpfile', 'ignorecase', 'length', 'number', 'pattern', 'source', 'value', 'count'];
var knownMethods = ['clear', 'execute', 'raise', 'replace', 'test', 'write', 'writeline', 'close', 'open', 'state', 'eof', 'update', 'addnew', 'end', 'createobject', 'quit'];

var aspBuiltinObjsWords = ['server', 'response', 'request', 'session', 'application'];
var aspKnownProperties = ['buffer', 'cachecontrol', 'charset', 'contenttype', 'expires', 'expiresabsolute', 'isclientconnected', 'pics', 'status', //response
'clientcertificate', 'cookies', 'form', 'querystring', 'servervariables', 'totalbytes', //request
'contents', 'staticobjects', //application
'codepage', 'lcid', 'sessionid', 'timeout', //session
'scripttimeout']; //server
var aspKnownMethods = ['addheader', 'appendtolog', 'binarywrite', 'end', 'flush', 'redirect', //response
'binaryread', //request
'remove', 'removeall', 'lock', 'unlock', //application
'abandon', //session
'getlasterror', 'htmlencode', 'mappath', 'transfer', 'urlencode']; //server

var knownWords = knownMethods.concat(knownProperties);

builtinObjsWords = builtinObjsWords.concat(builtinConsts);

if (conf.isASP){
builtinObjsWords = builtinObjsWords.concat(aspBuiltinObjsWords);
knownWords = knownWords.concat(aspKnownMethods, aspKnownProperties);
};

var keywords = wordRegexp(commonkeywords);
var atoms = wordRegexp(atomWords);
var builtinFuncs = wordRegexp(builtinFuncsWords);
var builtinObjs = wordRegexp(builtinObjsWords);
var known = wordRegexp(knownWords);
var stringPrefixes = '"';

var opening = wordRegexp(openingKeywords);
var middle = wordRegexp(middleKeywords);
var closing = wordRegexp(endKeywords);
var doubleClosing = wordRegexp(['end']);
var doOpening = wordRegexp(['do']);
var noIndentWords = wordRegexp(['on error resume next', 'exit']);
var comment = wordRegexp(['rem']);


function indent(_stream, state) {
state.currentIndent++;
}

function dedent(_stream, state) {
state.currentIndent--;
}
// tokenizers
function tokenBase(stream, state) {
if (stream.eatSpace()) {
return 'space';
//return null;
}

var ch = stream.peek();

// Handle Comments
if (ch === "'") {
stream.skipToEnd();
return 'comment';
}
if (stream.match(comment)){
stream.skipToEnd();
return 'comment';
}


// Handle Number Literals
if (stream.match(/^((&H)|(&O))?[0-9\.]/i, false) && !stream.match(/^((&H)|(&O))?[0-9\.]+[a-z_]/i, false)) {
var floatLiteral = false;
// Floats
if (stream.match(/^\d*\.\d+/i)) { floatLiteral = true; }
else if (stream.match(/^\d+\.\d*/)) { floatLiteral = true; }
else if (stream.match(/^\.\d+/)) { floatLiteral = true; }

if (floatLiteral) {
// Float literals may be "imaginary"
stream.eat(/J/i);
return 'number';
}
// Integers
var intLiteral = false;
// Hex
if (stream.match(/^&H[0-9a-f]+/i)) { intLiteral = true; }
// Octal
else if (stream.match(/^&O[0-7]+/i)) { intLiteral = true; }
// Decimal
else if (stream.match(/^[1-9]\d*F?/)) {
// Decimal literals may be "imaginary"
stream.eat(/J/i);
// TODO - Can you have imaginary longs?
intLiteral = true;
}
// Zero by itself with no other piece of number.
else if (stream.match(/^0(?![\dx])/i)) { intLiteral = true; }
if (intLiteral) {
// Integer literals may be "long"
stream.eat(/L/i);
return 'number';
}
}

// Handle Strings
if (stream.match(stringPrefixes)) {
state.tokenize = tokenStringFactory(stream.current());
return state.tokenize(stream, state);
}

// Handle operators and Delimiters
if (stream.match(doubleOperators)
|| stream.match(singleOperators)
|| stream.match(wordOperators)) {
return 'operator';
}
if (stream.match(singleDelimiters)) {
return null;
}

if (stream.match(brakets)) {
return "bracket";
}

if (stream.match(noIndentWords)) {
state.doInCurrentLine = true;

return 'keyword';
}

if (stream.match(doOpening)) {
indent(stream,state);
state.doInCurrentLine = true;

return 'keyword';
}
if (stream.match(opening)) {
if (! state.doInCurrentLine)
indent(stream,state);
else
state.doInCurrentLine = false;

return 'keyword';
}
if (stream.match(middle)) {
return 'keyword';
}


if (stream.match(doubleClosing)) {
dedent(stream,state);
dedent(stream,state);

return 'keyword';
}
if (stream.match(closing)) {
if (! state.doInCurrentLine)
dedent(stream,state);
else
state.doInCurrentLine = false;

return 'keyword';
}

if (stream.match(keywords)) {
return 'keyword';
}

if (stream.match(atoms)) {
return 'atom';
}

if (stream.match(known)) {
return 'variable-2';
}

if (stream.match(builtinFuncs)) {
return 'builtin';
}

if (stream.match(builtinObjs)){
return 'variable-2';
}

if (stream.match(identifiers)) {
return 'variable';
}

// Handle non-detected items
stream.next();
return ERRORCLASS;
}
};

function tokenStringFactory(delimiter) {
var singleline = delimiter.length == 1;
var OUTCLASS = 'string';

return function(stream, state) {
while (!stream.eol()) {
stream.eatWhile(/[^'"]/);
if (stream.match(delimiter)) {
state.tokenize = tokenBase;
return OUTCLASS;
} else {
stream.eat(/['"]/);
}
}
if (singleline) {
if (parserConf.singleLineStringErrors) {
return ERRORCLASS;
} else {
state.tokenize = tokenBase;
}
}
return OUTCLASS;
};
}


function tokenLexer(stream, state) {
var style = state.tokenize(stream, state);
var current = stream.current();

// Handle '.' connected identifiers
if (current === '.') {
style = state.tokenize(stream, state);

current = stream.current();
if (style.substr(0, 8) === 'variable' || style==='builtin' || style==='keyword'){//|| knownWords.indexOf(current.substring(1)) > -1) {
if (style === 'builtin' || style === 'keyword') style='variable';
if (knownWords.indexOf(current.substr(1)) > -1) style='variable-2';

return style;
} else {
return ERRORCLASS;
}
}

return style;
}

var external = {
electricChars:"dDpPtTfFeE ",
startState: function() {
return {
tokenize: tokenBase,
lastToken: null,
currentIndent: 0,
nextLineIndent: 0,
doInCurrentLine: false,
ignoreKeyword: false


};
},

token: function(stream, state) {
if (stream.sol()) {
state.currentIndent += state.nextLineIndent;
state.nextLineIndent = 0;
state.doInCurrentLine = 0;
}
var style = tokenLexer(stream, state);

state.lastToken = {style:style, content: stream.current()};

if (style==='space') style=null;

return style;
},

indent: function(state, textAfter) {
var trueText = textAfter.replace(/^\s+|\s+$/g, '') ;
if (trueText.match(closing) || trueText.match(doubleClosing) || trueText.match(middle)) return conf.indentUnit*(state.currentIndent-1);
if(state.currentIndent < 0) return 0;
return state.currentIndent * conf.indentUnit;
}

};
return external;
});

CodeMirror.defineMIME("text/vbscript", "vbscript");
21 changes: 18 additions & 3 deletions mode/xml/xml.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
CodeMirror.defineMode("xml", function(config, parserConfig) {
var indentUnit = config.indentUnit;
var multilineTagIndentFactor = parserConfig.multilineTagIndentFactor || 1;
var multilineTagIndentPastTag = parserConfig.multilineTagIndentPastTag || true;

var Kludges = parserConfig.htmlMode ? {
autoSelfClosers: {'area': true, 'base': true, 'br': true, 'col': true, 'command': true,
Expand Down Expand Up @@ -111,6 +112,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
return "error";
} else if (/[\'\"]/.test(ch)) {
state.tokenize = inAttribute(ch);
state.stringStartCol = stream.column();
return state.tokenize(stream, state);
} else {
stream.eatWhile(/[^\s\u00a0=<>\"\']/);
Expand All @@ -119,7 +121,7 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
}

function inAttribute(quote) {
return function(stream, state) {
var closure = function(stream, state) {
while (!stream.eol()) {
if (stream.next() == quote) {
state.tokenize = inTag;
Expand All @@ -128,6 +130,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
}
return "string";
};
closure.isInAttribute = true;
return closure;
}

function inBlock(style, terminator) {
Expand Down Expand Up @@ -299,10 +303,20 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {

indent: function(state, textAfter, fullLine) {
var context = state.context;
// Indent multi-line strings (e.g. css).
if (state.tokenize.isInAttribute) {
return state.stringStartCol + 1;
}
if ((state.tokenize != inTag && state.tokenize != inText) ||
context && context.noIndent)
return fullLine ? fullLine.match(/^(\s*)/)[0].length : 0;
if (state.tagName) return state.tagStart + indentUnit * multilineTagIndentFactor;
// Indent the starts of attribute names.
if (state.tagName) {
if (multilineTagIndentPastTag)
return state.tagStart + state.tagName.length + 2;
else
return state.tagStart + indentUnit * multilineTagIndentFactor;
}
if (alignCDATA && /<!\[CDATA\[/.test(textAfter)) return 0;
if (context && /^<\//.test(textAfter))
context = context.prev;
Expand All @@ -316,7 +330,8 @@ CodeMirror.defineMode("xml", function(config, parserConfig) {
blockCommentStart: "<!--",
blockCommentEnd: "-->",

configuration: parserConfig.htmlMode ? "html" : "xml"
configuration: parserConfig.htmlMode ? "html" : "xml",
helperType: parserConfig.htmlMode ? "html" : "xml"
};
});

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "codemirror",
"version":"3.14.0",
"version":"3.15.0",
"main": "lib/codemirror.js",
"description": "In-browser code editing made bearable",
"licenses": [{"type": "MIT",
Expand Down
1 change: 1 addition & 0 deletions test/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ <h1>CodeMirror: Test Suite</h1>
<script src="doc_test.js"></script>
<script src="comment_test.js"></script>
<script src="mode_test.js"></script>
<script src="../mode/javascript/test.js"></script>
<script src="../mode/css/css.js"></script>
<script src="../mode/css/test.js"></script>
<script src="../mode/css/scss_test.js"></script>
Expand Down
2 changes: 1 addition & 1 deletion test/mode_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@
}
s += '</tr><tr>';
for (var i = 0; i < output.length; i += 2) {
s += '<td class="mt-style"><span>' + output[i] + '</span></td>';
s += '<td class="mt-style"><span>' + (output[i] || null) + '</span></td>';
}
s += '</table>';
return s;
Expand Down
29 changes: 29 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,24 @@ testCM("bookmarkInsertLeft", function(cm) {
eqPos(bl.find(), Pos(0, 1));
}, {value: "abcdef"});

testCM("bookmarkCursor", function(cm) {
var pos01 = cm.cursorCoords(Pos(0, 1)), pos11 = cm.cursorCoords(Pos(1, 1)),
pos20 = cm.cursorCoords(Pos(2, 0)), pos30 = cm.cursorCoords(Pos(3, 0)),
pos41 = cm.cursorCoords(Pos(4, 1));
cm.setBookmark(Pos(0, 1), {widget: document.createTextNode("←"), insertLeft: true});
cm.setBookmark(Pos(2, 0), {widget: document.createTextNode("←"), insertLeft: true});
cm.setBookmark(Pos(1, 1), {widget: document.createTextNode("→")});
cm.setBookmark(Pos(3, 0), {widget: document.createTextNode("→")});
var new01 = cm.cursorCoords(Pos(0, 1)), new11 = cm.cursorCoords(Pos(1, 1)),
new20 = cm.cursorCoords(Pos(2, 0)), new30 = cm.cursorCoords(Pos(3, 0));
is(new01.left == pos01.left && new01.top == pos01.top, "at left, middle of line");
is(new11.left > pos11.left && new11.top == pos11.top, "at right, middle of line");
is(new20.left == pos20.left && new20.top == pos20.top, "at left, empty line");
is(new30.left > pos30.left && new30.top == pos30.top, "at right, empty line");
cm.setBookmark(Pos(4, 0), {widget: document.createTextNode("→")});
is(cm.cursorCoords(Pos(4, 1)).left > pos41.left, "single-char bug");
}, {value: "foo\nbar\n\n\nx\ny"});

testCM("getAllMarks", function(cm) {
addDoc(cm, 10, 10);
var m1 = cm.setBookmark(Pos(0, 2));
Expand Down Expand Up @@ -823,6 +841,17 @@ testCM("wrappingInlineWidget", function(cm) {
eq(curR.bottom, cur1.bottom);
}, {value: "1 2 3 xxx 4", lineWrapping: true});

testCM("changedInlineWidget", function(cm) {
cm.setSize("10em");
var w = document.createElement("span");
w.innerHTML = "x";
var m = cm.markText(Pos(0, 4), Pos(0, 5), {replacedWith: w});
w.innerHTML = "and now the widget is really really long all of a sudden and a scrollbar is needed";
m.changed();
var hScroll = byClassName(cm.getWrapperElement(), "CodeMirror-hscrollbar")[0];
is(hScroll.scrollWidth > hScroll.clientWidth);
}, {value: "hello there"});

testCM("inlineWidget", function(cm) {
var w = cm.setBookmark(Pos(0, 2), {widget: document.createTextNode("uu")});
cm.setCursor(0, 2);
Expand Down
74 changes: 41 additions & 33 deletions test/vim_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ function copyCursor(cur) {
function testVim(name, run, opts, expectedFail) {
var vimOpts = {
lineNumbers: true,
keyMap: 'vim',
vimMode: true,
showCursorWhenSelecting: true,
value: code
};
Expand All @@ -111,8 +111,7 @@ function testVim(name, run, opts, expectedFail) {
return test('vim_' + name, function() {
var place = document.getElementById("testground");
var cm = CodeMirror(place, vimOpts);
CodeMirror.Vim.maybeInitState(cm);
var vim = cm.vimState;
var vim = CodeMirror.Vim.maybeInitVimState_(cm);

function doKeysFn(cm) {
return function(args) {
Expand Down Expand Up @@ -140,7 +139,7 @@ function testVim(name, run, opts, expectedFail) {
// Find key in keymap and handle.
var handled = CodeMirror.lookupKey(key, ['vim-insert'], executeHandler);
// Record for insert mode.
if (handled === true && cm.vimState.insertMode && arguments[i] != 'Esc') {
if (handled === true && cm.state.vim.insertMode && arguments[i] != 'Esc') {
var lastChange = CodeMirror.Vim.getVimGlobalState_().macroModeState.lastInsertModeChanges;
if (lastChange) {
lastChange.changes.push(new CodeMirror.Vim.InsertModeKey(key));
Expand Down Expand Up @@ -184,7 +183,7 @@ function testVim(name, run, opts, expectedFail) {
return CodeMirror.Vim.getRegisterController();
}
}
CodeMirror.Vim.clearVimGlobalState_();
CodeMirror.Vim.resetVimGlobalState_();
var successful = false;
try {
run(cm, vim, helpers);
Expand Down Expand Up @@ -228,7 +227,7 @@ function testJumplist(name, keys, endPos, startPos, dialog) {
endPos = makeCursor(endPos[0], endPos[1]);
startPos = makeCursor(startPos[0], startPos[1]);
testVim(name, function(cm, vim, helpers) {
CodeMirror.Vim.clearVimGlobalState_();
CodeMirror.Vim.resetVimGlobalState_();
if(dialog)cm.openDialog = helpers.fakeOpenDialog('word');
cm.setCursor(startPos);
helpers.doKeys.apply(null, keys);
Expand Down Expand Up @@ -296,8 +295,10 @@ testMotion('l', 'l', makeCursor(0, 1));
testMotion('l_repeat', ['2', 'l'], makeCursor(0, 2));
testMotion('j', 'j', offsetCursor(word1.end, 1, 0), word1.end);
testMotion('j_repeat', ['2', 'j'], offsetCursor(word1.end, 2, 0), word1.end);
testMotion('j_repeat_clip', ['1000', 'j'], endOfDocument);
testMotion('k', 'k', offsetCursor(word3.end, -1, 0), word3.end);
testMotion('k_repeat', ['2', 'k'], makeCursor(0, 4), makeCursor(2, 4));
testMotion('k_repeat_clip', ['1000', 'k'], makeCursor(0, 4), makeCursor(2, 4));
testMotion('w', 'w', word1.start);
testMotion('w_multiple_newlines_no_space', 'w', makeCursor(12, 2), makeCursor(11, 2));
testMotion('w_multiple_newlines_with_space', 'w', makeCursor(14, 0), makeCursor(12, 51));
Expand Down Expand Up @@ -499,15 +500,13 @@ testVim('dl', function(cm, vim, helpers) {
eqPos(curStart, cm.getCursor());
}, { value: ' word1 ' });
testVim('dl_eol', function(cm, vim, helpers) {
// TODO: This test is incorrect. The cursor should end up at (0, 5).
var curStart = makeCursor(0, 6);
cm.setCursor(curStart);
cm.setCursor(0, 6);
helpers.doKeys('d', 'l');
eq(' word1', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq(' ', register.text);
is(!register.linewise);
helpers.assertCursorAt(0, 6);
helpers.assertCursorAt(0, 5);
}, { value: ' word1 ' });
testVim('dl_repeat', function(cm, vim, helpers) {
var curStart = makeCursor(0, 0);
Expand Down Expand Up @@ -592,38 +591,35 @@ testVim('dw_word', function(cm, vim, helpers) {
testVim('dw_only_word', function(cm, vim, helpers) {
// Test that if there is only 1 word left, dw deletes till the end of the
// line.
var curStart = makeCursor(0, 1);
cm.setCursor(curStart);
cm.setCursor(0, 1);
helpers.doKeys('d', 'w');
eq(' ', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq('word1 ', register.text);
is(!register.linewise);
eqPos(curStart, cm.getCursor());
helpers.assertCursorAt(0, 0);
}, { value: ' word1 ' });
testVim('dw_eol', function(cm, vim, helpers) {
// Assert that dw does not delete the newline if last word to delete is at end
// of line.
var curStart = makeCursor(0, 1);
cm.setCursor(curStart);
cm.setCursor(0, 1);
helpers.doKeys('d', 'w');
eq(' \nword2', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq('word1', register.text);
is(!register.linewise);
eqPos(curStart, cm.getCursor());
helpers.assertCursorAt(0, 0);
}, { value: ' word1\nword2' });
testVim('dw_eol_with_multiple_newlines', function(cm, vim, helpers) {
// Assert that dw does not delete the newline if last word to delete is at end
// of line and it is followed by multiple newlines.
var curStart = makeCursor(0, 1);
cm.setCursor(curStart);
cm.setCursor(0, 1);
helpers.doKeys('d', 'w');
eq(' \n\nword2', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq('word1', register.text);
is(!register.linewise);
eqPos(curStart, cm.getCursor());
helpers.assertCursorAt(0, 0);
}, { value: ' word1\n\nword2' });
testVim('dw_empty_line_followed_by_whitespace', function(cm, vim, helpers) {
cm.setCursor(0, 0);
Expand Down Expand Up @@ -663,14 +659,13 @@ testVim('dw_end_of_document', function(cm, vim, helpers) {
testVim('dw_repeat', function(cm, vim, helpers) {
// Assert that dw does delete newline if it should go to the next line, and
// that repeat works properly.
var curStart = makeCursor(0, 1);
cm.setCursor(curStart);
cm.setCursor(0, 1);
helpers.doKeys('d', '2', 'w');
eq(' ', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq('word1\nword2', register.text);
is(!register.linewise);
eqPos(curStart, cm.getCursor());
helpers.assertCursorAt(0, 0);
}, { value: ' word1\nword2' });
testVim('de_word_start_and_empty_lines', function(cm, vim, helpers) {
cm.setCursor(0, 0);
Expand Down Expand Up @@ -818,12 +813,6 @@ testVim('dd_lastline', function(cm, vim, helpers) {
eq(expectedLineCount, cm.lineCount());
helpers.assertCursorAt(cm.lineCount() - 1, 0);
});
testVim('cw', function(cm, vim, helpers) {
cm.setCursor(0, 0);
helpers.doKeys('c', '2', 'w');
eq(' word3', cm.getValue());
helpers.assertCursorAt(0, 0);
}, { value: 'word1 word2 word3'});
// Yank commands should behave the exact same as d commands, expect that nothing
// gets deleted.
testVim('yw_repeat', function(cm, vim, helpers) {
Expand Down Expand Up @@ -854,6 +843,12 @@ testVim('yy_multiply_repeat', function(cm, vim, helpers) {
// Change commands behave like d commands except that it also enters insert
// mode. In addition, when the change is linewise, an additional newline is
// inserted so that insert mode starts on that line.
testVim('cw', function(cm, vim, helpers) {
cm.setCursor(0, 0);
helpers.doKeys('c', '2', 'w');
eq(' word3', cm.getValue());
helpers.assertCursorAt(0, 0);
}, { value: 'word1 word2 word3'});
testVim('cw_repeat', function(cm, vim, helpers) {
// Assert that cw does delete newline if it should go to the next line, and
// that repeat works properly.
Expand All @@ -877,9 +872,14 @@ testVim('cc_multiply_repeat', function(cm, vim, helpers) {
var register = helpers.getRegisterController().getRegister();
eq(expectedBuffer, register.text);
is(register.linewise);
helpers.assertCursorAt(0, lines[0].textStart);
eq('vim-insert', cm.getOption('keyMap'));
});
testVim('cc_append', function(cm, vim, helpers) {
var expectedLineCount = cm.lineCount();
cm.setCursor(cm.lastLine(), 0);
helpers.doKeys('c', 'c');
eq(expectedLineCount, cm.lineCount());
});
// Swapcase commands edit in place and do not modify registers.
testVim('g~w_repeat', function(cm, vim, helpers) {
// Assert that dw does delete newline if it should go to the next line, and
Expand Down Expand Up @@ -994,14 +994,13 @@ testEdit('daW_end_punct', 'foo \tbAr.', /A/, 'daW', 'foo');

// Operator-motion tests
testVim('D', function(cm, vim, helpers) {
var curStart = makeCursor(0, 3);
cm.setCursor(curStart);
cm.setCursor(0, 3);
helpers.doKeys('D');
eq(' wo\nword2\n word3', cm.getValue());
var register = helpers.getRegisterController().getRegister();
eq('rd1', register.text);
is(!register.linewise);
helpers.assertCursorAt(0, 3);
helpers.assertCursorAt(0, 2);
}, { value: ' word1\nword2\n word3' });
testVim('C', function(cm, vim, helpers) {
var curStart = makeCursor(0, 3);
Expand All @@ -1011,7 +1010,7 @@ testVim('C', function(cm, vim, helpers) {
var register = helpers.getRegisterController().getRegister();
eq('rd1', register.text);
is(!register.linewise);
helpers.assertCursorAt(0, 3);
eqPos(curStart, cm.getCursor());
eq('vim-insert', cm.getOption('keyMap'));
}, { value: ' word1\nword2\n word3' });
testVim('Y', function(cm, vim, helpers) {
Expand All @@ -1024,6 +1023,11 @@ testVim('Y', function(cm, vim, helpers) {
is(!register.linewise);
helpers.assertCursorAt(0, 3);
}, { value: ' word1\nword2\n word3' });
testVim('~', function(cm, vim, helpers) {
helpers.doKeys('3', '~');
eq('ABCdefg', cm.getValue());
helpers.assertCursorAt(0, 3);
}, { value: 'abcdefg' });

// Action tests
testVim('ctrl-a', function(cm, vim, helpers) {
Expand Down Expand Up @@ -1471,6 +1475,10 @@ testVim('visual_join', function(cm, vim, helpers) {
helpers.doKeys('l', 'V', 'l', 'j', 'j', 'J');
eq(' 1 2 3\n 4\n 5', cm.getValue());
}, { value: ' 1\n 2\n 3\n 4\n 5' });
testVim('visual_blank', function(cm, vim, helpers) {
helpers.doKeys('v', 'k');
eq(vim.visualMode, true);
}, { value: '\n' });
testVim('/ and n/N', function(cm, vim, helpers) {
cm.openDialog = helpers.fakeOpenDialog('match');
helpers.doKeys('/');
Expand Down
33 changes: 33 additions & 0 deletions theme/3024-day.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Name: 3024 day
Author: Jan T. Sott (http://github.com/idleberg)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-3024-day.CodeMirror {background: #f7f7f7; color: #3a3432;}
.cm-s-3024-day div.CodeMirror-selected {background: #d6d5d4 !important;}
.cm-s-3024-day .CodeMirror-gutters {background: #f7f7f7; border-right: 0px;}
.cm-s-3024-day .CodeMirror-linenumber {color: #807d7c;}
.cm-s-3024-day .CodeMirror-cursor {border-left: 1px solid #5c5855 !important;}

.cm-s-3024-day span.cm-comment {color: #cdab53;}
.cm-s-3024-day span.cm-atom {color: #a16a94;}
.cm-s-3024-day span.cm-number {color: #a16a94;}

.cm-s-3024-day span.cm-property, .cm-s-3024-day span.cm-attribute {color: #01a252;}
.cm-s-3024-day span.cm-keyword {color: #db2d20;}
.cm-s-3024-day span.cm-string {color: #fded02;}

.cm-s-3024-day span.cm-variable {color: #01a252;}
.cm-s-3024-day span.cm-variable-2 {color: #01a0e4;}
.cm-s-3024-day span.cm-def {color: #e8bbd0;}
.cm-s-3024-day span.cm-error {background: #db2d20; color: #5c5855;}
.cm-s-3024-day span.cm-bracket {color: #3a3432;}
.cm-s-3024-day span.cm-tag {color: #db2d20;}
.cm-s-3024-day span.cm-link {color: #a16a94;}

.cm-s-3024-day .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
33 changes: 33 additions & 0 deletions theme/3024-night.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Name: 3024 night
Author: Jan T. Sott (http://github.com/idleberg)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-3024-night.CodeMirror {background: #090300; color: #d6d5d4;}
.cm-s-3024-night div.CodeMirror-selected {background: #3a3432 !important;}
.cm-s-3024-night .CodeMirror-gutters {background: #090300; border-right: 0px;}
.cm-s-3024-night .CodeMirror-linenumber {color: #5c5855;}
.cm-s-3024-night .CodeMirror-cursor {border-left: 1px solid #807d7c !important;}

.cm-s-3024-night span.cm-comment {color: #cdab53;}
.cm-s-3024-night span.cm-atom {color: #a16a94;}
.cm-s-3024-night span.cm-number {color: #a16a94;}

.cm-s-3024-night span.cm-property, .cm-s-3024-night span.cm-attribute {color: #01a252;}
.cm-s-3024-night span.cm-keyword {color: #db2d20;}
.cm-s-3024-night span.cm-string {color: #fded02;}

.cm-s-3024-night span.cm-variable {color: #01a252;}
.cm-s-3024-night span.cm-variable-2 {color: #01a0e4;}
.cm-s-3024-night span.cm-def {color: #e8bbd0;}
.cm-s-3024-night span.cm-error {background: #db2d20; color: #807d7c;}
.cm-s-3024-night span.cm-bracket {color: #d6d5d4;}
.cm-s-3024-night span.cm-tag {color: #db2d20;}
.cm-s-3024-night span.cm-link {color: #a16a94;}

.cm-s-3024-night .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
33 changes: 33 additions & 0 deletions theme/base16-dark.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Name: Base16 Default Dark
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-base16-dark.CodeMirror {background: #151515; color: #e0e0e0;}
.cm-s-base16-dark div.CodeMirror-selected {background: #202020 !important;}
.cm-s-base16-dark .CodeMirror-gutters {background: #151515; border-right: 0px;}
.cm-s-base16-dark .CodeMirror-linenumber {color: #505050;}
.cm-s-base16-dark .CodeMirror-cursor {border-left: 1px solid #b0b0b0 !important;}

.cm-s-base16-dark span.cm-comment {color: #8f5536;}
.cm-s-base16-dark span.cm-atom {color: #aa759f;}
.cm-s-base16-dark span.cm-number {color: #aa759f;}

.cm-s-base16-dark span.cm-property, .cm-s-base16-dark span.cm-attribute {color: #90a959;}
.cm-s-base16-dark span.cm-keyword {color: #ac4142;}
.cm-s-base16-dark span.cm-string {color: #f4bf75;}

.cm-s-base16-dark span.cm-variable {color: #90a959;}
.cm-s-base16-dark span.cm-variable-2 {color: #6a9fb5;}
.cm-s-base16-dark span.cm-def {color: #d28445;}
.cm-s-base16-dark span.cm-error {background: #ac4142; color: #b0b0b0;}
.cm-s-base16-dark span.cm-bracket {color: #e0e0e0;}
.cm-s-base16-dark span.cm-tag {color: #ac4142;}
.cm-s-base16-dark span.cm-link {color: #aa759f;}

.cm-s-base16-dark .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
33 changes: 33 additions & 0 deletions theme/base16-light.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Name: Base16 Default Light
Author: Chris Kempson (http://chriskempson.com)
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-chrome-devtools)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-base16-light.CodeMirror {background: #f5f5f5; color: #202020;}
.cm-s-base16-light div.CodeMirror-selected {background: #e0e0e0 !important;}
.cm-s-base16-light .CodeMirror-gutters {background: #f5f5f5; border-right: 0px;}
.cm-s-base16-light .CodeMirror-linenumber {color: #b0b0b0;}
.cm-s-base16-light .CodeMirror-cursor {border-left: 1px solid #505050 !important;}

.cm-s-base16-light span.cm-comment {color: #8f5536;}
.cm-s-base16-light span.cm-atom {color: #aa759f;}
.cm-s-base16-light span.cm-number {color: #aa759f;}

.cm-s-base16-light span.cm-property, .cm-s-base16-light span.cm-attribute {color: #90a959;}
.cm-s-base16-light span.cm-keyword {color: #ac4142;}
.cm-s-base16-light span.cm-string {color: #f4bf75;}

.cm-s-base16-light span.cm-variable {color: #90a959;}
.cm-s-base16-light span.cm-variable-2 {color: #6a9fb5;}
.cm-s-base16-light span.cm-def {color: #d28445;}
.cm-s-base16-light span.cm-error {background: #ac4142; color: #505050;}
.cm-s-base16-light span.cm-bracket {color: #202020;}
.cm-s-base16-light span.cm-tag {color: #ac4142;}
.cm-s-base16-light span.cm-link {color: #aa759f;}

.cm-s-base16-light .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
2 changes: 1 addition & 1 deletion theme/lesser-dark.css
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Ported to CodeMirror by Peter Kroon
.cm-s-lesser-dark .CodeMirror-cursor { border-left: 1px solid white !important; }
.cm-s-lesser-dark pre { padding: 0 8px; }/*editable code holder*/

div.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/
.cm-s-lesser-dark.CodeMirror span.CodeMirror-matchingbracket { color: #7EFC7E; }/*65FC65*/

.cm-s-lesser-dark .CodeMirror-gutters { background: #262626; border-right:1px solid #aaa; }
.cm-s-lesser-dark .CodeMirror-linenumber { color: #777; }
Expand Down
19 changes: 5 additions & 14 deletions theme/midnight.css
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
/* Based on the theme at http://bonsaiden.github.com/JavaScript-Garden */

/*<!--breakpoint-->*/
.breakpoints {width: .8em;}
.breakpoint { color: #822; }

/*<!--match-->*/
span.CodeMirror-matchhighlight { background: #494949 }
.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67; !important }
.cm-s-midnight span.CodeMirror-matchhighlight { background: #494949 }
.cm-s-midnight.CodeMirror-focused span.CodeMirror-matchhighlight { background: #314D67 !important; }

/*<!--activeline-->*/
.activeline {background: #253540 !important;}
.cm-s-midnight .activeline {background: #253540 !important;}

.cm-s-midnight.CodeMirror {
background: #0F192A;
color: #D1EDFF;
}

.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}
.cm-s-midnight.CodeMirror {border-top: 1px solid black; border-bottom: 1px solid black;}

.cm-s-midnight div.CodeMirror-selected {background: #314D67 !important;}
.cm-s-midnight .CodeMirror-gutters {background: #0F192A; border-right: 1px solid;}
Expand All @@ -29,7 +25,7 @@ span.CodeMirror-matchhighlight { background: #494949 }
.cm-s-midnight span.cm-atom {color: #AE81FF;}
.cm-s-midnight span.cm-number {color: #D1EDFF;}

.cm-s-midnight span.cm-property, .cm-s-tropicaleve span.cm-attribute {color: #A6E22E;}
.cm-s-midnight span.cm-property, .cm-s-midnight span.cm-attribute {color: #A6E22E;}
.cm-s-midnight span.cm-keyword {color: #E83737;}
.cm-s-midnight span.cm-string {color: #1DC116;}

Expand All @@ -45,8 +41,3 @@ span.CodeMirror-matchhighlight { background: #494949 }
text-decoration: underline;
color: white !important;
}

.typ { color: #FFAA3E; }
.atn { color: #606; }
.atv { color: #080; }
.dec { color: #606; }
33 changes: 33 additions & 0 deletions theme/tomorrow-night-eighties.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
Name: Tomorrow Night - Eighties
Author: Chris Kempson
CodeMirror template by Jan T. Sott (https://github.com/idleberg/base16-codemirror)
Original Base16 color scheme by Chris Kempson (https://github.com/chriskempson/base16)
*/

.cm-s-tomorrow-night-eighties.CodeMirror {background: #000000; color: #CCCCCC;}
.cm-s-tomorrow-night-eighties div.CodeMirror-selected {background: #2D2D2D !important;}
.cm-s-tomorrow-night-eighties .CodeMirror-gutters {background: #000000; border-right: 0px;}
.cm-s-tomorrow-night-eighties .CodeMirror-linenumber {color: #515151;}
.cm-s-tomorrow-night-eighties .CodeMirror-cursor {border-left: 1px solid #6A6A6A !important;}

.cm-s-tomorrow-night-eighties span.cm-comment {color: #d27b53;}
.cm-s-tomorrow-night-eighties span.cm-atom {color: #a16a94;}
.cm-s-tomorrow-night-eighties span.cm-number {color: #a16a94;}

.cm-s-tomorrow-night-eighties span.cm-property, .cm-s-tomorrow-night-eighties span.cm-attribute {color: #99cc99;}
.cm-s-tomorrow-night-eighties span.cm-keyword {color: #f2777a;}
.cm-s-tomorrow-night-eighties span.cm-string {color: #ffcc66;}

.cm-s-tomorrow-night-eighties span.cm-variable {color: #99cc99;}
.cm-s-tomorrow-night-eighties span.cm-variable-2 {color: #6699cc;}
.cm-s-tomorrow-night-eighties span.cm-def {color: #f99157;}
.cm-s-tomorrow-night-eighties span.cm-error {background: #f2777a; color: #6A6A6A;}
.cm-s-tomorrow-night-eighties span.cm-bracket {color: #CCCCCC;}
.cm-s-tomorrow-night-eighties span.cm-tag {color: #f2777a;}
.cm-s-tomorrow-night-eighties span.cm-link {color: #a16a94;}

.cm-s-tomorrow-night-eighties .CodeMirror-matchingbracket { text-decoration: underline; color: white !important;}
4 changes: 2 additions & 2 deletions theme/vibrant-ink.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
.cm-s-vibrant-ink .cm-atom { color: #FC0; }
.cm-s-vibrant-ink .cm-number { color: #FFEE98; }
.cm-s-vibrant-ink .cm-def { color: #8DA6CE; }
.cm-s-vibrant-ink span.cm-variable-2, .cm-s-cobalt span.cm-tag { color: #FFC66D }
.cm-s-vibrant-ink span.cm-variable-3, .cm-s-cobalt span.cm-def { color: #FFC66D }
.cm-s-vibrant-ink span.cm-variable-2, .cm-s-vibrant span.cm-tag { color: #FFC66D }
.cm-s-vibrant-ink span.cm-variable-3, .cm-s-vibrant span.cm-def { color: #FFC66D }
.cm-s-vibrant-ink .cm-operator { color: #888; }
.cm-s-vibrant-ink .cm-comment { color: gray; font-weight: bold; }
.cm-s-vibrant-ink .cm-string { color: #A5C25C }
Expand Down