Skip to content
This repository was archived by the owner on Apr 22, 2020. It is now read-only.

Commit 781168e

Browse files
author
mikesamuel
committed
added a language handler for lispy languages
1 parent fb81836 commit 781168e

File tree

4 files changed

+216
-9
lines changed

4 files changed

+216
-9
lines changed

README.html

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,17 @@ <h3>Which languages does it work for?</h3>
6767
should work on a number of languages including C and friends,
6868
Java, Python, Bash, SQL, HTML, XML, CSS, Javascript, and Makefiles.
6969
It works passably on Ruby, PHP and Awk and a decent subset of Perl, but,
70-
because of commenting conventions, doesn't work on Smalltalk, Lisp-like, or
70+
because of commenting conventions, doesn't work on Smalltalk, or
7171
CAML-like languages.</p>
7272

73+
<p>LISPy languages are supported via an extension:
74+
<a href="http://code.google.com/p/google-code-prettify/source/browse/trunk/src/lang-lisp.js"
75+
><code>lang-lisp.js</code></a>.</p>
76+
77+
<p>If you'd like to add an extension for your favorite language, please
78+
look at lang-lisp.js and file an <a href="http://code.google.com/p/google-code-prettify/issues/list">issue</a> including your language extension,
79+
and a testcase.</p>
80+
7381
<h3>How do I specify which language my code is in?</h3>
7482
<p>You don't need to specify the language since <code>prettyprint()</code>
7583
will guess. You can specify a language by specifying the language extension

