diff --git a/.gitmodules b/.gitmodules
index 577dd069..e69de29b 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +0,0 @@
-[submodule "js/josh.js"]
- path = js/josh.js
- url = git://github.com/sdether/josh.js
diff --git a/docs/TODO b/docs/TODO
index 0d5d28b0..22321ff0 100644
--- a/docs/TODO
+++ b/docs/TODO
@@ -32,6 +32,7 @@ Java:
- step9_interop
Javascript:
+ - switch to himera page/styling for online console
Make:
- allow '_' in make variable names
diff --git a/js/Makefile b/js/Makefile
index 87afef18..02678fbc 100644
--- a/js/Makefile
+++ b/js/Makefile
@@ -4,9 +4,9 @@ TESTS = tests/types.js tests/reader.js tests/step5_tco.js
SOURCES_BASE = node_readline.js types.js reader.js printer.js
SOURCES_LISP = env.js core.js stepA_more.js
SOURCES = $(SOURCES_BASE) $(SOURCES_LISP)
-WEB_SOURCES = $(SOURCES:node_readline.js=josh_readline.js)
+WEB_SOURCES = $(SOURCES:node_readline.js=jq_readline.js)
-all: node_modules mal.js mal_web.js
+all: node_modules mal.js web/mal.js
node_modules:
npm install
@@ -16,11 +16,11 @@ mal.js: $(SOURCES)
cat $+ | grep -v "= *require('./" >> $@
chmod +x $@
-mal_web.js: $(WEB_SOURCES)
+web/mal.js: $(WEB_SOURCES)
cat $+ | grep -v "= *require('./" > $@
clean:
- rm -f mal.js mal_web.js
+ rm -f mal.js web/mal.js
.PHONY: stats tests $(TESTS)
diff --git a/js/josh.js b/js/josh.js
deleted file mode 160000
index 25723755..00000000
--- a/js/josh.js
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 257237550ce9c02cfc426918845e636c763c49bc
diff --git a/js/josh_readline.js b/js/josh_readline.js
deleted file mode 100644
index 3d1a3d42..00000000
--- a/js/josh_readline.js
+++ /dev/null
@@ -1,420 +0,0 @@
-/* ------------------------------------------------------------------------*
- * Copyright 2013 Arne F. Claassen
- *
- * 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.
- *-------------------------------------------------------------------------*/
-
-var Josh = Josh || {};
-(function(root, $, _) {
- Josh.Shell = function(config) {
- config = config || {};
-
- // instance fields
- var _console = config.console || (Josh.Debug && root.console ? root.console : {
- log: function() {
- }
- });
- var _prompt = config.prompt || 'jsh$';
- var _action = config.action || function(str) {
- return "
No action defined for: " + str + "
";
- };
- var _shell_view_id = config.shell_view_id || 'shell-view';
- var _shell_panel_id = config.shell_panel_id || 'shell-panel';
- var _input_id = config.input_id || 'shell-cli';
- var _blinktime = config.blinktime || 500;
- var _history = config.history || new Josh.History();
- var _readline = config.readline || new Josh.ReadLine({history: _history, console: _console});
- var _active = false;
- var _cursor_visible = false;
- var _activationHandler;
- var _deactivationHandler;
- var _cmdHandlers = {
- clear: {
- exec: function(cmd, args, callback) {
- $(id(_input_id)).parent().empty();
- callback();
- }
- },
- help: {
- exec: function(cmd, args, callback) {
- callback(self.templates.help({commands: commands()}));
- }
- },
- history: {
- exec: function(cmd, args, callback) {
- if(args[0] == "-c") {
- _history.clear();
- callback();
- return;
- }
- callback(self.templates.history({items: _history.items()}));
- }
- },
- _default: {
- exec: function(cmd, args, callback) {
- callback(self.templates.bad_command({cmd: cmd}));
- },
- completion: function(cmd, arg, line, callback) {
- if(!arg) {
- arg = cmd;
- }
- return callback(self.bestMatch(arg, self.commands()))
- }
- }
- };
- var _line = {
- text: '',
- cursor: 0
- };
- var _searchMatch = '';
- var _view, _panel;
- var _promptHandler;
- var _initializationHandler;
- var _initialized;
-
- // public methods
- var self = {
- commands: commands,
- templates: {
- history: _.template("<% _.each(items, function(cmd, i) { %>
<%- i %> <%- cmd %>
<% }); %>
"),
- help: _.template("Commands:
<% _.each(commands, function(cmd) { %>
<%- cmd %>
<% }); %>
"),
- bad_command: _.template('Unrecognized command: <%=cmd%>
'),
- input_cmd: _.template('
'),
- empty_input_cmd: _.template(''),
- input_search: _.template('(reverse-i-search)`\':
'),
- suggest: _.template("<% _.each(suggestions, function(suggestion) { %>
<%- suggestion %>
<% }); %>
")
- },
- isActive: function() {
- return _readline.isActive();
- },
- activate: function() {
- if($(id(_shell_view_id)).length == 0) {
- _active = false;
- return;
- }
- _readline.activate();
- },
- deactivate: function() {
- _console.log("deactivating");
- _active = false;
- _readline.deactivate();
- },
- setCommandHandler: function(cmd, cmdHandler) {
- _cmdHandlers[cmd] = cmdHandler;
- },
- getCommandHandler: function(cmd) {
- return _cmdHandlers[cmd];
- },
- setPrompt: function(prompt) {
- _prompt = prompt;
- if(!_active) {
- return;
- }
- self.refresh();
- },
- onEOT: function(completionHandler) {
- _readline.onEOT(completionHandler);
- },
- onCancel: function(completionHandler) {
- _readline.onCancel(completionHandler);
- },
- onInitialize: function(completionHandler) {
- _initializationHandler = completionHandler;
- },
- onActivate: function(completionHandler) {
- _activationHandler = completionHandler;
- },
- onDeactivate: function(completionHandler) {
- _deactivationHandler = completionHandler;
- },
- onNewPrompt: function(completionHandler) {
- _promptHandler = completionHandler;
- },
- render: function() {
- var text = _line.text || '';
- var cursorIdx = _line.cursor || 0;
- if(_searchMatch) {
- cursorIdx = _searchMatch.cursoridx || 0;
- text = _searchMatch.text || '';
- $(id(_input_id) + ' .searchterm').text(_searchMatch.term);
- }
- var left = _.escape(text.substr(0, cursorIdx)).replace(/ /g, ' ');
- var cursor = text.substr(cursorIdx, 1);
- var right = _.escape(text.substr(cursorIdx + 1)).replace(/ /g, ' ');
- $(id(_input_id) + ' .prompt').html(_prompt);
- $(id(_input_id) + ' .input .left').html(left);
- if(!cursor) {
- $(id(_input_id) + ' .input .cursor').html(' ').css('textDecoration', 'underline');
- } else {
- $(id(_input_id) + ' .input .cursor').text(cursor).css('textDecoration', 'underline');
- }
- $(id(_input_id) + ' .input .right').html(right);
- _cursor_visible = true;
- self.scrollToBottom();
- _console.log('rendered "' + text + '" w/ cursor at ' + cursorIdx);
- },
- refresh: function() {
- $(id(_input_id)).replaceWith(self.templates.input_cmd({id:_input_id}));
- self.render();
- _console.log('refreshed ' + _input_id);
-
- },
- println: function(text) {
- var lines = text.split(/\n/);
- for (var i=0; i";
- } catch (e) {
- result = "" + e.stack + "
";
- }
- renderOutput(result, function() {
- callback("");
- });
- });
- _readline.onCompletion(function(line, callback) {
- if(!line) {
- return callback();
- }
- var text = line.text.substr(0, line.cursor);
- var parts = split(text);
-
- var cmd = parts.shift() || '';
- var arg = parts.pop() || '';
- _console.log("getting completion handler for " + cmd);
- var handler = getHandler(cmd);
- if(handler != _cmdHandlers._default && cmd && cmd == text) {
-
- _console.log("valid cmd, no args: append space");
- // the text to complete is just a valid command, append a space
- return callback(' ');
- }
- if(!handler.completion) {
- // handler has no completion function, so we can't complete
- return callback();
- }
- _console.log("calling completion handler for " + cmd);
- return handler.completion(cmd, arg, line, function(match) {
- _console.log("completion: " + JSON.stringify(match));
- if(!match) {
- return callback();
- }
- if(match.suggestions && match.suggestions.length > 1) {
- return renderOutput(self.templates.suggest({suggestions: match.suggestions}), function() {
- callback(match.completion);
- });
- }
- return callback(match.completion);
- });
- });
- return self;
- }
-})(this, $, _);
-
-var readline = {};
-readline.rlwrap = function(action) {
- var history = new Josh.History({ key: 'josh.helloworld'});
- var shell = Josh.Shell({history: history,
- action: action});
- var promptCounter = 0;
- shell.onNewPrompt(function(callback) {
- promptCounter++;
- callback("user>");
- });
- shell.activate();
-
- // map output/print to josh.js output
- readline.println = function () {
- shell.println(Array.prototype.slice.call(arguments).join(" "));
- };
-}
diff --git a/js/jq_readline.js b/js/jq_readline.js
new file mode 100644
index 00000000..e9f624f1
--- /dev/null
+++ b/js/jq_readline.js
@@ -0,0 +1,5 @@
+var readline = {
+ 'readline': function(prompt_str) {
+ return prompt(prompt_str);
+ }};
+
diff --git a/js/printer.js b/js/printer.js
index 5f0e03de..f3836e00 100644
--- a/js/printer.js
+++ b/js/printer.js
@@ -6,11 +6,6 @@ if (typeof module !== 'undefined') {
printer.println = exports.println = function () {
console.log.apply(console, arguments);
};
-} else {
- var exports = printer;
- printer.println = function() {
- readline.println.apply(null, arguments); // josh_readline.js
- }
}
function _pr_str(obj, print_readably) {
diff --git a/js/step0_repl.js b/js/step0_repl.js
index c13be2da..f9fa60e6 100644
--- a/js/step0_repl.js
+++ b/js/step0_repl.js
@@ -21,14 +21,7 @@ function PRINT(exp) {
var rep = function(str) { return PRINT(EVAL(READ(str), {})); };
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -41,6 +34,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step1_read_print.js b/js/step1_read_print.js
index 1ab162f7..f1fb0269 100644
--- a/js/step1_read_print.js
+++ b/js/step1_read_print.js
@@ -25,15 +25,7 @@ var re = function(str) { return EVAL(READ(str), {}); };
var rep = function(str) { return PRINT(EVAL(READ(str), {})); };
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -46,6 +38,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step2_eval.js b/js/step2_eval.js
index 72b1f9c3..58d561c8 100644
--- a/js/step2_eval.js
+++ b/js/step2_eval.js
@@ -62,15 +62,7 @@ repl_env['*'] = function(a,b){return a*b;};
repl_env['/'] = function(a,b){return a/b;};
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -83,6 +75,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step3_env.js b/js/step3_env.js
index b65824f8..1f5efb76 100644
--- a/js/step3_env.js
+++ b/js/step3_env.js
@@ -76,15 +76,7 @@ repl_env.set('*', function(a,b){return a*b;});
repl_env.set('/', function(a,b){return a/b;});
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -97,6 +89,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step4_if_fn_do.js b/js/step4_if_fn_do.js
index a0bb5488..27715fa0 100644
--- a/js/step4_if_fn_do.js
+++ b/js/step4_if_fn_do.js
@@ -92,15 +92,7 @@ for (var n in core.ns) { repl_env.set(n, core.ns[n]); }
rep("(def! not (fn* (a) (if a false true)))");
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -113,6 +105,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step5_tco.js b/js/step5_tco.js
index 76403274..659ac408 100644
--- a/js/step5_tco.js
+++ b/js/step5_tco.js
@@ -103,15 +103,7 @@ for (var n in core.ns) { repl_env.set(n, core.ns[n]); }
rep("(def! not (fn* (a) (if a false true)))");
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -124,6 +116,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step6_file.js b/js/step6_file.js
index 0dfe71e0..4c8ed179 100644
--- a/js/step6_file.js
+++ b/js/step6_file.js
@@ -112,15 +112,7 @@ if (typeof process !== 'undefined' && process.argv.length > 2) {
}
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -133,6 +125,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step7_quote.js b/js/step7_quote.js
index 067d68ee..62596726 100644
--- a/js/step7_quote.js
+++ b/js/step7_quote.js
@@ -137,15 +137,7 @@ if (typeof process !== 'undefined' && process.argv.length > 2) {
}
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -158,6 +150,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step8_macros.js b/js/step8_macros.js
index 2ddb56cd..f51592bd 100644
--- a/js/step8_macros.js
+++ b/js/step8_macros.js
@@ -163,15 +163,7 @@ if (typeof process !== 'undefined' && process.argv.length > 2) {
}
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -184,6 +176,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/step9_interop.js b/js/step9_interop.js
index 3988da1f..89d2ca48 100644
--- a/js/step9_interop.js
+++ b/js/step9_interop.js
@@ -169,15 +169,7 @@ if (typeof process !== 'undefined' && process.argv.length > 2) {
}
// repl loop
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
while (true) {
var line = readline.readline("user> ");
@@ -190,6 +182,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/stepA_more.js b/js/stepA_more.js
index 6058da19..0955b7f7 100644
--- a/js/stepA_more.js
+++ b/js/stepA_more.js
@@ -181,17 +181,9 @@ if (typeof process !== 'undefined' && process.argv.length > 2) {
}
// repl loop
-rep("(println (str \"Mal [\" *host-language* \"]\"))");
-if (typeof require === 'undefined') {
- // Asynchronous browser mode
- readline.rlwrap(function(line) { return rep(line); },
- function(exc) {
- if (exc instanceof reader.BlankException) { return; }
- if (exc.stack) { printer.println(exc.stack); }
- else { printer.println(exc); }
- });
-} else if (require.main === module) {
+if (typeof require !== 'undefined' && require.main === module) {
// Synchronous node.js commandline mode
+ rep("(println (str \"Mal [\" *host-language* \"]\"))");
while (true) {
var line = readline.readline("user> ");
if (line === null) { break; }
@@ -203,6 +195,4 @@ if (typeof require === 'undefined') {
else { printer.println(exc); }
}
}
-} else {
- exports.rep = rep;
}
diff --git a/js/web/ansi.css b/js/web/ansi.css
new file mode 100644
index 00000000..296cfc60
--- /dev/null
+++ b/js/web/ansi.css
@@ -0,0 +1,172 @@
+.jqconsole-ansi-bold {
+ font-weight: bold!important;
+}
+
+.jqconsole-ansi-lighter {
+ font-weight: lighter!important;
+}
+
+.jqconsole-ansi-italic {
+ font-style: italic!important;
+}
+
+.jqconsole-ansi-underline {
+ text-decoration: underline!important;
+}
+
+@-webkit-keyframes blinker {
+ from { opacity: 1.0; }
+ to { opacity: 0.0; }
+}
+
+@-moz-keyframes blinker {
+ from { opacity: 1.0; }
+ to { opacity: 0.0; }
+}
+
+@-ms-keyframes blinker {
+ from { opacity: 1.0; }
+ to { opacity: 0.0; }
+}
+
+@-o-keyframes blinker {
+ from { opacity: 1.0; }
+ to { opacity: 0.0; }
+}
+
+.jqconsole-ansi-blink {
+ -webkit-animation-name: blinker;
+ -moz-animation-name: blinker;
+ -ms-animation-name: blinker;
+ -o-animation-name: blinker;
+ -webkit-animation-iteration-count: infinite;
+ -moz-animation-iteration-count: infinite;
+ -ms-animation-iteration-count: infinite;
+ -o-animation-iteration-count: infinite;
+ -webkit-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -ms-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -o-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -moz-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -webkit-animation-duration: 1s;
+ -moz-animation-duration: 1s;
+ -o-animation-duration: 1s;
+ -ms-animation-duration: 1s;
+}
+
+.jqconsole-ansi-blink-rapid {
+ -webkit-animation-name: blinker;
+ -moz-animation-name: blinker;
+ -ms-animation-name: blinker;
+ -o-animation-name: blinker;
+ -webkit-animation-iteration-count: infinite;
+ -moz-animation-iteration-count: infinite;
+ -ms-animation-iteration-count: infinite;
+ -o-animation-iteration-count: infinite;
+ -webkit-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -ms-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -o-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -moz-animation-timing-function: cubic-bezier(1.0,0,0,1.0);
+ -webkit-animation-duration: 0.5s;
+ -moz-animation-duration: 0.5s;
+ -o-animation-duration: 0.5s;
+ -ms-animation-duration: 0.5s;
+}
+
+
+.jqconsole-ansi-hidden {
+ visibility:hidden!important;
+}
+
+.jqconsole-ansi-line-through {
+ text-decoration: line-through;
+}
+
+.jqconsole-ansi-fonts-1 {
+
+}
+.jqconsole-ansi-fonts-2 {
+
+}
+.jqconsole-ansi-fonts-3 {
+
+}
+.jqconsole-ansi-fonts-4 {
+
+}
+.jqconsole-ansi-fonts-5 {
+
+}
+.jqconsole-ansi-fonts-6 {
+
+}
+.jqconsole-ansi-fonts-7 {
+
+}
+.jqconsole-ansi-fonts-8 {
+
+}
+.jqconsole-ansi-fonts-9 {
+
+}
+
+.jqconsole-ansi-fraktur {
+
+}
+
+.jqconsole-ansi-color-black {
+ color: black!important;
+}
+.jqconsole-ansi-color-red {
+ color: red!important;
+}
+.jqconsole-ansi-color-green {
+ color: green!important;
+}
+.jqconsole-ansi-color-yellow {
+ color: yellow!important;
+}
+.jqconsole-ansi-color-blue {
+ color: blue!important;
+}
+.jqconsole-ansi-color-magenta {
+ color: magenta!important;
+}
+.jqconsole-ansi-color-cyan {
+ color: cyan!important;
+}
+.jqconsole-ansi-color-white {
+ color: white!important;
+}
+
+.jqconsole-ansi-background-color-black {
+ background-color: black!important;
+}
+.jqconsole-ansi-background-color-red {
+ background-color: red!important;
+}
+.jqconsole-ansi-background-color-green {
+ background-color: green!important;
+}
+.jqconsole-ansi-background-color-yellow {
+ background-color: yellow!important;
+}
+.jqconsole-ansi-background-color-blue {
+ background-color: blue!important;
+}
+.jqconsole-ansi-background-color-magenta {
+ background-color: magenta!important;
+}
+.jqconsole-ansi-background-color-cyan {
+ background-color: cyan!important;
+}
+.jqconsole-ansi-background-color-white {
+ background-color: white!important;
+}
+
+.jqconsole-ansi-framed {
+ border: 1px solid!important;
+}
+.jqconsole-ansi-overline {
+ text-decoration: overline!important;
+}
+
diff --git a/js/web/console.css b/js/web/console.css
new file mode 100644
index 00000000..454fbcbb
--- /dev/null
+++ b/js/web/console.css
@@ -0,0 +1,55 @@
+html, body {
+ background-color: #333;
+ color: white;
+ font-family: monospace;
+ margin: 0;
+ padding: 0;
+}
+#console {
+ height: 400px;
+ width: 750px;
+ position:relative;
+ background-color: black;
+ border: 2px solid #CCC;
+ margin: 0 auto;
+ margin-top: 50px;
+}
+.jqconsole {
+ padding: 10px;
+ padding-bottom: 10px;
+}
+.jqconsole-cursor {
+ background-color: #999;
+}
+.jqconsole-blurred .jqconsole-cursor {
+ background-color: #666;
+}
+.jqconsole-prompt {
+ color: #0d0;
+}
+.jqconsole-old-prompt {
+ color: #0b0;
+ font-weight: normal;
+}
+.jqconsole-input {
+ color: #dd0;
+}
+.jqconsole-old-input {
+ color: #bb0;
+ font-weight: normal;
+}
+.brace {
+ color: #00FFFF;
+}
+.paren {
+ color: #FF00FF;
+}
+.bracket {
+ color: #FFFF00;
+}
+.dquote {
+ color: #FF8888;
+}
+.jqconsole-composition {
+ background-color: red;
+}
diff --git a/js/web/jqconsole.min.js b/js/web/jqconsole.min.js
new file mode 100644
index 00000000..107e23d9
--- /dev/null
+++ b/js/web/jqconsole.min.js
@@ -0,0 +1 @@
+(function(){var t,e,i,s,r,o,n,h,p,c,a,l,u,_,f,m,d,$,y,v,g,x,b,k,w,C,T,S,M,P,H,E,L,I,W,D,A,R=function(t,e){return function(){return t.apply(e,arguments)}},U=[].slice;t=jQuery;I=0;W=1;D=2;w=13;H=9;x=46;g=8;T=37;P=39;E=38;b=40;C=36;k=35;M=33;S=34;p="jqconsole-";r=""+p+"cursor";o=""+p+"header";c=""+p+"prompt";h=""+p+"old-prompt";n=""+p+"input";s=""+p+"blurred";y="keypress";m="";_="";f=":empty";L="\n";u=">>> ";l="... ";a=2;i=""+p+"ansi-";d="";$=/\[(\d*)(?:;(\d*))*m/;e=function(){t.prototype.COLORS=["black","red","green","yellow","blue","magenta","cyan","white"];function t(){this.stylize=R(this.stylize,this);this._closeSpan=R(this._closeSpan,this);this._openSpan=R(this._openSpan,this);this.getClasses=R(this.getClasses,this);this._style=R(this._style,this);this._color=R(this._color,this);this._remove=R(this._remove,this);this._append=R(this._append,this);this.klasses=[]}t.prototype._append=function(t){t=""+i+t;if(this.klasses.indexOf(t)===-1){return this.klasses.push(t)}};t.prototype._remove=function(){var t,e,s,r,o,n;s=1<=arguments.length?U.call(arguments,0):[];n=[];for(r=0,o=s.length;r'+t};t.prototype._closeSpan=function(t){return""+t+""};t.prototype.stylize=function(t){var e,i,s,r,o,n;t=this._openSpan(t);s=0;while((s=t.indexOf(d,s))&&s!==-1){if(i=t.slice(s).match($)){n=i.slice(1);for(r=0,o=n.length;r'+(e||"")+""};v=function(){function i(i,s,r,n){this._HideComposition=R(this._HideComposition,this);this._ShowComposition=R(this._ShowComposition,this);this._UpdateComposition=R(this._UpdateComposition,this);this._EndComposition=R(this._EndComposition,this);this._StartComposition=R(this._StartComposition,this);this._CheckComposition=R(this._CheckComposition,this);this._ProcessMatch=R(this._ProcessMatch,this);this._HandleKey=R(this._HandleKey,this);this._HandleChar=R(this._HandleChar,this);this.isMobile=!!navigator.userAgent.match(/iPhone|iPad|iPod|Android/i);this.isIos=!!navigator.userAgent.match(/iPhone|iPad|iPod/i);this.isAndroid=!!navigator.userAgent.match(/Android/i);this.$window=t(window);this.header=s||"";this.prompt_label_main=typeof r==="string"?r:u;this.prompt_label_continue=n||l;this.indent_width=a;this.state=W;this.input_queue=[];this.input_callback=null;this.multiline_callback=null;this.history=[];this.history_index=0;this.history_new="";this.history_active=false;this.shortcuts={};this.$container=t("").appendTo(i);this.$container.css({top:0,left:0,right:0,bottom:0,position:"absolute",overflow:"auto"});this.$console=t('').appendTo(this.$container);this.$console.css({margin:0,position:"relative","min-height":"100%","box-sizing":"border-box","-moz-box-sizing":"border-box","-webkit-box-sizing":"border-box"});this.$console_focused=true;this.$input_container=t(_).appendTo(this.$container);this.$input_container.css({position:"absolute",width:1,height:0,overflow:"hidden"});this.$input_source=this.isAndroid?t(""):t("");this.$input_source.attr({wrap:"off",autocapitalize:"off",autocorrect:"off",spellcheck:"false",autocomplete:"off"});this.$input_source.css({position:"absolute",width:2});this.$input_source.appendTo(this.$input_container);this.$composition=t(_);this.$composition.addClass(""+p+"composition");this.$composition.css({display:"inline",position:"relative"});this.matchings={openings:{},closings:{},clss:[]};this.ansi=new e;this._InitPrompt();this._SetupEvents();this.Write(this.header,o);t(i).data("jqconsole",this)}i.prototype.ResetHistory=function(){return this.SetHistory([])};i.prototype.ResetShortcuts=function(){return this.shortcuts={}};i.prototype.ResetMatchings=function(){return this.matchings={openings:{},closings:{},clss:[]}};i.prototype.Reset=function(){if(this.state!==W){this.ClearPromptText(true)}this.state=W;this.input_queue=[];this.input_callback=null;this.multiline_callback=null;this.ResetHistory();this.ResetShortcuts();this.ResetMatchings();this.$prompt.detach();this.$input_container.detach();this.$console.html("");this.$prompt.appendTo(this.$console);this.$input_container.appendTo(this.$container);this.Write(this.header,o);return void 0};i.prototype.GetHistory=function(){return this.history};i.prototype.SetHistory=function(t){this.history=t.slice();return this.history_index=this.history.length};i.prototype._CheckKeyCode=function(t){if(isNaN(t)){t=t.charCodeAt(0)}else{t=parseInt(t,10)}if(!(0>> "))}else{o.push(t(i).text())}}return o}().join("")};i.prototype.GetState=function(){if(this.state===I){return"input"}else if(this.state===W){return"output"}else{return"prompt"}};i.prototype.Disable=function(){this.$input_source.attr("disabled",true);return this.$input_source.blur()};i.prototype.Enable=function(){return this.$input_source.attr("disabled",false)};i.prototype.IsDisabled=function(){return Boolean(this.$input_source.attr("disabled"))};i.prototype.MoveToStart=function(t){this._MoveTo(t,true);return void 0};i.prototype.MoveToEnd=function(t){this._MoveTo(t,false);return void 0};i.prototype.Clear=function(){this.$console.find("."+o).nextUntil("."+c).addBack().text("");this.$prompt_cursor.detach();return this.$prompt_after.before(this.$prompt_cursor)};i.prototype._CheckInputQueue=function(){if(this.input_queue.length){return this.input_queue.shift()()}};i.prototype._InitPrompt=function(){this.$prompt=t(A(n)).appendTo(this.$console);this.$prompt_before=t(m).appendTo(this.$prompt);this.$prompt_current=t(m).appendTo(this.$prompt);this.$prompt_after=t(m).appendTo(this.$prompt);this.$prompt_label=t(m).appendTo(this.$prompt_current);this.$prompt_left=t(m).appendTo(this.$prompt_current);this.$prompt_right=t(m).appendTo(this.$prompt_current);this.$prompt_right.css({position:"relative"});this.$prompt_cursor=t(A(r," "));this.$prompt_cursor.insertBefore(this.$prompt_right);this.$prompt_cursor.css({color:"transparent",display:"inline",zIndex:0});if(!this.isMobile){return this.$prompt_cursor.css("position","absolute")}};i.prototype._SetupEvents=function(){var t=this;if(this.isMobile){this.$console.click(function(e){e.preventDefault();return t.Focus()})}else{this.$console.mouseup(function(e){var i;if(e.which===2){return t.Focus()}else{i=function(){if(!window.getSelection().toString()){e.preventDefault();return t.Focus()}};return setTimeout(i,0)}})}this.$input_source.focus(function(){var e,i;t._ScrollToEnd();t.$console_focused=true;t.$console.removeClass(s);i=function(){if(t.$console_focused){return t.$console.removeClass(s)}};setTimeout(i,100);e=function(){if(t.isIos&&t.$console_focused){return t.$input_source.hide()}};return setTimeout(e,500)});this.$input_source.blur(function(){var e;t.$console_focused=false;if(t.isIos){t.$input_source.show()}e=function(){if(!t.$console_focused){return t.$console.addClass(s)}};return setTimeout(e,100)});this.$input_source.bind("paste",function(){var e;e=function(){if(t.in_composition){return}t._AppendPromptText(t.$input_source.val());t.$input_source.val("");return t.Focus()};return setTimeout(e,0)});this.$input_source.keypress(this._HandleChar);this.$input_source.keydown(this._HandleKey);this.$input_source.keydown(this._CheckComposition);this.$input_source.bind("compositionstart",this._StartComposition);this.$input_source.bind("compositionend",function(e){return setTimeout(function(){return t._EndComposition(e)},0)});if(this.isAndroid){this.$input_source.bind("input",this._StartComposition);return this.$input_source.bind("input",this._UpdateComposition)}else{return this.$input_source.bind("text",this._UpdateComposition)}};i.prototype._HandleChar=function(t){var e;if(this.state===W||t.metaKey||t.ctrlKey){return true}e=t.which;if(e===8||e===9||e===13){return false}this.$prompt_left.text(this.$prompt_left.text()+String.fromCharCode(e));this._ScrollToEnd();return false};i.prototype._HandleKey=function(e){var i;if(this.state===W){return true}i=e.keyCode||e.which;setTimeout(t.proxy(this._CheckMatchings,this),0);if(e.altKey){return true}else if(e.ctrlKey||e.metaKey){return this._HandleCtrlShortcut(i)}else if(e.shiftKey){switch(i){case w:this._HandleEnter(true);break;case H:this._Unindent();break;case E:this._MoveUp();break;case b:this._MoveDown();break;case M:this._ScrollPage("up");break;case S:this._ScrollPage("down");break;default:return true}return false}else{switch(i){case w:this._HandleEnter(false);break;case H:this._Indent();break;case x:this._Delete(false);break;case g:this._Backspace(false);break;case T:this._MoveLeft(false);break;case P:this._MoveRight(false);break;case E:this._HistoryPrevious();break;case b:this._HistoryNext();break;case C:this.MoveToStart(false);break;case k:this.MoveToEnd(false);break;case M:this._ScrollPage("up");break;case S:this._ScrollPage("down");break;default:return true}return false}};i.prototype._HandleCtrlShortcut=function(t){var e,i,s,r;switch(t){case x:this._Delete(true);break;case g:this._Backspace(true);break;case T:this._MoveLeft(true);break;case P:this._MoveRight(true);break;case E:this._MoveUp();break;case b:this._MoveDown();break;case k:this.MoveToEnd(true);break;case C:this.MoveToStart(true);break;default:if(t in this.shortcuts){r=this.shortcuts[t];for(i=0,s=r.length;ih;o=0<=h?++n:--n){if(t>0){c.push(s._Indent())}else{c.push(s._Unindent())}}return c}else{r=s.state===I?"input":"prompt";s.Write(s.GetPromptText(true)+L,""+p+"old-"+r);s.ClearPromptText(true);if(s.history_active){if(!s.history.length||s.history[s.history.length-1]!==i){s.history.push(i)}s.history_index=s.history.length}s.state=W;e=s.input_callback;s.input_callback=null;if(e){e(i)}return s._CheckInputQueue()}};if(this.multiline_callback){if(this.async_multiline){return this.multiline_callback(i,e)}else{return e(this.multiline_callback(i))}}else{return e(false)}}};i.prototype._GetDirectionals=function(e){var i,s,r,o,n,h,p,c;o=e?this.$prompt_left:this.$prompt_right;i=e?this.$prompt_right:this.$prompt_left;r=e?this.$prompt_before:this.$prompt_after;s=e?this.$prompt_after:this.$prompt_before;h=e?t.proxy(this.MoveToStart,this):t.proxy(this.MoveToEnd,this);n=e?t.proxy(this._MoveLeft,this):t.proxy(this._MoveRight,this);c=e?"last":"first";p=e?"prependTo":"appendTo";return{$prompt_which:o,$prompt_opposite:i,$prompt_relative:r,$prompt_rel_opposite:s,MoveToLimit:h,MoveDirection:n,which_end:c,where_append:p}};i.prototype._VerticalMove=function(t){var e,i,s,r,o,n,h,p;p=this._GetDirectionals(t),s=p.$prompt_which,e=p.$prompt_opposite,i=p.$prompt_relative,o=p.MoveToLimit,r=p.MoveDirection;if(i.is(f)){return}n=this.$prompt_left.text().length;o();r();h=s.text();e.text(t?h.slice(n):h.slice(0,n));return s.text(t?h.slice(0,n):h.slice(n))};i.prototype._MoveUp=function(){return this._VerticalMove(true)};i.prototype._MoveDown=function(){return this._VerticalMove()};i.prototype._HorizontalMove=function(e,i){var s,r,o,n,h,p,c,a,l,u,_,d,$,y;y=this._GetDirectionals(i),h=y.$prompt_which,r=y.$prompt_opposite,n=y.$prompt_relative,o=y.$prompt_rel_opposite,d=y.which_end,_=y.where_append;a=i?/\w*\W*$/:/^\w*\W*/;l=h.text();if(l){if(e){$=l.match(a);if(!$){return}$=$[0];u=r.text();r.text(i?$+u:u+$);c=$.length;return h.text(i?l.slice(0,-c):l.slice(c))}else{u=r.text();r.text(i?l.slice(-1)+u:u+l[0]);return h.text(i?l.slice(0,-1):l.slice(1))}}else if(!n.is(f)){p=t(m)[_](o);p.append(t(m).text(this.$prompt_label.text()));p.append(t(m).text(r.text()));s=n.children()[d]().detach();this.$prompt_label.text(s.children().first().text());h.text(s.children().last().text());return r.text("")}};i.prototype._MoveLeft=function(t){return this._HorizontalMove(t,true)};i.prototype._MoveRight=function(t){return this._HorizontalMove(t)};i.prototype._MoveTo=function(t,e){var i,s,r,o,n,h,p;h=this._GetDirectionals(e),r=h.$prompt_which,i=h.$prompt_opposite,s=h.$prompt_relative,n=h.MoveToLimit,o=h.MoveDirection;if(t){p=[];while(!(s.is(f)&&r.text()==="")){n(false);p.push(o(false))}return p}else{i.text(this.$prompt_left.text()+this.$prompt_right.text());return r.text("")}};i.prototype._Delete=function(t){var e,i,s;i=this.$prompt_right.text();if(i){if(t){s=i.match(/^\w*\W*/);if(!s){return}s=s[0];return this.$prompt_right.text(i.slice(s.length))}else{return this.$prompt_right.text(i.slice(1))}}else if(!this.$prompt_after.is(f)){e=this.$prompt_after.children().first().detach();return this.$prompt_right.text(e.children().last().text())}};i.prototype._Backspace=function(e){var i,s,r;setTimeout(t.proxy(this._ScrollToEnd,this),0);s=this.$prompt_left.text();if(s){if(e){r=s.match(/\w*\W*$/);if(!r){return}r=r[0];return this.$prompt_left.text(s.slice(0,-r.length))}else{return this.$prompt_left.text(s.slice(0,-1))}}else if(!this.$prompt_before.is(f)){i=this.$prompt_before.children().last().detach();this.$prompt_label.text(i.children().first().text());return this.$prompt_left.text(i.children().last().text())}};i.prototype._Indent=function(){var t;return this.$prompt_left.prepend(function(){var e,i,s;s=[];for(t=e=1,i=this.indent_width;1<=i?e<=i:e>=i;t=1<=i?++e:--e){s.push(" ")}return s}.call(this).join(""))};i.prototype._Unindent=function(){var t,e,i,s,r;t=this.$prompt_left.text()+this.$prompt_right.text();r=[];for(e=i=1,s=this.indent_width;1<=s?i<=s:i>=s;e=1<=s?++i:--i){if(!/^ /.test(t)){break}if(this.$prompt_left.text()){this.$prompt_left.text(this.$prompt_left.text().slice(1))}else{this.$prompt_right.text(this.$prompt_right.text().slice(1))}r.push(t=t.slice(1))}return r};i.prototype._InsertNewLine=function(e){var i,s,r;if(e==null){e=false}r=this._SelectPromptLabel(!this.$prompt_before.is(f));i=t(m).appendTo(this.$prompt_before);i.append(t(m).text(r));i.append(t(m).text(this.$prompt_left.text()));this.$prompt_label.text(this._SelectPromptLabel(true));if(e&&(s=this.$prompt_left.text().match(/^\s+/))){this.$prompt_left.text(s[0])}else{this.$prompt_left.text("")}return this._ScrollToEnd()};i.prototype._AppendPromptText=function(t){var e,i,s,r,o,n;i=t.split(L);this.$prompt_left.text(this.$prompt_left.text()+i[0]);o=i.slice(1);n=[];for(s=0,r=o.length;ss.top){return this.$window.scrollTop(i)}}else{if(o+ti){return this.$window.scrollTop(s.top)}}};i.prototype._SelectPromptLabel=function(t){if(this.state===D){if(t){return" \n"+this.prompt_label_continue}else{return this.prompt_label_main}}else{if(t){return"\n "}else{return" "}}};i.prototype._Wrap=function(t,e,i){var s,r;r=t.html();s=r.slice(0,e)+A(i,r[e])+r.slice(e+1);return t.html(s)};i.prototype._WalkCharacters=function(t,e,i,s,r){var o,n,h;n=r?t.length:0;t=t.split("");h=function(){var e,i,s,o;if(r){s=t,t=2<=s.length?U.call(s,0,i=s.length-1):(i=0,[]),e=s[i++]}else{o=t,e=o[0],t=2<=o.length?U.call(o,1):[]}if(e){n=n+(r?-1:+1)}return e};while(o=h()){if(o===e){s++}else if(o===i){s--}if(s===0){return{index:n,current_count:s}}}return{index:-1,current_count:s}};i.prototype._ProcessMatch=function(e,i,s){var r,o,n,h,p,c,a,l,u,_,f,m,d=this;_=i?[e["closing_char"],e["opening_char"]]:[e["opening_char"],e["closing_char"]],h=_[0],l=_[1];f=this._GetDirectionals(i),n=f.$prompt_which,o=f.$prompt_relative;p=1;c=false;u=n.html();if(!i){u=u.slice(1)}if(s&&i){u=u.slice(0,-1)}m=this._WalkCharacters(u,h,l,p,i),a=m.index,p=m.current_count;if(a>-1){this._Wrap(n,a,e.cls);c=true}else{r=o.children();r=i?Array.prototype.reverse.call(r):r;r.each(function(s,r){var o,n;o=t(r).children().last();u=o.html();n=d._WalkCharacters(u,h,l,p,i),a=n.index,p=n.current_count;if(a>-1){if(!i){a--}d._Wrap(o,a,e.cls);c=true;return false}})}return c};i.prototype._CheckMatchings=function(e){var i,s,r,o,n,h,p;r=e?this.$prompt_left.text().slice(this.$prompt_left.text().length-1):this.$prompt_right.text()[0];p=this.matchings.clss;for(n=0,h=p.length;n=this.history.length){return}if(this.history_index===this.history.length-1){this.history_index++;return this.SetPromptText(this.history_new)}else{return this.SetPromptText(this.history[++this.history_index])}};i.prototype._CheckComposition=function(t){var e;e=t.keyCode||t.which;if(e===229){if(this.in_composition){return this._UpdateComposition()}else{return this._StartComposition()}}};i.prototype._StartComposition=function(){if(this.in_composition){return}this.in_composition=true;this._ShowComposition();return setTimeout(this._UpdateComposition,0)};i.prototype._EndComposition=function(){if(!this.in_composition){return}this._HideComposition();this.$prompt_left.text(this.$prompt_left.text()+this.$composition.text());this.$composition.text("");this.$input_source.val("");return this.in_composition=false};i.prototype._UpdateComposition=function(t){var e,i=this;e=function(){if(!i.in_composition){return}return i.$composition.text(i.$input_source.val())};return setTimeout(e,0)};i.prototype._ShowComposition=function(){this.$composition.css("height",this.$prompt_cursor.height());this.$composition.empty();return this.$composition.appendTo(this.$prompt_left)};i.prototype._HideComposition=function(){return this.$composition.detach()};return i}();t.fn.jqconsole=function(t,e,i){return new v(this,t,e,i)};t.fn.jqconsole.JQConsole=v;t.fn.jqconsole.Ansi=e}).call(this);
\ No newline at end of file
diff --git a/mal.html b/mal.html
index b8b3dd0a..45e6dc33 100644
--- a/mal.html
+++ b/mal.html
@@ -1,52 +1,81 @@
-
+
-
-
-
- Make a Lisp
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ printer.println = function () {
+ var str = Array.prototype.join.call(arguments, " ")
+ jqconsole.Write(str + "\n");
+ }
-
- Make a Lisp
+ rep("(println (str \"Mal [\" *host-language* \"]\"))");
-
-
-
+ // Abort prompt on Ctrl+C.
+ jqconsole.RegisterShortcut('C', function() {
+ jqconsole.AbortPrompt();
+ handler();
+ });
+ // Move to line start Ctrl+A.
+ jqconsole.RegisterShortcut('A', function() {
+ jqconsole.MoveToStart();
+ handler();
+ });
+ // Move to line end Ctrl+E.
+ jqconsole.RegisterShortcut('E', function() {
+ jqconsole.MoveToEnd();
+ handler();
+ });
+ jqconsole.RegisterMatching('{', '}', 'brace');
+ jqconsole.RegisterMatching('(', ')', 'paren');
+ jqconsole.RegisterMatching('[', ']', 'bracket');
+ jqconsole.RegisterMatching('"', '"', 'dquote');
+ // Handle a command.
+ var handler = function(line) {
+ if (line) {
+ try {
+ jqconsole.Write(rep(line) + '\n');
+ } catch (exc) {
+ if (exc instanceof reader.BlankException) { return; }
+ if (exc.stack) {
+ jqconsole.Write(exc.stack + '\n');
+ } else {
+ jqconsole.Write(exc + '\n');
+ }
+ }
+ }
+ jqconsole.Prompt(true, handler);
+ /*
+ jqconsole.Prompt(true, handler, function(command) {
+ // Continue line if can't compile the command.
+ try {
+ Function(command);
+ } catch (e) {
+ if (/[\[\{\(]$/.test(command)) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+ return false;
+ });
+ */
+ };
-
-
+ // Initiate the first prompt.
+ handler();
+ });
+
+