liquid_cms 0.3.1.0 → 0.3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (136) hide show
  1. data/CHANGELOG.rdoc +10 -0
  2. data/Gemfile +0 -3
  3. data/README.rdoc +16 -2
  4. data/TODO.rdoc +0 -2
  5. data/app/controllers/cms/assets_controller.rb +20 -6
  6. data/app/controllers/cms/components_controller.rb +11 -3
  7. data/app/controllers/cms/pages_controller.rb +15 -4
  8. data/app/helpers/cms/common_helper.rb +31 -32
  9. data/app/liquid/cms_paperclip_extension.rb +75 -3
  10. data/app/liquid/tags/{data_tag.rb → cms/data_tag.rb} +0 -0
  11. data/app/models/cms/asset.rb +1 -1
  12. data/app/models/cms/component.rb +3 -3
  13. data/app/views/cms/assets/_form.html.erb +1 -2
  14. data/app/views/cms/assets/update.js.rjs +1 -0
  15. data/app/views/cms/components/update.js.rjs +1 -0
  16. data/app/views/cms/pages/_form.html.erb +3 -3
  17. data/app/views/cms/pages/update.js.rjs +1 -0
  18. data/app/views/layouts/cms.html.erb +4 -3
  19. data/config/initializers/cms/simple_form.rb +70 -12
  20. data/config/initializers/cms/simple_form_updates.rb +9 -3
  21. data/config/locales/cms/en.yml +6 -0
  22. data/lib/generators/liquid_cms/install_generator.rb +5 -1
  23. data/lib/generators/liquid_cms/templates/migration_rev2.rb +13 -0
  24. data/lib/generators/liquid_cms/templates/public/cms/codemirror/LICENSE +16 -20
  25. data/lib/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.css +68 -0
  26. data/lib/generators/liquid_cms/templates/public/cms/codemirror/lib/codemirror.js +2197 -0
  27. data/lib/generators/liquid_cms/templates/public/cms/codemirror/lib/overlay.js +51 -0
  28. data/lib/generators/liquid_cms/templates/public/cms/codemirror/lib/runmode.js +27 -0
  29. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/clike.js +247 -0
  30. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/clike/index.html +102 -0
  31. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/clojure.js +207 -0
  32. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/clojure/index.html +85 -0
  33. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/LICENSE +22 -0
  34. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/coffeescript.js +325 -0
  35. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/coffeescript/index.html +722 -0
  36. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/css/css.js +124 -0
  37. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/css/index.html +56 -0
  38. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.css +3 -0
  39. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/diff.js +13 -0
  40. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/diff/index.html +99 -0
  41. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/haskell.js +242 -0
  42. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/haskell/index.html +60 -0
  43. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/htmlmixed.js +79 -0
  44. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/htmlmixed/index.html +52 -0
  45. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/index.html +78 -0
  46. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/javascript/javascript.js +352 -0
  47. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/index.html +38 -0
  48. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/jinja2/jinja2.js +42 -0
  49. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/index.html +72 -0
  50. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/lua/lua.js +140 -0
  51. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/index.html +340 -0
  52. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.css +10 -0
  53. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/markdown/markdown.js +230 -0
  54. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/index.html +33 -0
  55. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/ntriples/ntriples.js +172 -0
  56. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/LICENSE +7 -0
  57. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/index.html +49 -0
  58. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/pascal/pascal.js +138 -0
  59. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/php/index.html +49 -0
  60. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/php/php.js +116 -0
  61. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/index.html +63 -0
  62. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/plsql/plsql.js +217 -0
  63. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/python/LICENSE.txt +21 -0
  64. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/python/index.html +123 -0
  65. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/python/python.js +320 -0
  66. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/r/LICENSE +24 -0
  67. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/r/index.html +74 -0
  68. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/r/r.js +141 -0
  69. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/index.html +526 -0
  70. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.css +75 -0
  71. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/rst/rst.js +333 -0
  72. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/LICENSE +24 -0
  73. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/index.html +172 -0
  74. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/ruby/ruby.js +195 -0
  75. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/index.html +65 -0
  76. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/scheme/scheme.js +202 -0
  77. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/index.html +56 -0
  78. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/smalltalk/smalltalk.js +122 -0
  79. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/index.html +41 -0
  80. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/sparql/sparql.js +143 -0
  81. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/index.html +96 -0
  82. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/stex/stex.js +167 -0
  83. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/index.html +103 -0
  84. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/velocity/velocity.js +146 -0
  85. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/index.html +42 -0
  86. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/xml/xml.js +231 -0
  87. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/index.html +60 -0
  88. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/xmlpure/xmlpure.js +481 -0
  89. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/index.html +68 -0
  90. data/lib/generators/liquid_cms/templates/public/cms/codemirror/mode/yaml/yaml.js +95 -0
  91. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/cobalt.css +17 -0
  92. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/default.css +19 -0
  93. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/eclipse.css +24 -0
  94. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/elegant.css +9 -0
  95. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/neat.css +8 -0
  96. data/lib/generators/liquid_cms/templates/public/cms/codemirror/theme/night.css +20 -0
  97. data/lib/generators/liquid_cms/templates/public/cms/javascripts/cms.js +1 -1
  98. data/lib/generators/liquid_cms/templates/public/cms/javascripts/codemirror_custom.js +96 -0
  99. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/codemirror_changes.css +26 -0
  100. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/liquid.css +7 -0
  101. data/lib/generators/liquid_cms/templates/public/cms/stylesheets/simple_form.css +0 -8
  102. data/lib/liquid_cms/version.rb +1 -1
  103. data/liquid_cms.gemspec +1 -1
  104. data/test/functional/assets_controller_test.rb +35 -20
  105. data/test/functional/components_controller_test.rb +15 -5
  106. data/test/functional/pages_controller_test.rb +19 -6
  107. data/test/rails_app/Gemfile +1 -2
  108. data/test/rails_app/config/locales/cms/en.yml +26 -4
  109. data/test/rails_app/db/migrate/20110511161859_create_liquid_cms_upgrade_rev2.rb +13 -0
  110. data/test/unit/asset_test.rb +1 -1
  111. data/test/unit/component_test.rb +1 -1
  112. metadata +89 -32
  113. data/generators/liquid_cms/templates/migration_rev1.rb +0 -38
  114. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/csscolors.css +0 -55
  115. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/docs.css +0 -158
  116. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/font.js +0 -15
  117. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/jscolors.css +0 -59
  118. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/sparqlcolors.css +0 -43
  119. data/lib/generators/liquid_cms/templates/public/cms/codemirror/css/xmlcolors.css +0 -55
  120. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/codemirror.js +0 -582
  121. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/editor.js +0 -1671
  122. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/highlight.js +0 -68
  123. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/mirrorframe.js +0 -81
  124. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsecss.js +0 -161
  125. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsedummy.js +0 -32
  126. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsehtmlmixed.js +0 -93
  127. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsejavascript.js +0 -359
  128. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsesparql.js +0 -162
  129. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/parsexml.js +0 -291
  130. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/select.js +0 -699
  131. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/stringstream.js +0 -159
  132. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenize.js +0 -57
  133. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/tokenizejavascript.js +0 -174
  134. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/undo.js +0 -413
  135. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/unittests.js +0 -44
  136. data/lib/generators/liquid_cms/templates/public/cms/codemirror/js/util.js +0 -133