src/lang-lisp.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright (C) 2008 Google Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
16+
17+
/**
18+
* @fileoverview
19+
* Registers a language handler for Common Lisp and related languages.
20+
*
21+
*
22+
* To use, include prettify.js and this file in your HTML page.
23+
* Then put your code in an HTML tag like
24+
* <pre class="prettyprint lang-lisp">(my lisp code)</pre>
25+
* The lang-cl class identifies the language as common lisp.
26+
* This file supports the following language extensions:
27+
* lang-cl - Common Lisp
28+
* lang-el - Emacs Lisp
29+
* lang-lisp - Lisp
30+
* lang-scm - Scheme
31+
*
32+
*
33+
* I used http://www.devincook.com/goldparser/doc/meta-language/grammar-LISP.htm
34+
* as the basis, but added line comments that start with ; and changed the atom
35+
* production to disallow unquoted semicolons.
36+
*
37+
* "Name" = 'LISP'
38+
* "Author" = 'John McCarthy'
39+
* "Version" = 'Minimal'
40+
* "About" = 'LISP is an abstract language that organizes ALL'
41+
* | 'data around "lists".'
42+
*
43+
* "Start Symbol" = [s-Expression]
44+
*
45+
* {Atom Char} = {Printable} - {Whitespace} - [()"\'']
46+
*
47+
* Atom = ( {Atom Char} | '\'{Printable} )+
48+
*
49+
* [s-Expression] ::= [Quote] Atom
50+
* | [Quote] '(' [Series] ')'
51+
* | [Quote] '(' [s-Expression] '.' [s-Expression] ')'
52+
*
53+
* [Series] ::= [s-Expression] [Series]
54+
* |
55+
*
56+
* [Quote] ::= '' !Quote = do not evaluate
57+
* |
58+
*
59+
*
60+
* I used <a href="http://gigamonkeys.com/book/">Practical Common Lisp</a> as
61+
* the basis for the reserved word list.
62+
*
63+
*
64+
65+
*/
66+
67+
PR.registerLangHandler(
68+
PR.createSimpleLexer(
69+
[
70+
['opn', /^\(/, null, '('],
71+
['clo', /^\)/, null, ')'],
72+
// A line comment that starts with ;
73+
[PR.PR_COMMENT, /^;[^\r\n]*/, null, ';'],
74+
// Whitespace
75+
[PR.PR_PLAIN, /^[\t\n\r \xA0]+/, null, '\t\n\r \xA0'],
76+
// A double quoted, possibly multi-line, string.
77+
[PR.PR_STRING, /^\"(?:[^\"\\]|\\[\s\S])*(?:\"|$)/, null, '"']
78+
],
79+
[
80+
[PR.PR_KEYWORD, /^(?:block|c[ad]+r|catch|cons|defun|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/, null],
81+
[PR.PR_LITERAL,
82+
/^[+\-]?(?:\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[eEdD][+\-]?\d+)?)/],
83+
// A single quote possibly followed by a word that optionally ends with
84+
// = ! or ?.
85+
[PR.PR_LITERAL,
86+
/^\'(?:-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?)?/],
87+
// A word that optionally ends with = ! or ?.
88+
[PR.PR_PLAIN,
89+
/^-*(?:\w|\\[\x21-\x7e])(?:[\w-]*|\\[\x21-\x7e])[=!?]?/],
90+
// A printable non-space non-special character
91+
[PR.PR_PUNCTUATION, /^[^\w\t\n\r \xA0()\"\\\';]+/]
92+
]),
93+
['cl', 'el', 'lisp', 'scm']);

src/prettify.js

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,10 @@ var PR_TAB_WIDTH = 8;
6262
*/
6363
var PR_normalizedHtml;
6464

65-
/** Register a language handler for the given file extensions.
66-
* @param {function (sourceCode : string) : Array.<number|string>} a function
67-
* from source code to a list of decorations.
68-
* @param {Array.<string>} fileExtensions
65+
/** Contains functions for creating and registering new language handlers.
66+
* @namespace
6967
*/
70-
var PR_registerLangHandler;
68+
var PR;
7169

7270
/** Pretty print a chunk of code.
7371
*
@@ -655,14 +653,17 @@ function pr_isIE6() {
655653
function sourceDecorator(options) {
656654
var shortcutStylePatterns = [], fallthroughStylePatterns = [];
657655
if (options.tripleQuotedStrings) {
656+
// '''multi-line-string''', 'single-line-string', and double-quoted
658657
shortcutStylePatterns.push(
659658
[PR_STRING, /^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,
660659
null, '\'"']);
661660
} else if (options.multiLineStrings) {
661+
// 'multi-line-string', "multi-line-string"
662662
shortcutStylePatterns.push(
663663
[PR_STRING, /^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,
664664
null, '\'"`']);
665665
} else {
666+
// 'single-line-string', "single-line-string"
666667
shortcutStylePatterns.push(
667668
[PR_STRING,
668669
/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,
@@ -983,9 +984,19 @@ function pr_isIE6() {
983984

984985
/** Maps language-specific file extensions to handlers. */
985986
var langHandlerRegistry = {};
987+
/** Register a language handler for the given file extensions.
988+
* @param {function (sourceCode : string) : Array.<number|string>} a function
989+
* from source code to a list of decorations.
990+
* @param {Array.<string>} fileExtensions
991+
*/
986992
function registerLangHandler(handler, fileExtensions) {
987993
for (var i = fileExtensions.length; --i >= 0;) {
988-
langHandlerRegistry[fileExtensions[i]] = handler;
994+
var ext = fileExtensions[i];
995+
if (!langHandlerRegistry.hasOwnProperty(ext)) {
996+
langHandlerRegistry[ext] = handler;
997+
} else if ('console' in window) {
998+
console.log('cannot override language handler %s', ext);
999+
}
9891000
}
9901001
}
9911002
registerLangHandler(decorateSource, ['default-code']);
@@ -1175,5 +1186,21 @@ function pr_isIE6() {
11751186
window.PR_normalizedHtml = normalizedHtml;
11761187
window.prettyPrintOne = prettyPrintOne;
11771188
window.prettyPrint = prettyPrint;
1178-
window.PR_registerLangHandler = registerLangHandler;
1189+
window.PR = {
1190+
createSimpleLexer: createSimpleLexer,
1191+
registerLangHandler: registerLangHandler,
1192+
sourceDecorator: sourceDecorator,
1193+
PR_ATTRIB_NAME: PR_ATTRIB_NAME,
1194+
PR_ATTRIB_VALUE: PR_ATTRIB_VALUE,
1195+
PR_COMMENT: PR_COMMENT,
1196+
PR_DECLARATION: PR_DECLARATION,
1197+
PR_KEYWORD: PR_KEYWORD,
1198+
PR_LITERAL: PR_LITERAL,
1199+
PR_PLAIN: PR_PLAIN,
1200+
PR_PUNCTUATION: PR_PUNCTUATION,
1201+
PR_SOURCE: PR_SOURCE,
1202+
PR_STRING: PR_STRING,
1203+
PR_TAG: PR_TAG,
1204+
PR_TYPE: PR_TYPE
1205+
};
11791206
})();

tests/prettify_test.html

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
<title>Code Prettifier</title>
55
<script src="../src/prettify.js" type="text/javascript"
66
onerror="alert('Error: failed to load ' + this.src)"></script>
7+
<script src="../src/lang-lisp.js" type="text/javascript"
8+
onerror="alert('Error: failed to load ' + this.src)"></script>
79
<script type="text/javascript">
810
// get accurate timing
911
PR_SHOULD_USE_CONTINUATION = false;
@@ -706,6 +708,46 @@ <h1>Bug 21 - code doesn't copy and paste well in IE</h1>
706708
<p>To test this bug, disable overriding of PR_isIE6 above, and copy and paste
707709
the above into Notepad.</p>
708710

711+
<h1>Bug 42 - Lisp Syntax Highlighting</h1>
712+
<pre class="prettyprint lang-el" id="issue42"
713+
>; -*- mode: lisp -*-
714+
715+
(defun back-six-lines () (interactive) (forward-line -6))
716+
(defun forward-six-lines () (interactive) (forward-line 6))
717+
718+
(global-set-key "\M-l" 'goto-line)
719+
(global-set-key "\C-z" 'advertised-undo)
720+
(global-set-key [C-insert] 'clipboard-kill-ring-save)
721+
(global-set-key [S-insert] 'clipboard-yank)
722+
(global-set-key [C-up] 'back-six-lines)
723+
(global-set-key [C-down] 'forward-six-lines)
724+
725+
(setq visible-bell t)
726+
(setq user-mail-address "[email protected]")
727+
(setq default-major-mode 'text-mode)
728+
729+
(setenv "TERM" "emacs")
730+
(c-set-offset 'case-label 2)
731+
(setq c-basic-offset 2)
732+
(setq perl-indent-level 2)
733+
(setq delete-key-deletes-forward t)
734+
(setq indent-tabs-mode nil)
735+
736+
;; Text mode
737+
(add-hook 'text-mode-hook
738+
'(lambda ()
739+
(turn-on-auto-fill)
740+
)
741+
)
742+
743+
;; Fundamental mode
744+
(add-hook 'fundamental-mode-hook
745+
'(lambda ()
746+
(turn-on-auto-fill)
747+
)
748+
)
749+
</pre>
750+
709751
</body>
710752

711753
<script type="text/javascript">
@@ -1631,7 +1673,44 @@ <h1>Bug 21 - code doesn't copy and paste well in IE</h1>
16311673
'&nbsp; &nbsp; `END`PUN&lt;`END`TAGtitle`END`PUN&gt;`END`PLNTest`END' +
16321674
'`PUN&lt;/`END`TAGtitle`END`PUN&gt;`END`PLN<br>' +
16331675
'&nbsp; `END`PUN&lt;/`END`TAGhead`END`PUN&gt;`END`PLN<br>' +
1634-
'`END`PUN&lt;/`END`TAGhtml`END`PUN&gt;`END')
1676+
'`END`PUN&lt;/`END`TAGhtml`END`PUN&gt;`END'),
1677+
issue42: (
1678+
'`COM; -*- mode: lisp -*-`END`PLN<br>' +
1679+
'<br>' +
1680+
'`END`OPN(`END`KWDdefun`END`PLN back-six-lines `END`OPN(`END`CLO)`END`PLN `END`OPN(`END`PLNinteractive`END`CLO)`END`PLN `END`OPN(`END`PLNforward-line `END`LIT-6`END`CLO))`END`PLN<br>' +
1681+
'`END`OPN(`END`KWDdefun`END`PLN forward-six-lines `END`OPN(`END`CLO)`END`PLN `END`OPN(`END`PLNinteractive`END`CLO)`END`PLN `END`OPN(`END`PLNforward-line `END`LIT6`END`CLO))`END`PLN<br>' +
1682+
'<br>' +
1683+
'`END`OPN(`END`PLNglobal-set-key `END`STR"\\M-l"`END`PLN `END`LIT\'goto-line`END`CLO)`END`PLN<br>' +
1684+
'`END`OPN(`END`PLNglobal-set-key `END`STR"\\C-z"`END`PLN `END`LIT\'advertised-undo`END`CLO)`END`PLN<br>' +
1685+
'`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-insert`END`PUN]`END`PLN `END`LIT\'clipboard-kill-ring-save`END`CLO)`END`PLN<br>' +
1686+
'`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNS-insert`END`PUN]`END`PLN `END`LIT\'clipboard-yank`END`CLO)`END`PLN<br>' +
1687+
'`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-up`END`PUN]`END`PLN `END`LIT\'back-six-lines`END`CLO)`END`PLN<br>' +
1688+
'`END`OPN(`END`PLNglobal-set-key `END`PUN[`END`PLNC-down`END`PUN]`END`PLN `END`LIT\'forward-six-lines`END`CLO)`END`PLN<br>' +
1689+
'<br>' +
1690+
'`END`OPN(`END`KWDsetq`END`PLN visible-bell `END`KWDt`END`CLO)`END`PLN<br>' +
1691+
'`END`OPN(`END`KWDsetq`END`PLN user-mail-address `END`STR"[email protected]"`END`CLO)`END`PLN<br>' +
1692+
'`END`OPN(`END`KWDsetq`END`PLN default-major-mode `END`LIT\'text-mode`END`CLO)`END`PLN<br>' +
1693+
'<br>' +
1694+
'`END`OPN(`END`PLNsetenv `END`STR"TERM"`END`PLN `END`STR"emacs"`END`CLO)`END`PLN<br>' +
1695+
'`END`OPN(`END`PLNc-set-offset `END`LIT\'case-label`END`PLN `END`LIT2`END`CLO)`END`PLN<br>' +
1696+
'`END`OPN(`END`KWDsetq`END`PLN c-basic-offset `END`LIT2`END`CLO)`END`PLN<br>' +
1697+
'`END`OPN(`END`KWDsetq`END`PLN perl-indent-level `END`LIT2`END`CLO)`END`PLN<br>' +
1698+
'`END`OPN(`END`KWDsetq`END`PLN delete-key-deletes-forward `END`KWDt`END`CLO)`END`PLN<br>' +
1699+
'`END`OPN(`END`KWDsetq`END`PLN indent-tabs-mode `END`KWDnil`END`CLO)`END`PLN<br>' +
1700+
'<br>' +
1701+
'`END`COM;; Text mode`END`PLN<br>' +
1702+
'`END`OPN(`END`PLNadd-hook `END`LIT\'text-mode-hook`END`PLN <br>' +
1703+
'&nbsp; `END`LIT\'`END`OPN(`END`KWDlambda`END`PLN `END`OPN(`END`CLO)`END`PLN<br>' +
1704+
'&nbsp; &nbsp; &nbsp;`END`OPN(`END`PLNturn-on-auto-fill`END`CLO)`END`PLN<br>' +
1705+
'&nbsp; &nbsp;`END`CLO)`END`PLN<br>' +
1706+
'`END`CLO)`END`PLN<br>' +
1707+
'<br>' +
1708+
'`END`COM;; Fundamental mode`END`PLN<br>' +
1709+
'`END`OPN(`END`PLNadd-hook `END`LIT\'fundamental-mode-hook`END`PLN <br>' +
1710+
'&nbsp; `END`LIT\'`END`OPN(`END`KWDlambda`END`PLN `END`OPN(`END`CLO)`END`PLN<br>' +
1711+
'&nbsp; &nbsp; &nbsp;`END`OPN(`END`PLNturn-on-auto-fill`END`CLO)`END`PLN<br>' +
1712+
'&nbsp; &nbsp;`END`CLO)`END`PLN<br>' +
1713+
'`END`CLO)`END')
16351714
};
16361715

16371716

0 commit comments

Comments
 (0)