diff --git a/src/lang-scala.js b/src/lang-scala.js new file mode 100644 index 00000000..e0d675a2 --- /dev/null +++ b/src/lang-scala.js @@ -0,0 +1,54 @@ +// Copyright (C) 2010 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + +/** + * @fileoverview + * Registers a language handler for Scala. + * + * Derived from http://lampsvn.epfl.ch/svn-repos/scala/scala-documentation/trunk/src/reference/SyntaxSummary.tex + * + * @author mikesamuel@gmail.com + */ + +PR.registerLangHandler( + PR.createSimpleLexer( + [ + // Whitespace + [PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'], + // A double or single quoted string + // or a triple double-quoted multi-line string. + [PR.PR_STRING, + /^(?:"(?:(?:""(?:""?(?!")|[^\\"]|\\.)*"{0,3})|(?:[^"\r\n\\]|\\.)*"?))/, + null, '"'], + [PR.PR_LITERAL, /^`(?:[^\r\n\\`]|\\.)*`?/, null, '`'], + [PR.PR_PUNCTUATION, /^[!#%&()*+,\-:;<=>?@\[\\\]^{|}~]+/, null, + '!#%&()*+,-:;<=>?@[\\]^{|}~'] + ], + [ + // A symbol literal is a single quote followed by an identifier with no + // single quote following + // A character literal has single quotes on either side + [PR.PR_STRING, /^'(?:[^\r\n\\']|\\(?:'|[^\r\n']+))'/], + [PR.PR_LITERAL, /^'[a-zA-Z_$][\w$]*(?!['$\w])/], + [PR.PR_KEYWORD, /^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/], + [PR.PR_LITERAL, /^(?:true|false|null|this)\b/], + [PR.PR_LITERAL, /^(?:(?:0(?:[0-7]+|X[0-9A-F]+))L?|(?:(?:0|[1-9][0-9]*)(?:(?:\.[0-9]+)?(?:E[+\-]?[0-9]+)?F?|L?))|\\.[0-9]+(?:E[+\-]?[0-9]+)?F?)/i], + // Treat upper camel case identifiers as types. + [PR.PR_TYPE, /^[$_]*[A-Z][_$A-Z0-9]*[a-z][\w$]*/], + [PR.PR_PLAIN, /^[$a-zA-Z_][\w$]*/], + [PR.PR_COMMENT, /^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/], + [PR.PR_PUNCTUATION, /^(?:\.+|\/)/] + ]), + ['scala']); diff --git a/src/prettify.js b/src/prettify.js index f95e4f01..1262dda5 100644 --- a/src/prettify.js +++ b/src/prettify.js @@ -1096,7 +1096,8 @@ window['_pr_isIE6'] = function () { // on IE. // Doing this on other browsers breaks lots of stuff since \r\n is // treated as two newlines on Firefox. - ? (isIE678 === 6 ? ' \r\n' : ' \r') + ? (isIE678 === 6 ? ' \r\n' : + isIE678 === 7 ? ' 
\r' : ' \r') // IE collapses multiple adjacent
s into 1 line break. // Prefix every newline with ' ' to prevent such behavior. //   is the same as   but works in XML as well as HTML. @@ -1360,8 +1361,7 @@ window['_pr_isIE6'] = function () { recombineTagsAndDecorations(job); } catch (e) { if ('console' in window) { - console['log'](e); - console['trace'](); + console['log'](e && e['stack'] ? e['stack'] : e); } } } diff --git a/tests/prettify_test.html b/tests/prettify_test.html index b63ced76..358e9cd7 100644 --- a/tests/prettify_test.html +++ b/tests/prettify_test.html @@ -26,6 +26,8 @@ onerror="alert('Error: failed to load ' + this.src)"> + @@ -1163,6 +1165,65 @@

YAML mode

] : !!str "value" } + +

Scala mode

+
+/* comment 1 */
+/*
+comment 2
+*/
+/* comment / * comment 3 **/
+// strings
+"Hello, World!", "\n",
+`an-identifier`, `\n`,
+'A', '\n',
+'aSymbol,
+"""Hello,
+World""", """Hello,\nWorld""",
+"""Hello, "World"!""",
+"""Hello, \"World\""""
+
+// Numbers
+0
+0123
+0xa0
+0XA0L
+123
+123.45
+1.50F
+0.50
+.50
+123e-1
+123.45e+1
+1.50e2
+0.50e-6
+.50e+42f
+
+// Values
+false, true, null, this;
+
+// Keywords
+class MyClass;
+import foo.bar;
+package baz;
+
+// From scala-lang.org/node/242
+def act() {
+  var pongCount = 0
+  loop {
+    react {
+      case Ping =>
+        if (pongCount % 1000 == 0)
+          Console.println("Pong: ping "+pongCount)
+        sender ! Pong
+        pongCount = pongCount + 1
+      case Stop =>
+        Console.println("Pong: stop")
+        exit()
+    }
+  }
+}
+