@@ -0,0 +1,195 @@
1
+ CodeMirror.defineMode("ruby", function(config, parserConfig) {
2
+ function wordObj(words) {
3
+ var o = {};
4
+ for (var i = 0, e = words.length; i < e; ++i) o[words[i]] = true;
5
+ return o;
6
+ }
7
+ var keywords = wordObj([
8
+ "alias", "and", "BEGIN", "begin", "break", "case", "class", "def", "defined?", "do", "else",
9
+ "elsif", "END", "end", "ensure", "false", "for", "if", "in", "module", "next", "not", "or",
10
+ "redo", "rescue", "retry", "return", "self", "super", "then", "true", "undef", "unless",
11
+ "until", "when", "while", "yield", "nil", "raise", "throw", "catch", "fail", "loop", "callcc",
12
+ "caller", "lambda", "proc", "public", "protected", "private", "require", "load",
13
+ "require_relative", "extend", "autoload"
14
+ ]);
15
+ var indentWords = wordObj(["def", "class", "case", "for", "while", "do", "module", "then",
16
+ "unless", "catch", "loop", "proc"]);
17
+ var dedentWords = wordObj(["end", "until"]);
18
+ var matching = {"[": "]", "{": "}", "(": ")"};
19
+ var curPunc;
20
+
21
+ function chain(newtok, stream, state) {
22
+ state.tokenize.push(newtok);
23
+ return newtok(stream, state);
24
+ }
25
+
26
+ function tokenBase(stream, state) {
27
+ curPunc = null;
28
+ if (stream.sol() && stream.match("=begin") && stream.eol()) {
29
+ state.tokenize.push(readBlockComment);
30
+ return "comment";
31
+ }
32
+ if (stream.eatSpace()) return null;
33
+ var ch = stream.next();
34
+ if (ch == "`" || ch == "'" || ch == '"' || ch == "/") {
35
+ return chain(readQuoted(ch, "string", ch == '"'), stream, state);
36
+ } else if (ch == "%") {
37
+ var style, embed = false;
38
+ if (stream.eat("s")) style = "atom";
39
+ else if (stream.eat(/[WQ]/)) { style = "string"; embed = true; }
40
+ else if (stream.eat(/[wxqr]/)) style = "string";
41
+ var delim = stream.eat(/[^\w\s]/);
42
+ if (!delim) return "operator";
43
+ if (matching.propertyIsEnumerable(delim)) delim = matching[delim];
44
+ return chain(readQuoted(delim, style, embed, true), stream, state);
45
+ } else if (ch == "#") {
46
+ stream.skipToEnd();
47
+ return "comment";
48
+ } else if (ch == "<" && stream.eat("<")) {
49
+ stream.eat("-");
50
+ stream.eat(/[\'\"\`]/);
51
+ var match = stream.match(/^\w+/);
52
+ stream.eat(/[\'\"\`]/);
53
+ if (match) return chain(readHereDoc(match[0]), stream, state);
54
+ return null;
55
+ } else if (ch == "0") {
56
+ if (stream.eat("x")) stream.eatWhile(/[\da-fA-F]/);
57
+ else if (stream.eat("b")) stream.eatWhile(/[01]/);
58
+ else stream.eatWhile(/[0-7]/);
59
+ return "number";
60
+ } else if (/\d/.test(ch)) {
61
+ stream.match(/^[\d_]*(?:\.[\d_]+)?(?:[eE][+\-]?[\d_]+)?/);
62
+ return "number";
63
+ } else if (ch == "?") {
64
+ while (stream.match(/^\\[CM]-/)) {}
65
+ if (stream.eat("\\")) stream.eatWhile(/\w/);
66
+ else stream.next();
67
+ return "string";
68
+ } else if (ch == ":") {
69
+ if (stream.eat("'")) return chain(readQuoted("'", "atom", false), stream, state);
70
+ if (stream.eat('"')) return chain(readQuoted('"', "atom", true), stream, state);
71
+ stream.eatWhile(/[\w\?]/);
72
+ return "atom";
73
+ } else if (ch == "@") {
74
+ stream.eat("@");
75
+ stream.eatWhile(/[\w\?]/);
76
+ return "variable-2";
77
+ } else if (ch == "$") {
78
+ stream.next();
79
+ stream.eatWhile(/[\w\?]/);
80
+ return "variable-3";
81
+ } else if (/\w/.test(ch)) {
82
+ stream.eatWhile(/[\w\?]/);
83
+ if (stream.eat(":")) return "atom";
84
+ return "ident";
85
+ } else if (ch == "|" && (state.varList || state.lastTok == "{" || state.lastTok == "do")) {
86
+ curPunc = "|";
87
+ return null;
88
+ } else if (/[\(\)\[\]{}\\;]/.test(ch)) {
89
+ curPunc = ch;
90
+ return null;
91
+ } else if (ch == "-" && stream.eat(">")) {
92
+ return "arrow";
93
+ } else if (/[=+\-\/*:\.^%<>~|]/.test(ch)) {
94
+ stream.eatWhile(/[=+\-\/*:\.^%<>~|]/);
95
+ return "operator";
96
+ } else {
97
+ return null;
98
+ }
99
+ }
100
+
101
+ function tokenBaseUntilBrace() {
102
+ var depth = 1;
103
+ return function(stream, state) {
104
+ if (stream.peek() == "}") {
105
+ depth--;
106
+ if (depth == 0) {
107
+ state.tokenize.pop();
108
+ return state.tokenize[state.tokenize.length-1](stream, state);
109
+ }
110
+ } else if (stream.peek() == "{") {
111
+ depth++;
112
+ }
113
+ return tokenBase(stream, state);
114
+ };
115
+ }
116
+ function readQuoted(quote, style, embed, unescaped) {
117
+ return function(stream, state) {
118
+ var escaped = false, ch;
119
+ while ((ch = stream.next()) != null) {
120
+ if (ch == quote && (unescaped || !escaped)) {
121
+ state.tokenize.pop();
122
+ break;
123
+ }
124
+ if (embed && ch == "#" && !escaped && stream.eat("{")) {
125
+ state.tokenize.push(tokenBaseUntilBrace(arguments.callee));
126
+ break;
127
+ }
128
+ escaped = !escaped && ch == "\\";
129
+ }
130
+ return style;
131
+ };
132
+ }
133
+ function readHereDoc(phrase) {
134
+ return function(stream, state) {
135
+ if (stream.match(phrase)) state.tokenize.pop();
136
+ else stream.skipToEnd();
137
+ return "string";
138
+ };
139
+ }
140
+ function readBlockComment(stream, state) {
141
+ if (stream.sol() && stream.match("=end") && stream.eol())
142
+ state.tokenize.pop();
143
+ stream.skipToEnd();
144
+ return "comment";
145
+ }
146
+
147
+ return {
148
+ startState: function() {
149
+ return {tokenize: [tokenBase],
150
+ indented: 0,
151
+ context: {type: "top", indented: -config.indentUnit},
152
+ continuedLine: false,
153
+ lastTok: null,
154
+ varList: false};
155
+ },
156
+
157
+ token: function(stream, state) {
158
+ if (stream.sol()) state.indented = stream.indentation();
159
+ var style = state.tokenize[state.tokenize.length-1](stream, state), kwtype;
160
+ if (style == "ident") {
161
+ var word = stream.current();
162
+ style = keywords.propertyIsEnumerable(stream.current()) ? "keyword"
163
+ : /^[A-Z]/.test(word) ? "tag"
164
+ : (state.lastTok == "def" || state.lastTok == "class" || state.varList) ? "def"
165
+ : "variable";
166
+ if (indentWords.propertyIsEnumerable(word)) kwtype = "indent";
167
+ else if (dedentWords.propertyIsEnumerable(word)) kwtype = "dedent";
168
+ else if (word == "if" && stream.column() == stream.indentation()) kwtype = "indent";
169
+ }
170
+ if (curPunc || (style && style != "comment")) state.lastTok = word || curPunc || style;
171
+ if (curPunc == "|") state.varList = !state.varList;
172
+
173
+ if (kwtype == "indent" || /[\(\[\{]/.test(curPunc))
174
+ state.context = {prev: state.context, type: curPunc || style, indented: state.indented};
175
+ else if ((kwtype == "dedent" || /[\)\]\}]/.test(curPunc)) && state.context.prev)
176
+ state.context = state.context.prev;
177
+
178
+ if (stream.eol())
179
+ state.continuedLine = (curPunc == "\\" || style == "operator");
180
+ return style;
181
+ },
182
+
183
+ indent: function(state, textAfter) {
184
+ if (state.tokenize[state.tokenize.length-1] != tokenBase) return 0;
185
+ var firstChar = textAfter && textAfter.charAt(0);
186
+ var ct = state.context;
187
+ var closing = ct.type == matching[firstChar] ||
188
+ ct.type == "keyword" && /^(?:end|until|else|elsif|when)\b/.test(textAfter);
189
+ return ct.indented + (closing ? 0 : config.indentUnit) +
190
+ (state.continuedLine ? config.indentUnit : 0);
191
+ }
192
+ };
193
+ });
194
+
195
+ CodeMirror.defineMIME("text/x-ruby", "ruby");
@@ -0,0 +1,65 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <title>CodeMirror 2: Scheme mode</title>
5
+ <link rel="stylesheet" href="../../lib/codemirror.css">
6
+ <script src="../../lib/codemirror.js"></script>
7
+ <script src="scheme.js"></script>
8
+ <link rel="stylesheet" href="../../theme/default.css">
9
+ <style>.CodeMirror {background: #f8f8f8;}</style>
10
+ <link rel="stylesheet" href="../../css/docs.css">
11
+ </head>
12
+ <body>
13
+ <h1>CodeMirror 2: Scheme mode</h1>
14
+ <form><textarea id="code" name="code">
15
+ ; See if the input starts with a given symbol.
16
+ (define (match-symbol input pattern)
17
+ (cond ((null? (remain input)) #f)
18
+ ((eqv? (car (remain input)) pattern) (r-cdr input))
19
+ (else #f)))
20
+
21
+ ; Allow the input to start with one of a list of patterns.
22
+ (define (match-or input pattern)
23
+ (cond ((null? pattern) #f)
24
+ ((match-pattern input (car pattern)))
25
+ (else (match-or input (cdr pattern)))))
26
+
27
+ ; Allow a sequence of patterns.
28
+ (define (match-seq input pattern)
29
+ (if (null? pattern)
30
+ input
31
+ (let ((match (match-pattern input (car pattern))))
32
+ (if match (match-seq match (cdr pattern)) #f))))
33
+
34
+ ; Match with the pattern but no problem if it does not match.
35
+ (define (match-opt input pattern)
36
+ (let ((match (match-pattern input (car pattern))))
37
+ (if match match input)))
38
+
39
+ ; Match anything (other than '()), until pattern is found. The rather
40
+ ; clumsy form of requiring an ending pattern is needed to decide where
41
+ ; the end of the match is. If none is given, this will match the rest
42
+ ; of the sentence.
43
+ (define (match-any input pattern)
44
+ (cond ((null? (remain input)) #f)
45
+ ((null? pattern) (f-cons (remain input) (clear-remain input)))
46
+ (else
47
+ (let ((accum-any (collector)))
48
+ (define (match-pattern-any input pattern)
49
+ (cond ((null? (remain input)) #f)
50
+ (else (accum-any (car (remain input)))
51
+ (cond ((match-pattern (r-cdr input) pattern))
52
+ (else (match-pattern-any (r-cdr input) pattern))))))
53
+ (let ((retval (match-pattern-any input (car pattern))))
54
+ (if retval
55
+ (f-cons (accum-any) retval)
56
+ #f))))))
57
+ </textarea></form>
58
+ <script>
59
+ var editor = CodeMirror.fromTextArea(document.getElementById("code"), {});
60
+ </script>
61
+
62
+ <p><strong>MIME types defined:</strong> <code>text/x-scheme</code>.</p>
63
+
64
+ </body>
65
+ </html>
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Author: Koh Zi Han, based on implementation by Koh Zi Chun
3
+ */
4
+ CodeMirror.defineMode("scheme", function (config, mode) {
5
+ var BUILTIN = "builtin", COMMENT = "comment", STRING = "string",
6
+ ATOM = "atom", NUMBER = "number", BRACKET = "bracket", KEYWORD="keyword";
7
+ var INDENT_WORD_SKIP = 2, KEYWORDS_SKIP = 1;
8
+
9
+ function makeKeywords(str) {
10
+ var obj = {}, words = str.split(" ");
11
+ for (var i = 0; i < words.length; ++i) obj[words[i]] = true;
12
+ return obj;
13
+ }
14
+
15
+ var keywords = makeKeywords("λ case-lambda call/cc class define-class exit-handler field import inherit init-field interface let*-values let-values let/ec mixin opt-lambda override protect provide public rename require require-for-syntax syntax syntax-case syntax-error unit/sig unless when with-syntax and begin call-with-current-continuation call-with-input-file call-with-output-file case cond define define-syntax delay do dynamic-wind else for-each if lambda let let* let-syntax letrec letrec-syntax map or syntax-rules abs acos angle append apply asin assoc assq assv atan boolean? caar cadr call-with-input-file call-with-output-file call-with-values car cdddar cddddr cdr ceiling char->integer char-alphabetic? char-ci<=? char-ci<? char-ci=? char-ci>=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? char-upcase char-upper-case? char-whitespace? char<=? char<? char=? char>=? char>? char? close-input-port close-output-port complex? cons cos current-input-port current-output-port denominator display eof-object? eq? equal? eqv? eval even? exact->inexact exact? exp expt #f floor force gcd imag-part inexact->exact inexact? input-port? integer->char integer? interaction-environment lcm length list list->string list->vector list-ref list-tail list? load log magnitude make-polar make-rectangular make-string make-vector max member memq memv min modulo negative? newline not null-environment null? number->string number? numerator odd? open-input-file open-output-file output-port? pair? peek-char port? positive? procedure? quasiquote quote quotient rational? rationalize read read-char real-part real? remainder reverse round scheme-report-environment set! set-car! set-cdr! sin sqrt string string->list string->number string->symbol string-append string-ci<=? string-ci<? string-ci=? string-ci>=? string-ci>? string-copy string-fill! string-length string-ref string-set! string<=? string<? string=? string>=? string>? string? substring symbol->string symbol? #t tan transcript-off transcript-on truncate values vector vector->list vector-fill! vector-length vector-ref vector-set! with-input-from-file with-output-to-file write write-char zero?");
16
+ var indentKeys = makeKeywords("define let letrec let* lambda");
17
+
18
+
19
+ function stateStack(indent, type, prev) { // represents a state stack object
20
+ this.indent = indent;
21
+ this.type = type;
22
+ this.prev = prev;
23
+ }
24
+
25
+ function pushStack(state, indent, type) {
26
+ state.indentStack = new stateStack(indent, type, state.indentStack);
27
+ }
28
+
29
+ function popStack(state) {
30
+ state.indentStack = state.indentStack.prev;
31
+ }
32
+
33
+ /**
34
+ * Scheme numbers are complicated unfortunately.
35
+ * Checks if we're looking at a number, which might be possibly a fraction.
36
+ * Also checks that it is not part of a longer identifier. Returns true/false accordingly.
37
+ */
38
+ function isNumber(ch, stream){
39
+ if(/[0-9]/.exec(ch) != null){
40
+ stream.eatWhile(/[0-9]/);
41
+ stream.eat(/\//);
42
+ stream.eatWhile(/[0-9]/);
43
+ if (stream.eol() || !(/[a-zA-Z\-\_\/]/.exec(stream.peek()))) return true;
44
+ stream.backUp(stream.current().length - 1); // undo all the eating
45
+ }
46
+ return false;
47
+ }
48
+
49
+ return {
50
+ startState: function () {
51
+ return {
52
+ indentStack: null,
53
+ indentation: 0,
54
+ mode: false,
55
+ sExprComment: false
56
+ };
57
+ },
58
+
59
+ token: function (stream, state) {
60
+ if (state.indentStack == null && stream.sol()) {
61
+ // update indentation, but only if indentStack is empty
62
+ state.indentation = stream.indentation();
63
+ }
64
+
65
+ // skip spaces
66
+ if (stream.eatSpace()) {
67
+ return null;
68
+ }
69
+ var returnType = null;
70
+
71
+ switch(state.mode){
72
+ case "string": // multi-line string parsing mode
73
+ var next, escaped = false;
74
+ while ((next = stream.next()) != null) {
75
+ if (next == "\"" && !escaped) {
76
+
77
+ state.mode = false;
78
+ break;
79
+ }
80
+ escaped = !escaped && next == "\\";
81
+ }
82
+ returnType = STRING; // continue on in scheme-string mode
83
+ break;
84
+ case "comment": // comment parsing mode
85
+ var next, maybeEnd = false;
86
+ while ((next = stream.next()) != null) {
87
+ if (next == "#" && maybeEnd) {
88
+
89
+ state.mode = false;
90
+ break;
91
+ }
92
+ maybeEnd = (next == "|");
93
+ }
94
+ returnType = COMMENT;
95
+ break;
96
+ case "s-expr-comment": // s-expr commenting mode
97
+ state.mode = false;
98
+ if(stream.peek() == "(" || stream.peek() == "["){
99
+ // actually start scheme s-expr commenting mode
100
+ state.sExprComment = 0;
101
+ }else{
102
+ // if not we just comment the entire of the next token
103
+ stream.eatWhile(/[^/s]/); // eat non spaces
104
+ returnType = COMMENT;
105
+ break;
106
+ }
107
+ default: // default parsing mode
108
+ var ch = stream.next();
109
+
110
+ if (ch == "\"") {
111
+ state.mode = "string";
112
+ returnType = STRING;
113
+
114
+ } else if (ch == "'") {
115
+ returnType = ATOM;
116
+ } else if (ch == '#') {
117
+ if (stream.eat("|")) { // Multi-line comment
118
+ state.mode = "comment"; // toggle to comment mode
119
+ returnType = COMMENT;
120
+ } else if (stream.eat(/[tf]/)) { // #t/#f (atom)
121
+ returnType = ATOM;
122
+ } else if (stream.eat(';')) { // S-Expr comment
123
+ state.mode = "s-expr-comment";
124
+ returnType = COMMENT;
125
+ }
126
+
127
+ } else if (ch == ";") { // comment
128
+ stream.skipToEnd(); // rest of the line is a comment
129
+ returnType = COMMENT;
130
+ } else if (ch == "-"){
131
+
132
+ if(!isNaN(parseInt(stream.peek()))){
133
+ stream.eatWhile(/[\/0-9]/);
134
+ returnType = NUMBER;
135
+ }else{
136
+ returnType = null;
137
+ }
138
+ } else if (isNumber(ch,stream)){
139
+ returnType = NUMBER;
140
+ } else if (ch == "(" || ch == "[") {
141
+ var keyWord = ''; var indentTemp = stream.column();
142
+ /**
143
+ Either
144
+ (indent-word ..
145
+ (non-indent-word ..
146
+ (;something else, bracket, etc.
147
+ */
148
+
149
+ while ((letter = stream.eat(/[^\s\(\[\;\)\]]/)) != null) {
150
+ keyWord += letter;
151
+ }
152
+
153
+ if (keyWord.length > 0 && indentKeys.propertyIsEnumerable(keyWord)) { // indent-word
154
+
155
+ pushStack(state, indentTemp + INDENT_WORD_SKIP, ch);
156
+ } else { // non-indent word
157
+ // we continue eating the spaces
158
+ stream.eatSpace();
159
+ if (stream.eol() || stream.peek() == ";") {
160
+ // nothing significant after
161
+ // we restart indentation 1 space after
162
+ pushStack(state, indentTemp + 1, ch);
163
+ } else {
164
+ pushStack(state, indentTemp + stream.current().length, ch); // else we match
165
+ }
166
+ }
167
+ stream.backUp(stream.current().length - 1); // undo all the eating
168
+
169
+ if(typeof state.sExprComment == "number") state.sExprComment++;
170
+
171
+ returnType = BRACKET;
172
+ } else if (ch == ")" || ch == "]") {
173
+ returnType = BRACKET;
174
+ if (state.indentStack != null && state.indentStack.type == (ch == ")" ? "(" : "[")) {
175
+ popStack(state);
176
+
177
+ if(typeof state.sExprComment == "number"){
178
+ if(--state.sExprComment == 0){
179
+ returnType = COMMENT; // final closing bracket
180
+ state.sExprComment = false; // turn off s-expr commenting mode
181
+ }
182
+ }
183
+ }
184
+ } else {
185
+ stream.eatWhile(/[\w\$_\-]/);
186
+
187
+ if (keywords && keywords.propertyIsEnumerable(stream.current())) {
188
+ returnType = BUILTIN;
189
+ }else returnType = null;
190
+ }
191
+ }
192
+ return (typeof state.sExprComment == "number") ? COMMENT : returnType;
193
+ },
194
+
195
+ indent: function (state, textAfter) {
196
+ if (state.indentStack == null) return state.indentation;
197
+ return state.indentStack.indent;
198
+ }
199
+ };
200
+ });
201
+
202
+ CodeMirror.defineMIME("text/x-scheme", "scheme");