Skip to content

Instantly share code, notes, and snippets.

@swannodette
Created November 13, 2011 22:45
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save swannodette/1362856 to your computer and use it in GitHub Desktop.
Save swannodette/1362856 to your computer and use it in GitHub Desktop.
core.clj
;; assumes browser-repl.sh and replnode.sh are on your path
(defun browser-repl ()
(interactive)
(setq inferior-lisp-program "browser-repl")
(run-lisp))
(defun node-repl ()
(interactive)
(setq inferior-lisp-program "replnode")
(run-lisp "replnode"))
#!/bin/sh
if [ "$CLOJURESCRIPT_HOME" = "" ]; then
CLOJURESCRIPT_HOME="`dirname $0`/.."
fi
CLJSC_CP=''
for next in lib/: lib/*: src/clj: src/cljs: test/cljs; do
CLJSC_CP=$CLJSC_CP$CLOJURESCRIPT_HOME'/'$next
done
java -server -cp $CLJSC_CP clojure.main -e \
"(require '[cljs.repl :as repl])
(require '[cljs.repl.browser :as browser])
(def env (browser/repl-env))
(repl/repl env)"
(ns cljs-conj.core
(:use-macros [clojure.core.match.js :only [match]])
(:require [goog.dom :as dom]
[goog.events :as events]
[goog.fx.dom :as fx]
[cljs.reader :as r]
[clojure.browser.repl :as repl]))
(repl/connect "http://localhost:9000/repl")
;; =============================================================================
;; Extending Natives
(extend-type js/CSSStyleDeclaration
ISeqable
(-seq [this]
(let [ks (js-keys this)]
(->> ks
(filter (fn [k] (. this (hasOwnProperty k))))
(map (fn [k] [k (aget this k)])))))
ILookup
(-lookup [this k] (-lookup this k nil))
(-lookup [this k not-found]
(if (. this (hasOwnProperty k))
(aget this k)
not-found))
IPrintable
(-pr-seq [coll opts]
(let [pr-pair (fn [keyval] (pr-sequential pr-seq "" " " "" opts keyval))]
(pr-sequential pr-pair "{" ", " "}" opts coll))))
;; =============================================================================
;; Macros
(defn balance [node]
(match [node]
[(:or [:black [:red [:red a x b] y c] z d]
[:black [:red a x [:red b y c]] z d]
[:black a x [:red [:red b y c] z d]]
[:black a x [:red b y [:red c z d]]])] [:red [:black a x b] y [:black c z d]]
:else node))
(comment
(balance [:black [:red [:red nil 1 nil] 2 nil] 3 nil])
;; ~1s in browser & node.js
(time
(dotimes [_ 60000]
(balance [:black [:red [:red nil 1 nil] 2 nil] 3 nil])))
)
;; =============================================================================
;; core.logic anyone?
;; =============================================================================
;; Reader
(defprotocol IMutableAssociative
(-assoc! [coll k v]))
(defprotocol IMutableEmptyable
(-empty! [coll]))
(extend-type js/Storage
ISeqable
(-seq [this]
(for [i (range (.length this))]
(let [k (. this (key i))]
[k (.getItem this k)])))
ILookup
(-lookup [this k] (-lookup this k nil))
(-lookup [this k not-found]
(if-let [v (r/read-string (.getItem this (pr-str k)))]
v not-found))
IPrintable
(-pr-seq [coll opts]
(let [pr-pair (fn [[k v :as kv]]
(if kv
(pr-sequential pr-seq "" " " "" opts
[(r/read-string k)
(r/read-string v)])))]
(pr-sequential pr-pair "{" ", " "}" opts coll)))
IMutableEmptyable
(-empty! [this]
(. this (clear)))
IMutableAssociative
(-assoc! [this k v]
(. this (setItem (pr-str k) (pr-str v)))))
(defn empty! [coll]
(-empty! coll))
(defn assoc! [coll k v]
(-assoc! coll k v))
(defn foo [a b]
(+ a b))
;; Copyright (c) Kurt Harriger. All rights reserved.
;; The use and distribution terms for this software are covered by the
;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
;; which can be found in the file epl-v10.html at the root of this distribution.
;; By using this software in any fashion, you are agreeing to be bound by
;; the terms of this license.
;; You must not remove this notice, or any other, from this software.
(ns cljs.repl.node
(:refer-clojure :exclude [loaded-libs])
(:require [clojure.string :as string]
[clojure.java.io :as io]
[cljs.compiler :as comp]
[cljs.repl :as repl]
[cljs.closure :as cljsc])
(:import cljs.repl.IJavaScriptEnv
java.net.Socket
[java.io BufferedReader BufferedWriter]))
(def current-repl-env (atom nil))
(def loaded-libs (atom #{}))
(defn socket [host port]
(let [socket (java.net.Socket. host port)
in (io/reader socket)
out (io/writer socket)]
{:socket socket :in in :out out}))
(defn close-socket [s]
(.close (:in s))
(.close (:out s))
(.close (:socket s)))
(defn write [^BufferedWriter out ^String js]
(.write out js)
(.write out (int 0))
(.flush out))
(defn read-response [^BufferedReader in]
(let [sb (java.lang.StringBuilder.)]
(loop [c (.read in)]
(if (not= c 0)
(do
(.append sb (char c))
(recur (.read in)))
(str sb)))))
(defn node-eval [{:keys [in out]} js]
(write out js)
{:status :success :value (read-response in)})
(defn load-javascript [ctx ns url]
(node-eval ctx (slurp url)))
(defn setup [repl-env]
(let [env {:context :statement :locals {} :ns (@comp/namespaces comp/*cljs-ns*)}
scope (:scope repl-env)]
(repl/load-file repl-env "cljs/core.cljs")
(swap! loaded-libs conj "cljs.core")
(repl/evaluate-form repl-env
env
"<cljs repl>"
'(ns cljs.user))
(repl/evaluate-form repl-env
env
"<cljs repl>"
'(set! *print-fn* (fn [x] (. js/console (log (pr-str x))))))))
(extend-protocol repl/IJavaScriptEnv
clojure.lang.IPersistentMap
(-setup [this] (setup this))
(-evaluate [this filename line js] (node-eval this js))
(-load [this ns url] (load-javascript this ns url))
(-tear-down [this] (close-socket this)))
;; do we need to implement our own version of goog.require ? - David
(defn repl-env
[& {:keys [host port] :or {host "localhost" port 5001}}]
(let [repl-env (socket host port)
base (io/resource "goog/base.js")
deps (io/resource "goog/deps.js")]
(node-eval repl-env (slurp (io/reader base)))
(node-eval repl-env (slurp (io/reader deps)))
repl-env))
process.env.NODE_DISABLE_COLORS = true;
var net = require("net"),
repl = require("repl"),
vm = require("vm"),
context = vm.createContext();
context.require = require;
net.createServer(function (socket) {
var buffer = "", ret;
socket.setEncoding("utf8");
context.console = {
log: function(x) {
ret = vm.runInContext(x, context, "repl");
socket.write(ret.toString()+"\n");
}
};
socket.on("data", function(data) {
if(data[data.length-1] != "\0") {
buffer += data;
} else {
if(buffer.length > 0) {
data = buffer + data;
buffer = "";
}
if(data) {
// not sure how \0's are getting through - David
data = data.replace(/\0/g, "");
try {
//console.log(data);
ret = vm.runInContext(data, context, "repl");
} catch (x) {
//console.log(data);
console.log(x.stack);
socket.write(x.stack+"\n");
}
}
if(ret !== undefined && ret !== null) {
socket.write(ret.toString());
} else {
socket.write("nil");
}
socket.write("\0");
}
});
}).listen(5001);
#!/bin/sh
if [ "$CLOJURESCRIPT_HOME" = "" ]; then
CLOJURESCRIPT_HOME="`dirname $0`/.."
fi
CLJSC_CP=''
for next in lib/*: src/clj: src/cljs: test/cljs; do
CLJSC_CP=$CLJSC_CP$CLOJURESCRIPT_HOME'/'$next
done
java -server -cp $CLJSC_CP clojure.main -e \
"(require '[cljs.repl :as repl])
(require '[cljs.repl.node :as node])
(repl/repl (node/repl-env $1))"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment