This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
yap-6.3/misc/editors/yap.js

862 lines
30 KiB
JavaScript

// CodeMirror, copyright (c) by Marijn Haverbeke and others
// Distributed under an MIT license: http://codemirror.net/LICENSE
(function(mod) {
if (typeof exports == "object" && typeof module == "object") // CommonJS
mod(require("codemirror/lib/codemirror"));
else if (typeof define == "function" && define.amd) // AMD
define(["codemirror/lib/codemirror"], mod);
else // Plain browser env
mod(CodeMirror);
})(function(CodeMirror) {
"use strict";
CodeMirror.modeInfo = [
{
name : "Prolog",
mime : "text/x-prolog",
mode : "prolog",
ext : [ "pl", "yap", "pro", "P", "prolog" ]
},
{name: "APL", mime: "text/apl", mode: "apl", ext: ["dyalog", "apl"]},
{name: "PGP", mimes: ["application/pgp", "application/pgp-keys", "application/pgp-signature"], mode: "asciiarmor", ext: ["pgp"]},
{name: "ASN.1", mime: "text/x-ttcn-asn", mode: "asn.1", ext: ["asn", "asn1"]},
{name: "Asterisk", mime: "text/x-asterisk", mode: "asterisk", file: /^extensions\.conf$/i},
{name: "Brainfuck", mime: "text/x-brainfuck", mode: "brainfuck", ext: ["b", "bf"]},
{name: "C", mime: "text/x-csrc", mode: "clike", ext: ["c", "h"]},
{name: "C++", mime: "text/x-c++src", mode: "clike", ext: ["cpp", "c++", "cc", "cxx", "hpp", "h++", "hh", "hxx"], alias: ["cpp"]},
{name: "Cobol", mime: "text/x-cobol", mode: "cobol", ext: ["cob", "cpy"]},
{name: "C#", mime: "text/x-csharp", mode: "clike", ext: ["cs"], alias: ["csharp"]},
{name: "Clojure", mime: "text/x-clojure", mode: "clojure", ext: ["clj", "cljc", "cljx"]},
{name: "ClojureScript", mime: "text/x-clojurescript", mode: "clojure", ext: ["cljs"]},
{name: "Closure Stylesheets (GSS)", mime: "text/x-gss", mode: "css", ext: ["gss"]},
{name: "CMake", mime: "text/x-cmake", mode: "cmake", ext: ["cmake", "cmake.in"], file: /^CMakeLists.txt$/},
{name: "CoffeeScript", mime: "text/x-coffeescript", mode: "coffeescript", ext: ["coffee"], alias: ["coffee", "coffee-script"]},
{name: "Common Lisp", mime: "text/x-common-lisp", mode: "commonlisp", ext: ["cl", "lisp", "el"], alias: ["lisp"]},
{name: "Cypher", mime: "application/x-cypher-query", mode: "cypher", ext: ["cyp", "cypher"]},
{name: "Cython", mime: "text/x-cython", mode: "python", ext: ["pyx", "pxd", "pxi"]},
{name: "Crystal", mime: "text/x-crystal", mode: "crystal", ext: ["cr"]},
{name: "CSS", mime: "text/css", mode: "css", ext: ["css"]},
{name: "CQL", mime: "text/x-cassandra", mode: "sql", ext: ["cql"]},
{name: "D", mime: "text/x-d", mode: "d", ext: ["d"]},
{name: "Dart", mimes: ["application/dart", "text/x-dart"], mode: "dart", ext: ["dart"]},
{name: "diff", mime: "text/x-diff", mode: "diff", ext: ["diff", "patch"]},
{name: "Django", mime: "text/x-django", mode: "django"},
{name: "Dockerfile", mime: "text/x-dockerfile", mode: "dockerfile", file: /^Dockerfile$/},
{name: "DTD", mime: "application/xml-dtd", mode: "dtd", ext: ["dtd"]},
{name: "Dylan", mime: "text/x-dylan", mode: "dylan", ext: ["dylan", "dyl", "intr"]},
{name: "EBNF", mime: "text/x-ebnf", mode: "ebnf"},
{name: "ECL", mime: "text/x-ecl", mode: "ecl", ext: ["ecl"]},
{name: "edn", mime: "application/edn", mode: "clojure", ext: ["edn"]},
{name: "Eiffel", mime: "text/x-eiffel", mode: "eiffel", ext: ["e"]},
{name: "Elm", mime: "text/x-elm", mode: "elm", ext: ["elm"]},
{name: "Embedded Javascript", mime: "application/x-ejs", mode: "htmlembedded", ext: ["ejs"]},
{name: "Embedded Ruby", mime: "application/x-erb", mode: "htmlembedded", ext: ["erb"]},
{name: "Erlang", mime: "text/x-erlang", mode: "erlang", ext: ["erl"]},
{name: "Factor", mime: "text/x-factor", mode: "factor", ext: ["factor"]},
{name: "FCL", mime: "text/x-fcl", mode: "fcl"},
{name: "Forth", mime: "text/x-forth", mode: "forth", ext: ["forth", "fth", "4th"]},
{name: "Fortran", mime: "text/x-fortran", mode: "fortran", ext: ["f", "for", "f77", "f90"]},
{name: "F#", mime: "text/x-fsharp", mode: "mllike", ext: ["fs"], alias: ["fsharp"]},
{name: "Gas", mime: "text/x-gas", mode: "gas", ext: ["s"]},
{name: "Gherkin", mime: "text/x-feature", mode: "gherkin", ext: ["feature"]},
{name: "GitHub Flavored Markdown", mime: "text/x-gfm", mode: "gfm", file: /^(readme|contributing|history).md$/i},
{name: "Go", mime: "text/x-go", mode: "go", ext: ["go"]},
{name: "Groovy", mime: "text/x-groovy", mode: "groovy", ext: ["groovy", "gradle"], file: /^Jenkinsfile$/},
{name: "HAML", mime: "text/x-haml", mode: "haml", ext: ["haml"]},
{name: "Haskell", mime: "text/x-haskell", mode: "haskell", ext: ["hs"]},
{name: "Haskell (Literate)", mime: "text/x-literate-haskell", mode: "haskell-literate", ext: ["lhs"]},
{name: "Haxe", mime: "text/x-haxe", mode: "haxe", ext: ["hx"]},
{name: "HXML", mime: "text/x-hxml", mode: "haxe", ext: ["hxml"]},
{name: "ASP.NET", mime: "application/x-aspx", mode: "htmlembedded", ext: ["aspx"], alias: ["asp", "aspx"]},
{name: "HTML", mime: "text/html", mode: "htmlmixed", ext: ["html", "htm"], alias: ["xhtml"]},
{name: "HTTP", mime: "message/http", mode: "http"},
{name: "IDL", mime: "text/x-idl", mode: "idl", ext: ["pro"]},
{name: "Pug", mime: "text/x-pug", mode: "pug", ext: ["jade", "pug"], alias: ["jade"]},
{name: "Java", mime: "text/x-java", mode: "clike", ext: ["java"]},
{name: "Java Server Pages", mime: "application/x-jsp", mode: "htmlembedded", ext: ["jsp"], alias: ["jsp"]},
{name: "JavaScript", mimes: ["text/javascript", "text/ecmascript", "application/javascript", "application/x-javascript", "application/ecmascript"],
mode: "javascript", ext: ["js"], alias: ["ecmascript", "js", "node"]},
{name: "JSON", mimes: ["application/json", "application/x-json"], mode: "javascript", ext: ["json", "map"], alias: ["json5"]},
{name: "JSON-LD", mime: "application/ld+json", mode: "javascript", ext: ["jsonld"], alias: ["jsonld"]},
{name: "JSX", mime: "text/jsx", mode: "jsx", ext: ["jsx"]},
{name: "Jinja2", mime: "null", mode: "jinja2"},
{name: "Julia", mime: "text/x-julia", mode: "julia", ext: ["jl"]},
{name: "Kotlin", mime: "text/x-kotlin", mode: "clike", ext: ["kt"]},
{name: "LESS", mime: "text/x-less", mode: "css", ext: ["less"]},
{name: "LiveScript", mime: "text/x-livescript", mode: "livescript", ext: ["ls"], alias: ["ls"]},
{name: "Lua", mime: "text/x-lua", mode: "lua", ext: ["lua"]},
{name: "Markdown", mime: "text/x-markdown", mode: "markdown", ext: ["markdown", "md", "mkd"]},
{name: "mIRC", mime: "text/mirc", mode: "mirc"},
{name: "MariaDB SQL", mime: "text/x-mariadb", mode: "sql"},
{name: "Mathematica", mime: "text/x-mathematica", mode: "mathematica", ext: ["m", "nb"]},
{name: "Modelica", mime: "text/x-modelica", mode: "modelica", ext: ["mo"]},
{name: "MUMPS", mime: "text/x-mumps", mode: "mumps", ext: ["mps"]},
{name: "MS SQL", mime: "text/x-mssql", mode: "sql"},
{name: "mbox", mime: "application/mbox", mode: "mbox", ext: ["mbox"]},
{name: "MySQL", mime: "text/x-mysql", mode: "sql"},
{name: "Nginx", mime: "text/x-nginx-conf", mode: "nginx", file: /nginx.*\.conf$/i},
{name: "NSIS", mime: "text/x-nsis", mode: "nsis", ext: ["nsh", "nsi"]},
{name: "NTriples", mime: "text/n-triples", mode: "ntriples", ext: ["nt"]},
{name: "Objective C", mime: "text/x-objectivec", mode: "clike", ext: ["m", "mm"], alias: ["objective-c", "objc"]},
{name: "OCaml", mime: "text/x-ocaml", mode: "mllike", ext: ["ml", "mli", "mll", "mly"]},
{name: "Octave", mime: "text/x-octave", mode: "octave", ext: ["m"]},
{name: "Oz", mime: "text/x-oz", mode: "oz", ext: ["oz"]},
{name: "Pascal", mime: "text/x-pascal", mode: "pascal", ext: ["p", "pas"]},
{name: "PEG.js", mime: "null", mode: "pegjs", ext: ["jsonld"]},
{name: "Perl", mime: "text/x-perl", mode: "perl", ext: ["pl", "pm"]},
{name: "PHP", mime: "application/x-httpd-php", mode: "php", ext: ["php", "php3", "php4", "php5", "phtml"]},
{name: "Pig", mime: "text/x-pig", mode: "pig", ext: ["pig"]},
{name: "Plain Text", mime: "text/plain", mode: "null", ext: ["txt", "text", "conf", "def", "list", "log"]},
{name: "PLSQL", mime: "text/x-plsql", mode: "sql", ext: ["pls"]},
{name: "PowerShell", mime: "application/x-powershell", mode: "powershell", ext: ["ps1", "psd1", "psm1"]},
{name: "Properties files", mime: "text/x-properties", mode: "properties", ext: ["properties", "ini", "in"], alias: ["ini", "properties"]},
{name: "ProtoBuf", mime: "text/x-protobuf", mode: "protobuf", ext: ["proto"]},
{name: "Python", mime: "text/x-python", mode: "python", ext: ["BUILD", "bzl", "py", "pyw"], file: /^(BUCK|BUILD)$/},
{name: "Puppet", mime: "text/x-puppet", mode: "puppet", ext: ["pp"]},
{name: "Q", mime: "text/x-q", mode: "q", ext: ["q"]},
{name: "R", mime: "text/x-rsrc", mode: "r", ext: ["r", "R"], alias: ["rscript"]},
{name: "reStructuredText", mime: "text/x-rst", mode: "rst", ext: ["rst"], alias: ["rst"]},
{name: "RPM Changes", mime: "text/x-rpm-changes", mode: "rpm"},
{name: "RPM Spec", mime: "text/x-rpm-spec", mode: "rpm", ext: ["spec"]},
{name: "Ruby", mime: "text/x-ruby", mode: "ruby", ext: ["rb"], alias: ["jruby", "macruby", "rake", "rb", "rbx"]},
{name: "Rust", mime: "text/x-rustsrc", mode: "rust", ext: ["rs"]},
{name: "SAS", mime: "text/x-sas", mode: "sas", ext: ["sas"]},
{name: "Sass", mime: "text/x-sass", mode: "sass", ext: ["sass"]},
{name: "Scala", mime: "text/x-scala", mode: "clike", ext: ["scala"]},
{name: "Scheme", mime: "text/x-scheme", mode: "scheme", ext: ["scm", "ss"]},
{name: "SCSS", mime: "text/x-scss", mode: "css", ext: ["scss"]},
{name: "Shell", mime: "text/x-sh", mode: "shell", ext: ["sh", "ksh", "bash"], alias: ["bash", "sh", "zsh"], file: /^PKGBUILD$/},
{name: "Sieve", mime: "application/sieve", mode: "sieve", ext: ["siv", "sieve"]},
{name: "Slim", mimes: ["text/x-slim", "application/x-slim"], mode: "slim", ext: ["slim"]},
{name: "Smalltalk", mime: "text/x-stsrc", mode: "smalltalk", ext: ["st"]},
{name: "Smarty", mime: "text/x-smarty", mode: "smarty", ext: ["tpl"]},
{name: "Solr", mime: "text/x-solr", mode: "solr"},
{name: "Soy", mime: "text/x-soy", mode: "soy", ext: ["soy"], alias: ["closure template"]},
{name: "SPARQL", mime: "application/sparql-query", mode: "sparql", ext: ["rq", "sparql"], alias: ["sparul"]},
{name: "Spreadsheet", mime: "text/x-spreadsheet", mode: "spreadsheet", alias: ["excel", "formula"]},
{name: "SQL", mime: "text/x-sql", mode: "sql", ext: ["sql"]},
{name: "SQLite", mime: "text/x-sqlite", mode: "sql"},
{name: "Squirrel", mime: "text/x-squirrel", mode: "clike", ext: ["nut"]},
{name: "Stylus", mime: "text/x-styl", mode: "stylus", ext: ["styl"]},
{name: "Swift", mime: "text/x-swift", mode: "swift", ext: ["swift"]},
{name: "sTeX", mime: "text/x-stex", mode: "stex"},
{name: "LaTeX", mime: "text/x-latex", mode: "stex", ext: ["text", "ltx"], alias: ["tex"]},
{name: "SystemVerilog", mime: "text/x-systemverilog", mode: "verilog", ext: ["v"]},
{name: "Tcl", mime: "text/x-tcl", mode: "tcl", ext: ["tcl"]},
{name: "Textile", mime: "text/x-textile", mode: "textile", ext: ["textile"]},
{name: "TiddlyWiki ", mime: "text/x-tiddlywiki", mode: "tiddlywiki"},
{name: "Tiki wiki", mime: "text/tiki", mode: "tiki"},
{name: "TOML", mime: "text/x-toml", mode: "toml", ext: ["toml"]},
{name: "Tornado", mime: "text/x-tornado", mode: "tornado"},
{name: "troff", mime: "text/troff", mode: "troff", ext: ["1", "2", "3", "4", "5", "6", "7", "8", "9"]},
{name: "TTCN", mime: "text/x-ttcn", mode: "ttcn", ext: ["ttcn", "ttcn3", "ttcnpp"]},
{name: "TTCN_CFG", mime: "text/x-ttcn-cfg", mode: "ttcn-cfg", ext: ["cfg"]},
{name: "Turtle", mime: "text/turtle", mode: "turtle", ext: ["ttl"]},
{name: "TypeScript", mime: "application/typescript", mode: "javascript", ext: ["ts"], alias: ["ts"]},
{name: "TypeScript-JSX", mime: "text/typescript-jsx", mode: "jsx", ext: ["tsx"], alias: ["tsx"]},
{name: "Twig", mime: "text/x-twig", mode: "twig"},
{name: "Web IDL", mime: "text/x-webidl", mode: "webidl", ext: ["webidl"]},
{name: "VB.NET", mime: "text/x-vb", mode: "vb", ext: ["vb"]},
{name: "VBScript", mime: "text/vbscript", mode: "vbscript", ext: ["vbs"]},
{name: "Velocity", mime: "text/velocity", mode: "velocity", ext: ["vtl"]},
{name: "Verilog", mime: "text/x-verilog", mode: "verilog", ext: ["v"]},
{name: "VHDL", mime: "text/x-vhdl", mode: "vhdl", ext: ["vhd", "vhdl"]},
{name: "Vue.js Component", mimes: ["script/x-vue", "text/x-vue"], mode: "vue", ext: ["vue"]},
{name: "XML", mimes: ["application/xml", "text/xml"], mode: "xml", ext: ["xml", "xsl", "xsd", "svg"], alias: ["rss", "wsdl", "xsd"]},
{name: "XQuery", mime: "application/xquery", mode: "xquery", ext: ["xy", "xquery"]},
{name: "Yacas", mime: "text/x-yacas", mode: "yacas", ext: ["ys"]},
{name: "YAML", mimes: ["text/x-yaml", "text/yaml"], mode: "yaml", ext: ["yaml", "yml"], alias: ["yml"]},
{name: "Z80", mime: "text/x-z80", mode: "z80", ext: ["z80"]},
{name: "mscgen", mime: "text/x-mscgen", mode: "mscgen", ext: ["mscgen", "mscin", "msc"]},
{name: "xu", mime: "text/x-xu", mode: "mscgen", ext: ["xu"]},
{name: "msgenny", mime: "text/x-msgenny", mode: "mscgen", ext: ["msgenny"]}
];
// Ensure all modes have a mime property for backwards compatibility
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.mimes) info.mime = info.mimes[0];
}
CodeMirror.findModeByMIME = function(mime) {
mime = mime.toLowerCase();
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.mime == mime) return info;
if (info.mimes) for (var j = 0; j < info.mimes.length; j++)
if (info.mimes[j] == mime) return info;
}
if (/\+xml$/.test(mime)) return CodeMirror.findModeByMIME("application/xml")
if (/\+json$/.test(mime)) return CodeMirror.findModeByMIME("application/json")
};
CodeMirror.findModeByExtension = function(ext) {
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.ext) for (var j = 0; j < info.ext.length; j++)
if (info.ext[j] == ext) return info;
}
};
CodeMirror.findModeByFileName = function(filename) {
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.file && info.file.test(filename)) return info;
}
var dot = filename.lastIndexOf(".");
var ext = dot > -1 && filename.substring(dot + 1, filename.length);
if (ext) return CodeMirror.findModeByExtension(ext);
};
CodeMirror.findModeByName = function(name) {
name = name.toLowerCase();
for (var i = 0; i < CodeMirror.modeInfo.length; i++) {
var info = CodeMirror.modeInfo[i];
if (info.name.toLowerCase() == name) return info;
if (info.alias) for (var j = 0; j < info.alias.length; j++)
if (info.alias[j].toLowerCase() == name) return info;
}
};
CodeMirror.defineMode("prolog", function(cmConfig) {
function chain(stream, state, f) {
state.tokenize = f;
return f(stream, state);
}
/*******************************
* CONFIG DATA *
*******************************/
var config = { quasiQuotations: false, /* {|Syntax||Quotation|} */
dicts: false, /* tag{k:v, ...} */
unicodeEscape: true, /* \uXXXX and \UXXXXXXXX */
multiLineQuoted: true, /* "...\n..." */
groupedIntegers: false /* 10 000 or 10_000 */
};
var quoteType = { '"': "string",
"'": "qatom",
"`": "bqstring"
};
var isSingleEscChar = /[abref\\'"nrtsv]/;
var isOctalDigit = /[0-7]/;
var isHexDigit = /[0-9a-fA-F]/;
var isSymbolChar = /[-#$&*+./:<=>?@\\^~]/; /* Prolog glueing symbols chars */
var isSoloChar = /[[\]{}(),;|]/; /* Prolog solo chars] */
var isNeck = /^(:-|-->)$/;
var isControlOp = /^(,|;|->|\*->|\\+|\|)$/;
/*******************************
* CHARACTER ESCAPES *
*******************************/
function readDigits(stream, re, count) {
if ( count > 0 ) {
while( count-- > 0 ) {
if ( !re.test(stream.next()) )
return false;
}
} else {
while ( re.test(stream.peek()) )
stream.next();
}
return true;
}
function readEsc(stream) {
var next = stream.next();
if ( isSingleEscChar.test(next) )
return true;
switch( next )
{ case "u":
if ( config.unicodeEscape )
return readDigits(stream, isHexDigit, 4); /* SWI */
return false;
case "U":
if ( config.unicodeEscape )
return readDigits(stream, isHexDigit, 8); /* SWI */
return false;
case null: return true; /* end of line */
case "c": stream.eatSpace(); return true;
case "x": return readDigits(stream, isHexDigit, 2);
}
if ( isOctalDigit.test(next) ) {
if ( !readDigits(stream, isOctalDigit, -1) )
return false;
if ( stream.peek() == "\\" ) /* SWI: optional closing \ */
stream.next();
return true;
}
return false;
}
function nextUntilUnescaped(stream, state, end) {
var next;
while ((next = stream.next()) != null) {
if ( next == end && end != stream.peek() )
{ state.nesting.pop();
return false;
}
if ( next == "\\" )
{ if ( !readEsc(stream) )
return false;
}
}
return config.multiLineQuoted;
}
/*******************************
* CONTEXT NESTING *
*******************************/
function nesting(state) {
return state.nesting.slice(-1)[0];
}
/* Called on every non-comment token */
function setArg1(state) {
var nest = nesting(state);
if ( nest ) {
if ( nest.arg == 0 ) /* nested in a compound */
nest.arg = 1;
else if ( nest.type == "control" )
state.goalStart = false;
} else
state.goalStart = false;
}
function setArgAlignment(state) {
var nest = nesting(state);
if ( nest && !nest.alignment && nest.arg != undefined ) {
if ( nest.arg == 0 )
nest.alignment = nest.leftCol ? nest.leftCol+4 : nest.column+4;
else
nest.alignment = nest.column+1;
}
}
function nextArg(state) {
var nest = nesting(state);
if ( nest ) {
if ( nest.arg ) /* nested in a compound */
nest.arg++;
else if ( nest.type == "control" )
state.goalStart = true; /* FIXME: also needed for ; and -> */
} else
state.goalStart = true;
}
function isControl(state) { /* our terms are goals */
var nest = nesting(state);
if ( nest ) {
if ( nest.type == "control" ) {
return true;
}
return false;
} else
return state.inBody;
}
// Used as scratch variables to communicate multiple values without
// consing up tons of objects.
var type, content;
function ret(tp, style, cont) {
type = tp; content = cont;
return style;
}
function peekSpace(stream) { /* TBD: handle block comment as space */
if ( stream.eol() ||
/[\s%]/.test(stream.peek()) )
return true;
return false;
}
/*******************************
* SUB TOKENISERS *
*******************************/
function plTokenBase(stream, state) {
var ch = stream.next();
if ( ch == "(" ) {
if ( state.lastType == "functor" ) {
state.nesting.push({ functor: state.functorName,
column: stream.column(),
leftCol: state.functorColumn,
arg: 0
});
delete state.functorName;
delete state.functorColumn;
} else {
state.nesting.push({ type: "control",
closeColumn: stream.column(),
alignment: stream.column()+4
});
}
return ret("solo", null, "(");
}
if ( ch == "{" && state.lastType == "tag" ) {
state.nesting.push({ tag: state.tagName,
column: stream.column(),
leftCol: state.tagColumn,
arg: 0
});
delete state.tagName;
delete state.tagColumn;
return ret("dict_open", null);
}
if ( ch == "/" && stream.eat("*") )
return chain(stream, state, plTokenComment);
if ( ch == "%" ) {
stream.skipToEnd();
return ret("comment", "comment");
}
setArg1(state);
if ( isSoloChar.test(ch) ) {
switch ( ch )
{ case ")":
state.nesting.pop();
break;
case "]":
state.nesting.pop();
return ret("list_close", null);
case "}":
{ var nest = nesting(state);
var type = (nest && nest.tag) ? "dict_close" : "brace_term_close";
state.nesting.pop();
return ret(type, null);
}
case ",":
if ( stream.eol() )
state.commaAtEOL = true;
nextArg(state);
/*FALLTHROUGH*/
case ";":
if ( isControl(state) )
state.goalStart = true;
break;
case "[":
state.nesting.push({ type: "list",
closeColumn: stream.column(),
alignment: stream.column()+2
});
return ret("list_open", null);
break;
case "{":
if ( config.quasiQuotations && stream.eat("|") ) {
state.nesting.push({ type: "quasi-quotation",
alignment: stream.column()+1
});
return ret("qq_open", "qq_open");
} else {
state.nesting.push({ type: "curly",
closeColumn: stream.column(),
alignment: stream.column()+2
});
return ret("brace_term_open", null);
}
break;
case "|":
if ( config.quasiQuotations ) {
if ( stream.eat("|") ) {
state.tokenize = plTokenQuasiQuotation;
return ret("qq_sep", "qq_sep");
} else if ( stream.eat("}") ) {
state.nesting.pop();
return ret("qq_close", "qq_close");
}
}
if ( isControl(state) )
state.goalStart = true;
break;
}
return ret("solo", null, ch);
}
if (ch == '"' || ch == "'" || ch == "`")
{ state.nesting.push({ type: "quoted",
alignment: stream.column()+1
});
return chain(stream, state, plTokenString(ch));
}
if ( ch == "0" ) {
if ( stream.eat(/x/i)) {
stream.eatWhile(/[\da-f]/i);
return ret("number", "number");
}
if ( stream.eat(/o/i)) {
stream.eatWhile(/[0-7]/i);
return ret("number", "number");
}
if ( stream.eat(/'/) ) { /* 0' */
var next = stream.next();
if ( next == "\\" ) {
if ( !readEsc(stream) )
return ret("error", "error");
}
return ret("code", "code");
}
}
if ( /\d/.test(ch) || /[+-]/.test(ch) && stream.eat(/\d/)) {
if ( config.groupedIntegers )
stream.match(/^\d*((_|\s+)\d+)*(?:\.\d+)?(?:[eE][+\-]?\d+)?/);
else
stream.match(/^\d*(?:\.\d+)?(?:[eE][+\-]?\d+)?/);
return ret(ch == "-" ? "neg-number" :
ch == "+" ? "pos-number" :
"number");
}
if ( isSymbolChar.test(ch) ) {
stream.eatWhile(isSymbolChar);
var atom = stream.current();
if ( atom == "." && peekSpace(stream) ) {
if ( nesting(state) ) {
return ret("fullstop", "error", atom);
} else {
} return ret("fullstop", "fullstop", atom);
} else if ( isNeck.test(atom) ) {
return ret("neck", "neck", atom);
} else if ( isControl(state) && isControlOp.test(atom) ) {
state.goalStart = true;
return ret("symbol", "operator", atom);
} else
return ret("symbol", "operator", atom);
}
stream.eatWhile(/[\w_]/);
var word = stream.current();
if ( stream.peek() == "{" && config.dicts ) {
state.tagName = word; /* tmp state extension */
state.tagColumn = stream.column();
return ret("tag", "tag", word);
} else if ( ch == "_" ) {
if ( word.length == 1 ) {
return ret("var", "anon", word);
} else {
var sec = word.charAt(1);
if ( sec == sec.toUpperCase() )
return ret("var", "var-2", word);
}
return ret("var", "var", word);
} else if ( ch == ch.toUpperCase() ) {
return ret("var", "var", word);
} else if ( stream.peek() == "(" ) {
state.functorName = word; /* tmp state extension */
state.functorColumn = stream.column();
return ret("functor", "functor", word);
} else
return ret("atom", "atom", word);
}
function plTokenString(quote) {
return function(stream, state) {
if (!nextUntilUnescaped(stream, state, quote)) {
state.tokenize = plTokenBase;
if ( stream.peek() == "(" ) { /* 'quoted functor'() */
var word = stream.current();
state.functorName = word; /* tmp state extension */
return ret("functor", "functor", word);
}
if ( stream.peek() == "{" && config.dicts ) { /* 'quoted tag'{} */
var word = stream.current();
state.tagName = word; /* tmp state extension */
return ret("tag", "tag", word);
}
}
return ret(quoteType[quote], quoteType[quote]);
};
}
function plTokenQuasiQuotation(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "}" && maybeEnd) {
state.tokenize = plTokenBase;
stream.backUp(2);
break;
}
maybeEnd = (ch == "|");
}
return ret("qq_content", "qq_content");
}
function plTokenComment(stream, state) {
var maybeEnd = false, ch;
while (ch = stream.next()) {
if (ch == "/" && maybeEnd) {
state.tokenize = plTokenBase;
break;
}
maybeEnd = (ch == "*");
}
return ret("comment", "comment");
}
/*******************************
* ACTIVE KEYS *
*******************************/
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Support if-then-else layout like this:
goal :-
( Condition
-> IfTrue
; IfFalse
).
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
CodeMirror.commands.prologStartIfThenElse = function(cm) {
var start = cm.getCursor("start");
var token = cm.getTokenAt(start, true);
if ( token.state.goalStart == true )
{ cm.replaceSelection("( ", "end");
return;
}
return CodeMirror.Pass;
}
CodeMirror.commands.prologStartThen = function(cm) {
var start = cm.getCursor("start");
var token = cm.getTokenAt(start, true);
/* FIXME: These functions are copied from prolog.js. How
can we reuse these?
*/
function nesting(state) {
var len = state.nesting.length;
if ( len > 0 )
return state.nesting[len-1];
return null;
}
function isControl(state) { /* our terms are goals */
var nest = nesting(state);
if ( nest ) {
if ( nest.type == "control" ) {
return true;
}
return false;
} else
return state.inBody;
}
if ( start.ch == token.end &&
token.type == "operator" &&
token.string == "-" &&
isControl(token.state) )
{ cm.replaceSelection("> ", "end");
return;
}
return CodeMirror.Pass;
}
CodeMirror.commands.prologStartElse = function(cm) {
var start = cm.getCursor("start");
var token = cm.getTokenAt(start, true);
if ( token.start == 0 && start.ch == token.end &&
!/\S/.test(token.string) )
{ cm.replaceSelection("; ", "end");
return;
}
return CodeMirror.Pass;
}
CodeMirror.defineOption("prologKeys", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("prolog");
if ( val ) {
var map = { name: "prolog",
"'('": "prologStartIfThenElse",
"'>'": "prologStartThen",
"';'": "prologStartElse",
"Ctrl-L": "refreshHighlight"
};
cm.addKeyMap(map);
}
});
});
//Default (SWI-)Prolog operator table. To be used later to enhance the
//offline experience.
var ops = { "-->": { p:1200, t:"xfx" },
":-": [ { p:1200, t:"xfx" },
{ p:1200, t:"fx" }
],
"?-": { p:1200, t:"fx" },
"dynamic": { p:1150, t:"fx" },
"discontiguous": { p:1150, t:"fx" },
"initialization": { p:1150, t:"fx" },
"meta_predicate": { p:1150, t:"fx" },
"module_transparent": { p:1150, t:"fx" },
"multifile": { p:1150, t:"fx" },
"thread_local": { p:1150, t:"fx" },
"volatile": { p:1150, t:"fx" },
";": { p:1100, t:"xfy" },
"|": { p:1100, t:"xfy" },
"->": { p:1050, t:"xfy" },
"*->": { p:1050, t:"xfy" },
",": { p:1000, t:"xfy" },
"\\+": { p:900, t:"fy" },
"~": { p:900, t:"fx" },
"<": { p:700, t:"xfx" },
"=": { p:700, t:"xfx" },
"=..": { p:700, t:"xfx" },
"=@=": { p:700, t:"xfx" },
"=:=": { p:700, t:"xfx" },
"=<": { p:700, t:"xfx" },
"==": { p:700, t:"xfx" },
"=\\=": { p:700, t:"xfx" },
">": { p:700, t:"xfx" },
">=": { p:700, t:"xfx" },
"@<": { p:700, t:"xfx" },
"@=<": { p:700, t:"xfx" },
"@>": { p:700, t:"xfx" },
"@>=": { p:700, t:"xfx" },
"\\=": { p:700, t:"xfx" },
"\\==": { p:700, t:"xfx" },
"is": { p:700, t:"xfx" },
":": { p:600, t:"xfy" },
"+": [ { p:500, t:"yfx" },
{ p:200, t:"fy" }
],
"-": [ { p:500, t:"yfx" },
{ p:200, t:"fy" }
],
"/\\": { p:500, t:"yfx" },
"\\/": { p:500, t:"yfx" },
"xor": { p:500, t:"yfx" },
"?": { p:500, t:"fx" },
"*": { p:400, t:"yfx" },
"/": { p:400, t:"yfx" },
"//": { p:400, t:"yfx" },
"rdiv": { p:400, t:"yfx" },
"<<": { p:400, t:"yfx" },
">>": { p:400, t:"yfx" },
"mod": { p:400, t:"yfx" },
"rem": { p:400, t:"yfx" },
"**": { p:200, t:"xfx" },
"^": { p:200, t:"xfy" },
"\\": { p:200, t:"fy" }
};
/*******************************
* RETURN OBJECT *
*******************************/
return {
startState: function() {
return {
tokenize: plTokenBase,
inBody: false,
goalStart: false,
lastType: null,
nesting: new Array(), /* ([{}]) nesting FIXME: copy this */
curTerm: null, /* term index in metainfo */
curToken: null /* token in term */
};
},
token: function(stream, state) {
var nest;
if ( state.curTerm == null /* && parserConfig.metainfo */ ) {
state.curTerm = 0;
state.curToken = 0;
}
if ( stream.sol() )
delete state.commaAtEOL;
if ( state.tokenize == plTokenBase && stream.eatSpace() ) {
if ( stream.eol() )
setArgAlignment(state);
return null;
}
var style = state.tokenize(stream, state);
if ( stream.eol() )
setArgAlignment(state);
if ( type == "neck" ) {
state.inBody = true;
state.goalStart = true;
} else if ( type == "fullstop" ) {
state.inBody = false;
state.goalStart = false;
}
state.lastType = type;
//if ( typeof(parserConfig.enrich) == "function" )
// style = parserConfig.enrich(stream, state, type, content, style);
return style;
},
indent: function(state, textAfter) {
if (state.tokenize == plTokenComment) return CodeMirror.Pass;
var nest;
if ( (nest=nesting(state)) ) {
if ( nest.closeColumn && !state.commaAtEOL )
return nest.closeColumn;
return nest.alignment;
}
if ( !state.inBody )
return 0;
return 4;
},
theme: "prolog",
blockCommentStart: "/*", /* continuecomment.js support */
blockCommentEnd: "*/",
blockCommentContinue: " * ",
lineComment: "%",
});
}
});