├── .gitignore ├── .gitmodules ├── .travis.yml ├── Clojurescript.iml ├── README.md ├── benchmark └── cljs │ └── benchmark_runner.cljs ├── bin ├── cljsc ├── cljsc.bat └── cljsc.clj ├── devnotes ├── README.org ├── bcrepl.org ├── cljs.org ├── corelib.org ├── day1.org ├── day2.org ├── talk.org ├── testing └── todo.org ├── epl-v10.html ├── node ├── hello.cljs ├── run.js ├── run2.js └── shebang.cljs ├── pom.template.xml ├── samples ├── dom │ ├── .gitignore │ ├── src │ │ └── dom │ │ │ └── test.cljs │ └── test.html ├── hello-js │ ├── .gitignore │ ├── README.md │ ├── externed-lib.js │ ├── externs.js │ ├── hello-extern.html │ ├── hello-js-dev.html │ ├── hello-js.html │ ├── my-external-lib.js │ └── src │ │ └── hello-js │ │ ├── core.cljs │ │ └── extern-example.cljs ├── hello │ ├── .gitignore │ ├── README.md │ ├── hello-dev.html │ ├── hello.html │ └── src │ │ └── hello │ │ ├── core.cljs │ │ └── foo │ │ └── bar.cljs ├── nodehello.cljs ├── nodels.cljs ├── repl │ ├── .gitignore │ ├── README.md │ ├── index.html │ └── src │ │ └── repl │ │ └── test.cljs └── twitterbuzz │ ├── .gitignore │ ├── README.md │ ├── index-advanced.html │ ├── index.html │ ├── reset.css │ ├── src │ └── twitterbuzz │ │ ├── anneal.cljs │ │ ├── core.cljs │ │ ├── dom-helpers.cljs │ │ ├── layout.cljs │ │ ├── leaderboard.cljs │ │ ├── radial.cljs │ │ ├── showgraph.cljs │ │ └── timeline.cljs │ ├── style.css │ ├── test_data.txt │ └── tweet_maps.txt ├── script ├── benchmark ├── bootstrap ├── browser-repl ├── build ├── clean ├── closure-library-release │ ├── google-closure-library-third-party.pom.template │ ├── google-closure-library.pom.template │ └── make-closure-library-jars.sh ├── compile ├── repl ├── repl.bat ├── repljs ├── repljs.bat ├── test └── test-compile ├── src ├── clj │ └── cljs │ │ ├── analyzer.clj │ │ ├── closure.clj │ │ ├── compiler.clj │ │ ├── core.clj │ │ ├── repl.clj │ │ ├── repl │ │ ├── browser.clj │ │ ├── reflect.clj │ │ ├── rhino.clj │ │ └── server.clj │ │ └── tagged_literals.clj └── cljs │ ├── cljs │ ├── analyzer.cljs │ ├── analyzer_macros.clj │ ├── analyzer_macros.cljs │ ├── closure.cljs │ ├── compiler.cljs │ ├── compiler_macros.clj │ ├── compiler_macros.cljs │ ├── core.cljs │ ├── core_macros.clj │ ├── core_top.cljs │ ├── io.cljs │ ├── nodejs.cljs │ ├── nodejs_externs.js │ ├── nodejscli.cljs │ ├── reader.cljs │ └── repl.cljs │ ├── cljsc.cljs │ ├── clojure │ ├── browser │ │ ├── dom.cljs │ │ ├── event.cljs │ │ ├── net.cljs │ │ └── repl.cljs │ ├── core │ │ └── reducers.cljs │ ├── data.cljs │ ├── reflect.cljs │ ├── set.cljs │ ├── string.cljs │ ├── walk.cljs │ └── zip.cljs │ ├── goog.js │ ├── nodecljs.cljs │ ├── noderepl.cljs │ ├── webconsole.cljs │ ├── webedit.cljs │ ├── webrepl.cljs │ ├── webrepl2.cljs │ └── webrepl3.cljs ├── test └── cljs │ ├── cljs │ ├── binding_test.cljs │ ├── binding_test_other_ns.cljs │ ├── core_test.cljs │ ├── import_test.cljs │ ├── import_test │ │ └── foo.cljs │ ├── letfn_test.cljs │ ├── macro_test.cljs │ ├── macro_test │ │ └── macros.clj │ ├── ns_test.cljs │ ├── ns_test │ │ ├── bar.cljs │ │ └── foo.cljs │ ├── quick.cljs │ ├── reader_test.cljs │ └── top-level.cljs │ ├── clojure │ ├── data_test.cljs │ └── string_test.cljs │ ├── foo │ └── ns_shadow_test.cljs │ └── test_runner.cljs └── web ├── blank.gif ├── build.sh ├── build2.sh ├── build3.sh ├── dots.png ├── images ├── bg-body.png ├── bg-rule.png └── github-icon.png ├── jsrepl.css ├── jsrepl.html ├── repl.html ├── repl3.html ├── stylesheets ├── base.css ├── fonts │ ├── exo-black-webfont.eot │ ├── exo-black-webfont.svg │ ├── exo-black-webfont.ttf │ ├── exo-black-webfont.woff │ ├── exo-bold-webfont.eot │ ├── exo-bold-webfont.svg │ ├── exo-bold-webfont.ttf │ ├── exo-bold-webfont.woff │ ├── exo-regular-webfont.eot │ ├── exo-regular-webfont.svg │ ├── exo-regular-webfont.ttf │ └── exo-regular-webfont.woff ├── himera.css ├── layout.css └── skeleton.css ├── synonym.html └── vendor ├── shBrushClojure.js ├── shBrushJScript.js ├── shCore.css ├── shCore.js ├── shThemeMarginalia.css └── xregexp-min.js /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | .idea 3 | /.DS_Store 4 | /classes 5 | /lib 6 | closure 7 | /core.js 8 | /coreadvanced.js 9 | /coresimple.js 10 | /out 11 | /web/out 12 | /node/out 13 | .repl 14 | *.swp 15 | *.zip 16 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "web/vendor/jq-console"] 2 | path = web/vendor/jq-console 3 | url = https://github.com/replit/jq-console 4 | [submodule "web/vendor/codemirror"] 5 | path = web/vendor/codemirror 6 | url = https://github.com/marijnh/CodeMirror 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sudo apt-get install wget -qq 3 | - sudo apt-get install unzip -qq 4 | 5 | before_script: 6 | - echo "Fetching V8..." 7 | - git clone --branch=master --depth=1 --quiet git://github.com/v8/v8.git v8 && cd v8 8 | - echo "Building V8" 9 | - make dependencies 10 | - make native 11 | - cd ./out/native/ 12 | - export V8_HOME=`pwd` 13 | - cd ../../../ 14 | - echo "Fetching Spidermonkey" 15 | - wget http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-mozilla-central/jsshell-linux-i686.zip 16 | - unzip jsshell-linux-i686.zip -d spidermonkey 17 | - cd spidermonkey 18 | - export SPIDERMONKEY_HOME=`pwd` 19 | - cd ../ 20 | - ./script/bootstrap 21 | 22 | script: 23 | - ./script/test 24 | -------------------------------------------------------------------------------- /Clojurescript.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## ClojureScript Compiler Compiled with ClojureScript? ## 2 | 3 | This is a **patched version of the ClojureScript compiler** that 4 | compiles to ClojureScript. Normally, the ClojureScript compiler is 5 | a pure Clojure program that runs on the JVM. This patched version runs 6 | from the compiled JavaScript. This project was kicked off by 7 | [kanaka](https://github.com/kanaka) and 8 | [chouser](https://github.com/chouser) during some intense hacking at 9 | Clojure/conj 2012. Kanaka continues to develop the fork towards the 10 | goal of being fully self-hosting (i.e. ClojureScript-in-ClojureScript). 11 | 12 | ### Why? 13 | 14 | * Why not? 15 | * Compilers are only cool once they are self-hosting (can compile 16 | their own code). This fork is not self-hosting yet, but that is the 17 | goal. 18 | * You can use ClojureScript without a JVM. 19 | * You can have a [ClojureScript REPL web 20 | app](http://kanaka.github.com/clojurescript/web/jsrepl.html) that 21 | runs locally in your browser (no server involved after loading the 22 | page). 23 | 24 | ### Current Caveats 25 | 26 | * JavaScript output is not optimized by the Google Closure Compiler 27 | (which is a Java program). 28 | * The code changes are not all compatible with the normal Clojure 29 | ClojureScript (JVM based) compiler. To make it compatible we really 30 | need [Feature Expressions in Clojure](http://dev.clojure.org/display/design/Feature+Expressions) 31 | * The :nodejs compilation target is currently broken. However, the 32 | `node/run.js` bootstrap script enables compiled CLJS code to be 33 | invoked that was not compiled with a :target. 34 | * Other miscellaneous broken things that have not been tracked down 35 | yet. 36 | 37 | ### Bugs 38 | 39 | - numeric keywords (:2) are broken 40 | - anonymous functions do not warn about arity 41 | - Unicode symbol breakage 42 | - hex numbers "0x7e7" 43 | - warnings during compile about *unchecked-if* 44 | 45 | 46 | ### TODOs 47 | 48 | - update to upstream ClojureScript 49 | - file I/O (at least on the node.js side) 50 | - misc functionality: require, use, var metadata, :private def check 51 | - self-hosting (compile ClojureScript compiler using node.js hosted ClojureScript compiler) 52 | - optional optimizations (single JS file output, etc) 53 | - tagged reader literals 54 | - get test/cljs/cljs/core_test.cljs to load/run successfully 55 | - line numbered errors 56 | - single file output and performance optimizations (without unused code removal) 57 | - better long line/multiline editing in web REPL 58 | 59 | ### Build 60 | 61 | The ClojureScript-in-ClojureScript compiler is compiled using Clojure (i.e. on the JVM). 62 | 63 | First, run `./script/bootstrap` which downloads the necessary dependencies: Clojure, Google Closure Library, Google Closure Compiler, and Rhino. This must be run from the root project directory. 64 | 65 | Next, run `./script/compile` to build the compiler. This might give off some warnings, but that's okay. 66 | 67 | You should now have a functioning ClojureScript compiler at `./bin/cljs`. 68 | 69 | 70 | ### Usage 71 | 72 | The `./bin/cljsc` script takes a file or project directory containing .cljs files. It creates an `out` folder with your compiled JavaScript. It optionally accepts a second argument with Google Closure Compiler options, although it currently won't work with any optimization mode other than `{:optimizations :none}` (the default). 73 | 74 | After building a cljs project, you will need to copy `./src/cljs/goog.js` into the `out` directory created by compilation if it doesn't already exist there. 75 | 76 | ### Examples 77 | 78 | #### Web REPL 79 | There is a sample project (a web-based REPL) you can build and play with inside the `web` directory. 80 | 81 | It comes with a build script: 82 | 83 | ``` 84 | cd web 85 | ./build2.sh 86 | ``` 87 | 88 | Now open the `web/repl.html` file in a browser. 89 | 90 | #### Node.js REPL 91 | 92 | For a REPL in Node.js, build the `src/cljs/noderepl.cljs` code: 93 | 94 | ``` 95 | cd node 96 | ../bin/cljsc ../noderepl.cljs > noderepl.js 97 | cp ../src/cljs/goog.js out/ 98 | ``` 99 | 100 | Now use the `run.js` bootstrap code to launch the repl: 101 | 102 | ``` 103 | ./run.js noderepl.js 104 | ``` 105 | 106 | #### Node.js compilation/evaluation 107 | For direct *.cljs file compilation/evaluation, build the nodecljs.cljs compiler: 108 | 109 | ``` 110 | cd node 111 | ../bin/cljsc ../src/cljs/nodecljs.cljs > nodecljs.js 112 | cp ../src/cljs/goog.js out/ 113 | ``` 114 | 115 | You can now use a combination of the `run.js` bootstrap code and 116 | `nodecljs.js` to compile/evaluate the `hello.cljs` file: 117 | 118 | ``` 119 | ./run.js nodecljs.js hello.cljs 120 | ``` 121 | 122 | 123 | 124 | -------- 125 | 126 | ## What is ClojureScript? ## 127 | 128 | ClojureScript is a new compiler for [Clojure](http://clojure.org) that targets JavaScript. It is designed to emit JavaScript code which is compatible with the advanced compilation mode of the [Google Closure](http://code.google.com/closure/) optimizing compiler. 129 | 130 | ## Getting Started ## 131 | 132 | * [Compare with JavaScript](http://himera.herokuapp.com/synonym.html) 133 | * [Try it online](http://himera.herokuapp.com/index.html) 134 | * Read the [Quick Start](https://github.com/clojure/clojurescript/wiki/Quick-Start) guide. 135 | * Read the [Documentation](https://github.com/clojure/clojurescript/wiki). 136 | * Look at the [Sample Applications](https://github.com/clojure/clojurescript/tree/master/samples). 137 | 138 | ## Questions, Feedback? ## 139 | 140 | Please point all of your questions and feedback [here](http://groups.google.com/group/clojure). 141 | 142 | ## Developers Welcome ## 143 | 144 | ClojureScript operates under the same license as Clojure. All contributors must have a signed CA (Contributor's Agreement) and submit their patch via the appropriate channels. If you're interested in contributing to the project, please see the [contributing](http://clojure.org/contributing) page on [clojure.org](http://clojure.org). 145 | 146 | ## License ## 147 | 148 | Copyright (c) Rich Hickey. All rights reserved. The use and 149 | distribution terms for this software are covered by the Eclipse 150 | Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 151 | which can be found in the file epl-v10.html at the root of this 152 | distribution. By using this software in any fashion, you are 153 | agreeing to be bound by the terms of this license. You must 154 | not remove this notice, or any other, from this software. 155 | -------------------------------------------------------------------------------- /benchmark/cljs/benchmark_runner.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.benchmark-runner 2 | (:refer-clojure :exclude [println]) 3 | (:require [cljs.reader :as reader])) 4 | 5 | (def println print) 6 | 7 | (set! *print-fn* js/print) 8 | 9 | (simple-benchmark [x 1] (identity x) 1000000) 10 | 11 | (println ";; array-reduce & ci-reduce") 12 | (def arr (let [arr (array)] 13 | (dotimes [i 1000000] 14 | (.push arr i)) 15 | arr)) 16 | (defn sum [a b] (+ a b)) 17 | (simple-benchmark [coll (seq arr)] (ci-reduce coll + 0) 1) 18 | (simple-benchmark [coll (seq arr)] (ci-reduce coll sum 0) 1) 19 | (simple-benchmark [coll arr] (array-reduce coll + 0) 1) 20 | (simple-benchmark [coll arr] (array-reduce coll sum 0) 1) 21 | 22 | (println ";;; instance?") 23 | ;; WARNING: will get compiled away under advanced 24 | (simple-benchmark [coll []] (instance? PersistentVector coll) 1000000) 25 | (println ";;; satisfies?") 26 | (simple-benchmark [coll (list 1 2 3)] (satisfies? ISeq coll) 1000000) 27 | (simple-benchmark [coll [1 2 3]] (satisfies? ISeq coll) 1000000) 28 | (println) 29 | 30 | (println ";;; list ops") 31 | (simple-benchmark [coll (list 1 2 3)] (first coll) 1000000) 32 | (simple-benchmark [coll (list 1 2 3)] (-first coll) 1000000) 33 | (simple-benchmark [coll (list 1 2 3)] (rest coll) 1000000) 34 | (simple-benchmark [coll (list 1 2 3)] (-rest coll) 1000000) 35 | (simple-benchmark [] (list) 1000000) 36 | (simple-benchmark [] (list 1 2 3) 1000000) 37 | (println) 38 | 39 | (println ";;; vector ops") 40 | (simple-benchmark [] [] 1000000) 41 | (simple-benchmark [] [1 2 3] 1000000) 42 | (simple-benchmark [coll [1 2 3]] (transient coll) 100000) 43 | (simple-benchmark [coll [1 2 3]] (nth coll 0) 1000000) 44 | (simple-benchmark [coll [1 2 3]] (-nth coll 0) 1000000) 45 | (simple-benchmark [coll [1 2 3]] (conj coll 4) 1000000) 46 | (simple-benchmark [coll [1 2 3]] (-conj coll 4) 1000000) 47 | (simple-benchmark [coll [1 2 3]] (seq coll) 1000000) 48 | (simple-benchmark [coll (seq [1 2 3])] (first coll) 1000000) 49 | (simple-benchmark [coll (seq [1 2 3])] (-first coll) 1000000) 50 | (simple-benchmark [coll (seq [1 2 3])] (rest coll) 1000000) 51 | (simple-benchmark [coll (seq [1 2 3])] (-rest coll) 1000000) 52 | (simple-benchmark [coll (seq [1 2 3])] (next coll) 1000000) 53 | (println) 54 | 55 | (println ";;; large vector ops") 56 | (simple-benchmark [] (reduce conj [] (range 40000)) 10) 57 | (simple-benchmark [coll (reduce conj [] (range (+ 32768 32)))] (conj coll :foo) 100000) 58 | (simple-benchmark [coll (reduce conj [] (range 40000))] (assoc coll 123 :foo) 100000) 59 | (simple-benchmark [coll (reduce conj [] (range (+ 32768 33)))] (pop coll) 100000) 60 | (println) 61 | 62 | (println ";;; transients") 63 | (print "transient vector, conj! 1000000 items") 64 | (time 65 | (let [v (transient [])] 66 | (loop [i 0 v v] 67 | (if (> i 1000000) 68 | (persistent! v) 69 | (recur (inc i) (conj! v i)))))) 70 | 71 | (println ";;; reduce lazy-seqs, vectors, ranges") 72 | (simple-benchmark [coll (take 100000 (iterate inc 0))] (reduce + 0 coll) 1) 73 | (simple-benchmark [coll (range 1000000)] (reduce + 0 coll) 1) 74 | (simple-benchmark [coll (into [] (range 1000000))] (reduce + 0 coll) 1) 75 | (println) 76 | 77 | (println ";; apply") 78 | (simple-benchmark [coll (into [] (range 1000000))] (apply + coll) 1) 79 | (println) 80 | 81 | (println ";;; map / record ops") 82 | (simple-benchmark [coll {:foo 1 :bar 2}] (get coll :foo) 1000000) 83 | (simple-benchmark [coll {:foo 1 :bar 2}] (-lookup coll :foo nil) 1000000) 84 | (simple-benchmark [coll {:foo 1 :bar 2}] (:foo coll) 1000000) 85 | (defrecord Foo [bar baz]) 86 | (simple-benchmark [coll (Foo. 1 2)] (:bar coll) 1000000) 87 | (simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :baz 3) 100000) 88 | (simple-benchmark [coll {:foo 1 :bar 2}] (assoc coll :foo 2) 100000) 89 | (simple-benchmark [coll {:foo 1 :bar 2}] 90 | (loop [i 0 m coll] 91 | (if (< i 100000) 92 | (recur (inc i) (assoc m :foo 2)) 93 | m)) 94 | 1) 95 | (println ";;; persistent hash maps") 96 | (def pmap (into cljs.core.PersistentHashMap/EMPTY 97 | [[:a 0] [:b 1] [:c 2] [:d 3] [:e 4] [:f 5] [:g 6] [:h 7] 98 | [:i 8] [:j 9] [:k 10] [:l 11] [:m 12] [:n 13] [:o 14] [:p 15] 99 | [:q 16] [:r 17] [:s 18] [:t 19] [:u 20] [:v 21] [:w 22] [:x 23] 100 | [:y 24] [:z 25] [:a0 26] [:b0 27] [:c0 28] [:d0 29] [:e0 30] [:f0 31]])) 101 | (simple-benchmark [key :f0] (hash key) 1000000) 102 | (simple-benchmark [key :unsynchronized-mutable] (hash key false) 1000000) 103 | (simple-benchmark [key :unsynchronized-mutable] (hash key) 1000000) 104 | (def hash-coll-test 105 | (loop [i 0 r []] 106 | (if (< i 1000) 107 | (recur (inc i) (conj r (str "foo" i))) 108 | r))) 109 | (simple-benchmark [coll hash-coll-test] (hash-coll coll) 100) 110 | (simple-benchmark [coll pmap] (:f0 coll) 1000000) 111 | (simple-benchmark [coll pmap] (get coll :f0) 1000000) 112 | (simple-benchmark [coll pmap] (-lookup coll :f0 nil) 1000000) 113 | (simple-benchmark [coll pmap] (assoc coll :g0 32) 1000000) 114 | (simple-benchmark [coll pmap] 115 | (loop [i 0 m coll] 116 | (if (< i 1000000) 117 | (recur (inc i) (assoc m :a 1)) 118 | m)) 119 | 1) 120 | (simple-benchmark [coll cljs.core.PersistentHashMap/EMPTY] (assoc coll :f0 1) 1000000) 121 | (println) 122 | 123 | (println ";;; set ops") 124 | (simple-benchmark [] #{} 100000) 125 | (simple-benchmark [] #{1 2 3} 100000) 126 | (simple-benchmark [coll #{1 2 3}] (conj coll 4) 100000) 127 | (println) 128 | 129 | (println ";;; seq ops") 130 | (simple-benchmark [coll (range 500000)] (reduce + coll) 1) 131 | (println) 132 | 133 | (println ";;; reader") 134 | (simple-benchmark [s "{:foo [1 2 3]}"] (reader/read-string s) 1000) 135 | (println) 136 | 137 | (println ";;; range") 138 | (simple-benchmark [r (range 1000000)] (last r) 1) 139 | (println) 140 | 141 | (defn ints-seq 142 | ([n] (ints-seq 0 n)) 143 | ([i n] 144 | (when (< i n) 145 | (lazy-seq 146 | (cons i (ints-seq (inc i) n)))))) 147 | (def r (ints-seq 1000000)) 148 | (println ";;; lazy-seq") 149 | (println ";;; first run") 150 | (simple-benchmark [r r] (last r) 1) 151 | (println ";;; second run") 152 | (simple-benchmark [r r] (last r) 1) 153 | (println) 154 | 155 | (println "\n") 156 | -------------------------------------------------------------------------------- /bin/cljsc: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Compile a single cljs file or a directory of cljs files into a 4 | # single JavaScript file. 5 | 6 | if [ "$CLOJURESCRIPT_HOME" = "" ]; then 7 | CLOJURESCRIPT_HOME="`dirname $0`/.." 8 | fi 9 | 10 | CLJSC_CP='' 11 | for next in lib/*: src/clj: src/cljs: test/cljs; do 12 | CLJSC_CP="${CLJSC_CP}${CLOJURESCRIPT_HOME}/${next}" 13 | done 14 | 15 | if test "$#" -eq 0 16 | then 17 | echo 'Usage: cljsc ' 18 | echo ' cljsc "{:optimizations :advanced}"' 19 | else 20 | java -server -cp "$CLJSC_CP" clojure.main "$CLOJURESCRIPT_HOME/bin/cljsc.clj" "$@" 21 | fi 22 | -------------------------------------------------------------------------------- /bin/cljsc.bat: -------------------------------------------------------------------------------- 1 | 2 | @echo off 3 | setLocal EnableDelayedExpansion 4 | 5 | if "%CLOJURESCRIPT_HOME%" == "" set CLOJURESCRIPT_HOME=%~dp0..\ 6 | 7 | set CLASSPATH=%CLOJURESCRIPT_HOME%src\clj;%CLOJURESCRIPT_HOME%src\cljs" 8 | for /R "%CLOJURESCRIPT_HOME%\lib" %%a in (*.jar) do ( 9 | set CLASSPATH=!CLASSPATH!;%%a 10 | ) 11 | set CLASSPATH=!CLASSPATH!" 12 | 13 | if (%1) == () ( 14 | echo Usage: "cljsc > out.js" 15 | echo "cljsc {:optimiztions :advanced} > out.js" 16 | ) else ( 17 | java -server -cp "%CLASSPATH%" clojure.main "%CLOJURESCRIPT_HOME%\bin\cljsc.clj" %* 18 | ) 19 | -------------------------------------------------------------------------------- /bin/cljsc.clj: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (require '[cljs.closure :as closure]) 10 | 11 | (defn transform-cl-args 12 | [args] 13 | (let [source (first args) 14 | opts-string (apply str (interpose " " (rest args))) 15 | options (when (> (count opts-string) 1) 16 | (try (read-string opts-string) 17 | (catch Exception e (println e))))] 18 | {:source source :options (merge {:output-to :print} options)})) 19 | 20 | (let [args (transform-cl-args *command-line-args*)] 21 | (closure/build (:source args) (:options args))) 22 | -------------------------------------------------------------------------------- /devnotes/README.org: -------------------------------------------------------------------------------- 1 | * ClojureScript 2 | - What: Clojure running on Javascript VMs 3 | - Why: Clojure rocks, Javascript reaches 4 | - When: Now! - a compiler exists, we need libraries and tool integration. Full day sessions 6/10 and 6/17 5 | - Where: In stealth mode 'here' at Clojure/core 6 | - How: ClojureScript -> ClojureScript-Compiler -> Javascript -> [Google-Closure-JS->JS-Compiler -> Optimized-Javascript] ->Browser/V8/Node/PhoneGap... 7 | - Who: You, if you're interested in: 8 | - How hand-written recursive descent compilers work (the ClojureScript compiler is about 1/6 the code of the CoffeeScript compiler) 9 | - Writing libraries using Clojure's latest type and polymorphism tools 10 | - How Clojure works - its data structures and abstractions 11 | - Extending the reach of Clojure 12 | - Google's industrial-strength JS tools 13 | - Investigating how powerful code-emitting tools can change the face 14 | of web and mobile development... 15 | * Getting Started 16 | - Clone the repo 17 | - cd clojurescript 18 | - run script/bootstrap 19 | - copy clojure.jar into /lib 20 | - script/repl will start a properly-classpathed repl 21 | * Starting the clojurescript repl 22 | - (require '[cljs.compiler :as comp]) 23 | - (def jse (comp/repl-env)) 24 | - (comp/repl jse) 25 | * Reading list 26 | - If you are interested in participating, please read: 27 | - [[http://www.amazon.com/Closure-Definitive-Guide-Michael-Bolin/dp/1449381871][Closure-Definitive-Guide-Michael-Bolin]] 28 | - and maybe: 29 | - [[http://www.amazon.com/JavaScript-Good-Parts-Douglas-Crockford/dp/0596517742][JavaScript-Good-Parts-Douglas-Crockford]] 30 | - [[http://www.amazon.com/Performance-JavaScript-Faster-Application-Interfaces/dp/059680279X][Performance-JavaScript-Faster-Application-Interfaces]] 31 | - [[http://www.amazon.com/JavaScript-Patterns-Stoyan-Stefanov/dp/0596806752][JavaScript-Patterns-Stoyan-Stefanov]] 32 | - Those looking to cram tonight can get the O'Reilly Closure book on kindle above or ebook directly: 33 | - [[http://oreilly.com/catalog/0636920001416/]] 34 | * More info 35 | [[https://github.com/relevance/clojurescript/wiki][Check the Wiki]] 36 | -------------------------------------------------------------------------------- /devnotes/bcrepl.org: -------------------------------------------------------------------------------- 1 | * ClojureScript browser connected REPL 2 | ** send cljs compiler output to the browser to be evaluated 3 | ** send results back to the command line process to be printed 4 | ** side effects happen in the browser 5 | ** abstract communication away using goog library 6 | *** Goog abstraction for websockets? Ideal! 7 | *** Polling? It will work everywhere. 8 | *** Ideally an abstraction over both that prefers websockets but doesn't fail and doesn't complain loudly. 9 | ** evaluation daemon for the browser 10 | ** launch browser 11 | ** transparent update of bound symbols? We should test. 12 | ** brepl has its own solution for deps, we'd like to tie into the ClojureScript dependency story 13 | ** require mechanisms are out; the source that forms the repl's environment will need to be updated and the page reloaded 14 | -------------------------------------------------------------------------------- /devnotes/day2.org: -------------------------------------------------------------------------------- 1 | * ClojureScript Day #2 2 | * Welcome Thortech! 3 | ** Eric, Frank and Tom 4 | *** Long time cohorts 5 | * Tips 6 | ** Don't define things in terms of undefined things 7 | *** someone else will just trip over later 8 | ** Test 9 | *** nil 10 | ** Encapsulate use of -methods in a single place 11 | ** Where's the global namespace? 12 | * Where are we at 13 | * Where are we going 14 | ** [[file:corelib.org][Core lib punchlist]] 15 | ** [[file:~/dev/clojurescript/todo.org][To do]] 16 | ** [[https://github.com/relevance/clojurescript/issues][Tickets]] 17 | * Release 1 18 | ** Make goog-compatible libs work 19 | ** Data structures 20 | *** work but are not optimal for large instances 21 | *** persistent guarantees 22 | ** seq library 23 | ** associative library 24 | ** indexed library 25 | ** atoms 26 | ** binding 27 | ** great tooling 28 | *** push button 29 | ** reader? 30 | *** print-read 31 | ** regex 32 | * Release 2 33 | ** DOM manipulation 34 | ** Can I use jQuery? 35 | ** bitops 36 | ** multimethods 37 | ** hierarchy 38 | ** reader + record support 39 | ** unchecked 40 | ** bitops 41 | ** print 42 | ** eventing value add 43 | ** DOM value add 44 | ** UI value add 45 | -------------------------------------------------------------------------------- /devnotes/talk.org: -------------------------------------------------------------------------------- 1 | * Title 2 | ** Clojure 3 | *** Rocks 4 | ** Javascript 5 | *** Reaches 6 | ** Announcing Clojure on Javascript 7 | *** ClojureScript 8 | * Problem statement 9 | ** Javascript is the only programmable technology in key target environments 10 | *** i.e. the browser 11 | *** nothing will change that for years to come 12 | ** and has the greatest reach in other key environments 13 | *** i.e. mobile 14 | ** Javascript (the language) is not very robust 15 | *** Fewer good parts than bad parts 16 | *** Much convention and discipline required to avoid headaches 17 | *** Conventions differ between shops, libs 18 | ** Ever increasing pressure to create richer applications in these environments 19 | *** requiring more, and larger, libraries 20 | **** ordinary minification doesn't scale up 21 | *** increasing requirements complexity 22 | **** can't add language or environment complexity on top 23 | * Rationale 24 | ** Clojure is arguably simpler, more powerful and more robust than JS 25 | ** JS VMs getting faster and more sophisticated 26 | ** Putting Clojure on JS empowers developers 27 | * Strategy 28 | ** Compile (a substantial subset of) Clojure to Javascript source 29 | ** Leverage best-of-breed JS approaches 30 | ** Look beyond the browser 31 | ** Non-objectives 32 | *** Complete Clojure 33 | *** Portable large applications 34 | *** Browser REPL demos etc 35 | ** Target is production applications 36 | * Tactics 37 | ** Clojure[Script] in Clojure 38 | *** Written in Clojure and itself 39 | ** Clojure on Closure 40 | *** Google's JS toolkit 41 | ** Clojure[Script] in Clojure 42 | ** Google Closure 43 | ** some subset of my gclosure lightning talk 44 | * Where we are at 45 | ** What's there? 46 | *** Compiler 47 | *** REPL 48 | *** All the primitives (that make sense) 49 | *** Arity overloading 50 | *** Macros 51 | *** Seqs, maps, vectors, sets 52 | **** and supporting library 53 | **** callable maps, vectors, sets 54 | *** Symbols and keywords 55 | *** deftypes and protocols 56 | *** all the core abstractions as protocols 57 | *** destructuring 58 | *** 2500 lines of core libs! 59 | *** clojure.string and .set .walk .zip 60 | *** regex 61 | *** reader? 62 | *** Full participation with Google Closure library 63 | **** ns mechanism maps to provide/require 64 | *** compile-file and compile-project 65 | ** What's not (yet)? 66 | *** Full collection persistence 67 | *** defrecord 68 | *** Multimethods 69 | *** Hierarchy 70 | *** Rich numerics 71 | *** Testing framework 72 | *** Misc core lib 73 | ** What won't be? 74 | *** things related to threads 75 | *** eval and runtime compilation 76 | *** structs, proxy, Java type stuff 77 | *** Runtime reification of: 78 | **** Vars 79 | **** Namespaces 80 | **** Protocols 81 | **** etc 82 | ** TBD 83 | *** optimizations 84 | **** chunks, transients 85 | *** agents (on webworkers?) 86 | *** unchecked 87 | ** What's different 88 | *** no runtime Vars 89 | *** some in-function subsetting 90 | **** e.g. satisfies? is a macro, can't be mapped/applied 91 | ** It's alpha 92 | * Where we are going 93 | ** This is Clojure's client story 94 | ** This is Clojure's mobile story 95 | ** This is Clojure's CLI scripting story 96 | * The Team thus far - Clojure/core and friends 97 | ** Aaron Bedra 98 | ** Alan Dipert 99 | ** Alex Redington 100 | ** Bobby Calderwood 101 | ** Brenton Ashworth 102 | ** Chris Houser 103 | ** Devin Walters 104 | ** Eric Thorsen 105 | ** Frank Failla 106 | ** Michael Fogus 107 | ** Jonathan Clagett 108 | ** Jess Martin 109 | ** Luke VanderHart 110 | ** Chris Redinger 111 | ** Stuart Halloway 112 | ** Stuart Sierra 113 | ** Tom Hickey 114 | * Participating 115 | ** This is a Clojure dev project 116 | *** all with Clojure CAs welcome to participate 117 | ** The Friday invite 118 | ** The Conj 119 | * Demo 120 | ** REPL 121 | ** Compilation 122 | ** Web app 123 | ** CLI app? 124 | * Q & A 125 | 126 | 127 | -------------------------------------------------------------------------------- /devnotes/testing: -------------------------------------------------------------------------------- 1 | Definitely a work-in-progress. 2 | 3 | To run tests before you commit: 4 | 5 | script/test 6 | 7 | To add tests: 8 | 9 | * Create test fiels in the test/cljs directory. 10 | * Write fns that throw an exception on failure. 11 | * Call those fns from test/cljs/cljs/test_runner.cljs 12 | 13 | 14 | -------------------------------------------------------------------------------- /devnotes/todo.org: -------------------------------------------------------------------------------- 1 | #+TODO: TODO IN-PROGRESS REVIEW DONE 2 | * The near term tasks 3 | * Compiler 4 | ** IN-PROGRESS throw/try/catch/finally :@stuarthalloway: 5 | * Data structures 6 | ** IN-PROGRESS keyword :@levand: 7 | *** requires interning strategy 8 | **** possibly compiler support for same 9 | *** string starting with noncharacter code 10 | **** \uFFFE and \uFFFF are guaranteed noncharacters 11 | **** use as prefix for keywords and symbols 12 | **** must test in predicates string? symbol? keyword? 13 | ** IN-PROGRESS symbol :@levand: 14 | *** string starting with noncharacter code 15 | ** DONE cons cell/list 16 | ** DONE map 17 | *** first cut COW, string uniqueness required 18 | ** DONE vector 19 | *** first cut, COW, internal array 20 | ** TODO numbers 21 | *** js native number is our double 22 | *** goog.math.Long? 23 | **** building Long objects defeats fixnum support in JS VMs 24 | **** but they are 32-bit - some type bits 25 | * Abstractions 26 | ** TODO Clojure's interfaces 27 | *** we don't need all of them 28 | Associative 29 | Counted 30 | Fn 31 | IBlockingDeref 32 | IChunk 33 | IChunkedSeq 34 | IDeref 35 | IEditableCollection 36 | IFn 37 | IKeywordLookup 38 | ILookup 39 | ILookupSite 40 | ILookupThunk 41 | IMapEntry 42 | IMeta 43 | Indexed 44 | IndexedSeq 45 | IObj 46 | IPending 47 | IPersistentCollection 48 | IPersistentList 49 | IPersistentMap 50 | IPersistentSet 51 | IPersistentStack 52 | IPersistentVector 53 | IProxy 54 | IRecord 55 | IReduce 56 | IRef 57 | IReference 58 | ISeq 59 | ITransientAssociative 60 | ITransientCollection 61 | ITransientMap 62 | ITransientSet 63 | ITransientVector 64 | IType 65 | MapEquivalence 66 | Named 67 | Reversible 68 | Seqable 69 | Sequential 70 | Settable 71 | Sorted 72 | ** Naming convention for protocols? 73 | *** IBlah 74 | ** TODO equality and hashing 75 | *** investigate gclosure and GWT 76 | ** TODO seqable 77 | ** TODO collection 78 | ** TODO counted 79 | ** DONE seq 80 | ** TODO lookup 81 | ** TODO associative 82 | ** TODO indexed 83 | ** TODO map 84 | ** TODO set 85 | ** TODO vector 86 | ** TODO deref 87 | ** TODO metadata 88 | * Runtime Lib 89 | ** key missing macros 90 | *** binding 91 | **** single threaded 92 | **** save, set!, finally restore 93 | **** deps: try/finally primitives in compiler 94 | *** dotimes 95 | ** math ops 96 | *** intrinsify built-ins 97 | *** handle variadic 98 | ** core.cljs! 99 | *** crank through core.clj 100 | *** see [[file:docs/corelib.org][docs/corelib.org]] 101 | * Tools 102 | ** getting set up story 103 | *** gclosure library 104 | *** gclosure compiler 105 | *** V8 106 | **** optional for now? 107 | ** DONE REPL 108 | *** there's a ticket for this 109 | ** Integration of gclosure library 110 | *** how do we reference/load? 111 | **** REPL runtime behavior of provide/require 112 | *** versioning issues 113 | **** just SVN revs 114 | **** how to bind to version 115 | ** Testing 116 | *** anything good in gclosure? 117 | ** Build 118 | *** deps 119 | *** glcosure compiler 120 | **** invocation via API gives most control 121 | **** but deps a Python thingy 122 | -------------------------------------------------------------------------------- /node/hello.cljs: -------------------------------------------------------------------------------- 1 | (def sqr (fn* [x] (* x x))) 2 | 3 | (println "hello world" (sqr 16)) 4 | -------------------------------------------------------------------------------- /node/run.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Launch a CLJS compiled program using node 4 | // - First argument is the path to the compiled *.js file 5 | // - Rest of the arguments are passed to the *main-cli* 6 | 7 | (function() { 8 | var path = require("path"), 9 | targ = process.argv[2], 10 | ns = path.basename(targ).replace(/[.]js$/, ""), 11 | jsfile = path.resolve("./", targ); 12 | 13 | // Load the Closure Library wrapper 14 | require('./out/goog.js'); 15 | 16 | // Load the initial compiled file 17 | require(jsfile); 18 | goog.require(ns); 19 | 20 | // Call the users's main function 21 | if(cljs.core._STAR_main_cli_fn_STAR_) cljs.core.apply.call(null,cljs.core._STAR_main_cli_fn_STAR_,cljs.core.drop.call(null,3,process.argv)); 22 | })(); 23 | 24 | 25 | -------------------------------------------------------------------------------- /node/run2.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | // Launch a CLJS compiled program using node 4 | // - First argument is the path to the compiled *.js file 5 | // - Rest of the arguments are passed to the *main-cli* 6 | 7 | (function() { 8 | var path = require("path"), 9 | targ = process.argv[2], 10 | ns = path.basename(targ).replace(/[.]js$/, ""), 11 | jsfile = path.resolve("./", targ); 12 | 13 | // Load the Closure Library wrapper 14 | require('./out2/goog.js'); 15 | 16 | // Load the initial compiled file 17 | require(jsfile); 18 | goog.require(ns); 19 | 20 | // Call the users's main function 21 | if(cljs.core._STAR_main_cli_fn_STAR_) cljs.core.apply.call(null,cljs.core._STAR_main_cli_fn_STAR_,cljs.core.drop.call(null,3,process.argv)); 22 | })(); 23 | 24 | 25 | -------------------------------------------------------------------------------- /node/shebang.cljs: -------------------------------------------------------------------------------- 1 | #!./run.js nodecljs.js 2 | 3 | (ns shebang-test) 4 | 5 | (def dbl (fn* [x] (* 2 x))) 6 | 7 | (println "Hello World UNIX World.") 8 | (println "(dbl 16) is:" (dbl 16)) 9 | 10 | 8 11 | -------------------------------------------------------------------------------- /pom.template.xml: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.clojure 4 | clojurescript 5 | 6 | CLOJURESCRIPT_VERSION 7 | jar 8 | ClojureScript 9 | 10 | https://github.com/clojure/clojurescript 11 | 12 | 13 | ClojureScript compiler and core runtime library. 14 | 15 | 16 | 17 | 18 | Eclipse Public License 1.0 19 | http://opensource.org/licenses/eclipse-1.0.php 20 | repo 21 | 22 | 23 | 24 | 25 | 26 | com.google.javascript 27 | closure-compiler 28 | r1918 29 | 30 | 31 | org.clojure 32 | google-closure-library 33 | 0.0-1376-2 34 | 35 | 36 | org.mozilla 37 | rhino 38 | 1.7R3 39 | 40 | 41 | 42 | 43 | Aaron Bedra 44 | Alan Dipert 45 | Alan Malloy 46 | Alen Ribic 47 | Alex Redington 48 | Bobby Calderwood 49 | Brandon Bloom 50 | Brenton Ashworth 51 | Chris Houser 52 | Christopher Redinger 53 | Creighton Kirkendall 54 | David Nolen 55 | Devin Walters 56 | Eric Thorsen 57 | Frank Failla 58 | Hubert Iwaniuk 59 | Hugo Duncan 60 | Jess Martin 61 | John Li 62 | Jonas Enlund 63 | Juergen Hoetzel 64 | Kevin J. Lynagh 65 | Laszlo Toeroek 66 | Luke VanderHart 67 | Michael Fogus 68 | Michał Marczyk 69 | Moritz Ulrich 70 | Nicola Mometto 71 | Paul Michael Bauer 72 | Rich Hickey 73 | Roman Gonzalez 74 | Russ Olsen 75 | Stuart Halloway 76 | Stuart Sierra 77 | Takahiro Hozumi 78 | Thomas Scheiblauer 79 | Tom Hickey 80 | Wilkes Joiner 81 | 82 | 83 | 84 | scm:git:git://github.com/clojure/clojurescript.git 85 | scm:git:git@github.com:clojure/clojurescript.git 86 | https://github.com/clojure/clojurescript 87 | 88 | 89 | -------------------------------------------------------------------------------- /samples/dom/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | dom.js -------------------------------------------------------------------------------- /samples/dom/src/dom/test.cljs: -------------------------------------------------------------------------------- 1 | (ns dom.test 2 | (:require [clojure.browser.event :as event] 3 | [clojure.browser.dom :as dom])) 4 | 5 | (defn log [& args] 6 | (.log js/console (apply pr-str args))) 7 | 8 | (defn log-obj [obj] 9 | (.log js/console obj)) 10 | 11 | (defn log-listener-count [] 12 | (log "listener count: " (event/total-listener-count))) 13 | 14 | (def source (dom/get-element "source")) 15 | (def destination (dom/get-element "destination")) 16 | 17 | (dom/append source 18 | (dom/element "Testing me ") 19 | (dom/element "out!")) 20 | 21 | (def success-count (atom 0)) 22 | 23 | (log-listener-count) 24 | 25 | (event/listen source 26 | :click 27 | (fn [e] 28 | (let [i (swap! success-count inc) 29 | e (dom/element :li 30 | {:id "testing" 31 | :class "test me out please"} 32 | "It worked!")] 33 | (log-obj e) 34 | (log i) 35 | (dom/append destination 36 | e)))) 37 | 38 | (log-obj (dom/element "Text node")) 39 | (log-obj (dom/element :li)) 40 | (log-obj (dom/element :li {:class "foo"})) 41 | (log-obj (dom/element :li {:class "bar"} "text node")) 42 | (log-obj (dom/element [:ul [:li :li :li]])) 43 | (log-obj (dom/element :ul [:li :li :li])) 44 | (log-obj (dom/element :li {} [:ul {} [:li :li :li]])) 45 | (log-obj (dom/element [:li {:class "baz"} [:li {:class "quux"}]])) 46 | 47 | (log-obj source) 48 | (log-listener-count) -------------------------------------------------------------------------------- /samples/dom/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | DOM testing 12 | 13 | 14 | 17 | 18 | 19 | 20 |
21 |
    22 | 23 | 24 | 25 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /samples/hello-js/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | hello*.js 3 | -------------------------------------------------------------------------------- /samples/hello-js/README.md: -------------------------------------------------------------------------------- 1 | Simple ClojureScript Project Example Using an External JavaScript Library 2 | 3 | One-time Setup 4 | ============== 5 | 6 | - Create a CLOJURESCRIPT_HOME environment variable which points to the 7 | ClojureScript root directory. 8 | 9 | - If you have not already done so, execute 10 | 11 | $CLOJURESCRIPT_HOME/script/bootstrap 12 | 13 | - Add $CLOJURESCRIPT_HOME/bin to your PATH. 14 | 15 | 16 | Simple external JavaScript file 17 | =============================== 18 | 19 | 20 | 21 | Run in Development Mode 22 | ----------------------- 23 | 24 | Development mode allows for each file to be loaded in a separate script tag so 25 | that errors can be easily tracked to the offending file. 26 | 27 | cljsc src > hello-js.js 28 | 29 | After running the above command, open hello-js-dev.html. Notice that each required 30 | JavaScript file has been loaded in its most readable form. 31 | 32 | Run Optimized JavaScript 33 | ------------------------ 34 | 35 | Once an application is ready for production, a single optimized file can be produced. 36 | 37 | cljsc src {:optimizations :advanced} > hello-js.js 38 | 39 | After running the above command, open hello-js.html to view the result. 40 | 41 | 42 | Using an externed JavaScript file 43 | ================================= 44 | 45 | To see how external calls are optimized away, execute the following: 46 | 47 | cljsc src '{:optimizations :advanced :output-to "hello-extern.js"}' 48 | 49 | After running the above command, open hello-extern.html to view the result. You should see nothing and possibly a JavaScript error. The solution is to compile the ClojureScript source with a referred externs file as follows: 50 | 51 | cljsc src '{:optimizations :advanced :output-to "hello-extern.js" :externs ["externs.js"]}' 52 | 53 | Again after running the above command, open hello-extern.html to view the result. You should see an alert box. 54 | -------------------------------------------------------------------------------- /samples/hello-js/externed-lib.js: -------------------------------------------------------------------------------- 1 | external = {}; 2 | 3 | external.lib = { 4 | send_alert : function (msg) { 5 | alert("Sending Alert via " + msg + "!"); 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /samples/hello-js/externs.js: -------------------------------------------------------------------------------- 1 | var external = {}; 2 | external.lib = {}; 3 | external.lib.send_alert = function() {}; 4 | -------------------------------------------------------------------------------- /samples/hello-js/hello-extern.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello Externed JavaScript Library 4 | 5 | 6 |

    Hello Externed JavaScript Library!

    7 | 8 | 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/hello-js/hello-js-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello External JavaScript Library 4 | 5 | 6 |

    Hello External JavaScript Library!

    7 | 8 | 9 | 10 | 11 | 14 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/hello-js/hello-js.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello External JavaScript Library 4 | 5 | 6 |

    Hello External JavaScript Library!

    7 | 8 | 9 | 10 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /samples/hello-js/my-external-lib.js: -------------------------------------------------------------------------------- 1 | function send_alert(msg) { 2 | alert("Sending Alert via " + msg + "!"); 3 | }; 4 | -------------------------------------------------------------------------------- /samples/hello-js/src/hello-js/core.cljs: -------------------------------------------------------------------------------- 1 | (ns hello-js.core) 2 | 3 | (defn ^:export popup-msg 4 | [msg] 5 | (js/send_alert msg)) 6 | 7 | (popup-msg "ClojureScript calling a global function defined in an external JavaScript library") 8 | 9 | (popup-msg (str "ClojureScript: the time is now " (js/Date.))) 10 | -------------------------------------------------------------------------------- /samples/hello-js/src/hello-js/extern-example.cljs: -------------------------------------------------------------------------------- 1 | (ns hello.extern-example) 2 | 3 | (defn ^:export foo [] 42) 4 | 5 | (external.lib/send_alert "ClojureScript calling a function defined in an externed JavaScript library") 6 | -------------------------------------------------------------------------------- /samples/hello/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | hello.js 3 | -------------------------------------------------------------------------------- /samples/hello/README.md: -------------------------------------------------------------------------------- 1 | Simple ClojureScript Project Example. 2 | 3 | One-time Setup 4 | ============== 5 | 6 | - Create a CLOJURESCRIPT_HOME environment variable which points to the 7 | ClojureScript root directory. 8 | 9 | - If you have not already done so, execute 10 | 11 | $CLOJURESCRIPT_HOME/script/bootstrap 12 | 13 | - Add $CLOJURESCRIPT_HOME/bin to your PATH. 14 | 15 | Run in Development Mode 16 | ======================= 17 | 18 | Development mode allows for each file to be loaded in a separate script tag so 19 | that errors can be easily tracked to the offending file. 20 | 21 | cljsc src > hello.js 22 | 23 | After running the above command, open hello-dev.html. Notice that each required 24 | JavaScript file has been loaded in its most readable form. 25 | 26 | Run Optimized JavaScript 27 | ======================== 28 | 29 | Once an application is ready for production, a single optimized file can be produced. 30 | 31 | cljsc src {:optimizations :advanced} > hello.js 32 | 33 | After running the above command, open hello.html to view the result. 34 | 35 | -------------------------------------------------------------------------------- /samples/hello/hello-dev.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello ClojureScript 4 | 5 | 6 |

    Hello ClojureScript!

    7 | 8 | 9 | 10 | 13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /samples/hello/hello.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Hello ClojureScript 4 | 5 | 6 |

    Hello ClojureScript!

    7 | 8 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /samples/hello/src/hello/core.cljs: -------------------------------------------------------------------------------- 1 | (ns hello.core 2 | (:require [hello.foo.bar :as bar])) 3 | 4 | (defn ^{:export greet} greet [n] 5 | (str "Hello " n)) 6 | 7 | (defn ^:export sum [xs] 8 | (bar/sum xs)) 9 | -------------------------------------------------------------------------------- /samples/hello/src/hello/foo/bar.cljs: -------------------------------------------------------------------------------- 1 | (ns hello.foo.bar) 2 | 3 | (defn sum [xs] 4 | (reduce + 0 xs)) 5 | -------------------------------------------------------------------------------- /samples/nodehello.cljs: -------------------------------------------------------------------------------- 1 | (ns nodehello) 2 | 3 | (defn -main [& args] 4 | (println (apply str (map [\space "world" "hello"] [2 0 1])))) 5 | 6 | (set! *main-cli-fn* -main) 7 | 8 | (comment 9 | ; Compile this using a command line like: 10 | 11 | CLOJURESCRIPT_HOME=".../clojurescript/" \ 12 | bin/cljsc samples/nodehello.cljs {:target :nodejs} \ 13 | > out/nodehello.js 14 | 15 | ; Then run using: 16 | nodejs out/nodehello.js 17 | 18 | ) 19 | -------------------------------------------------------------------------------- /samples/nodels.cljs: -------------------------------------------------------------------------------- 1 | ; This one doesn't yet work with :optimizations :advanced 2 | (ns nodels 3 | (:require [cljs.nodejs :as nodejs])) 4 | 5 | (def fs (nodejs/require "fs")) 6 | (def path (nodejs/require "path")) 7 | 8 | (defn file-seq [dir] 9 | (tree-seq 10 | (fn [f] (.isDirectory (.statSync fs f) ())) 11 | (fn [d] (map #(.join path d %) (.readdirSync fs d))) 12 | dir)) 13 | 14 | (defn -main [& paths] 15 | (dorun (map println (mapcat file-seq paths)))) 16 | 17 | (set! *main-cli-fn* -main) 18 | -------------------------------------------------------------------------------- /samples/repl/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | main.js 3 | -------------------------------------------------------------------------------- /samples/repl/README.md: -------------------------------------------------------------------------------- 1 | # ClojureScript REPL Examples 2 | 3 | The ClojureScript REPL has been updated to work with multiple 4 | JavaScript evaluation environments. This readme and the example code 5 | in this project show how to use the new REPL. There are now two 6 | implemented environments: Rhino and the browser. 7 | 8 | ## Using the new REPL 9 | 10 | There are currently four steps in starting a ClojureScript REPL. 11 | 12 | 1. require cljs.repl 13 | 2. require the namespace which implements the desired evaluation environment 14 | 3. create a new evaluation environment 15 | 4. start the REPL with the created environment 16 | 17 | ## Evaluating with Rhino 18 | 19 | ```clj 20 | (require '[cljs.repl :as repl]) 21 | (require '[cljs.repl.rhino :as rhino]) 22 | (def env (rhino/repl-env)) 23 | (repl/repl env) 24 | ``` 25 | 26 | ## Evaluating in the Browser 27 | 28 | A browser-connected REPL works in much the same way as a normal REPL: 29 | forms are read from the console, evaluated and return values are 30 | printed. A major and useful difference form normal REPL usage is that 31 | all side-effects occur in the browser. You can show alerts, manipulate 32 | the dom and interact with running applications. 33 | 34 | The main benefit of using the browser as an evaluation environment is 35 | that the REPL is no longer limited to non-browser code. You get all 36 | the benefits of a REPL with all of your code. 37 | 38 | The example below shows how to start a browser-connected REPL with an 39 | empty project. The same technique can be used to integrate a REPL into 40 | an existing project. In the future there may be an easier way to start 41 | a browser-connected REPL without a project. 42 | 43 | ### Building 44 | 45 | This sample project contains an HTML file and single ClojureScript 46 | file which establishes the connection to the REPL from the 47 | browser. These are currently the minimum requirements for starting a 48 | browser-connected REPL. 49 | 50 | To build the project, launch a Clojure REPL from this folder 51 | 52 | ```bash 53 | cd samples/repl 54 | ../../script/repl 55 | ``` 56 | 57 | and evaluate the following forms: 58 | 59 | ```clj 60 | (use 'cljs.closure) 61 | (def opts {:output-to "main.js" :output-dir "out"}) 62 | (build "src" opts) 63 | ``` 64 | 65 | ### Starting the REPL and connecting to the browser 66 | 67 | Start the REPL using the browser as the evaluator (do it in "samples/repl"): 68 | 69 | ```clj 70 | (require '[cljs.repl :as repl]) 71 | (require '[cljs.repl.browser :as browser]) 72 | (def env (browser/repl-env)) 73 | (repl/repl env) 74 | ``` 75 | 76 | Open http://localhost:9000/ in a browser. When this page is loaded it will connect 77 | to the REPL. Alternatively you can serve index.html from your own local webserver. 78 | 79 | ### Try it out 80 | 81 | ```clj 82 | ;; Evaluate some basic forms. 83 | (+ 1 1) 84 | {:a :b} 85 | "hello" 86 | (reduce + [1 2 3 4 5]) 87 | (js/alert "Hello World!") 88 | 89 | ;; Load a file, and use it. 90 | (load-file "clojure/string.cljs") 91 | (clojure.string/reverse "Hello") 92 | 93 | ;; Define functions and call them. 94 | (defn sum [coll] (reduce + coll)) 95 | (sum [2 2 2 2]) 96 | 97 | ;; Create dom elements. 98 | (ns dom.testing (:require [clojure.browser.dom :as dom])) 99 | (dom/append (dom/get-element "content") 100 | (dom/element "Hello World!")) 101 | ``` 102 | -------------------------------------------------------------------------------- /samples/repl/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | Browser-connected REPL 12 | 13 | 14 | 17 | 18 | 19 | 20 |
    21 | 22 | 23 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /samples/repl/src/repl/test.cljs: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns repl.test 10 | (:require [clojure.browser.repl :as repl] 11 | [clojure.reflect :as reflect])) 12 | 13 | (repl/connect "http://localhost:9000/repl") 14 | 15 | (comment 16 | 17 | ;; Note: If you would like for the compiler to be aware of 18 | ;; everything in a project then delete the 'out' directory before 19 | ;; calling build. This will force the compiler to compile the whole 20 | ;; project. 21 | 22 | ;; Compile this project to JavaScript 23 | (use 'cljs.closure) 24 | (def opts {:output-to "samples/repl/main.js" 25 | :output-dir "samples/repl/out"}) 26 | (build "samples/repl/src" opts) 27 | 28 | ;; Start REPL 29 | (do (require '[cljs.repl :as repl]) 30 | (require '[cljs.repl.browser :as browser]) 31 | (def env (browser/repl-env)) 32 | (repl/repl env)) 33 | 34 | ;; Open http://localhost:9000/ in a browser. When this page is loaded 35 | ;; it will connect to the REPL. Alternatively you can serve index.html 36 | ;; from your own local webserver. 37 | 38 | ;; Evaluate some basic forms 39 | (+ 1 1) 40 | (string-print "hello") 41 | (prn "foo") 42 | (prn {:a :b}) 43 | (println "hello") 44 | (doseq [next (range 20)] (println next)) 45 | {:a :b} 46 | "hello" 47 | (reduce + [1 2 3 4 5]) 48 | (time (reduce + (range 10000))) 49 | (js/alert "Hello World!") 50 | 51 | (load-file "clojure/string.cljs") 52 | (clojure.string/reverse "Hello") 53 | 54 | (defn sum [coll] (reduce + coll)) 55 | (sum [2 2 2 2]) 56 | 57 | ;; Create dom elements. 58 | (ns dom.testing (:require [clojure.browser.dom :as dom])) 59 | (dom/append (dom/get-element "content") 60 | (dom/element "Hello World!")) 61 | 62 | ;; Load something we haven't used yet 63 | (ns test.crypt 64 | (:require [goog.crypt :as c])) 65 | (c/stringToByteArray "ClojureScript") 66 | 67 | (load-namespace 'goog.date.Date) 68 | (goog.date.Date.) 69 | 70 | (ns test.color (:require [goog.color :as c])) 71 | (js->clj (c/parse "#000000")) 72 | 73 | ) 74 | -------------------------------------------------------------------------------- /samples/twitterbuzz/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | twitterbuzz.js 3 | -------------------------------------------------------------------------------- /samples/twitterbuzz/README.md: -------------------------------------------------------------------------------- 1 | # ClojureScript "TwitterBuzz" Demo 2 | 3 | ## One-time Setup 4 | 5 | See https://github.com/clojure/clojurescript/wiki/Quick-Start 6 | 7 | ## Run in Development Mode 8 | 9 | Compile the demo: 10 | 11 | cljsc src > twitterbuzz.js 12 | 13 | After running the above command, open index.html. 14 | 15 | ## Compile in Development Mode with the REPL (Faster) 16 | 17 | * Run `script/repl` 18 | * To run it from Emacs, `C-x d` and nav to the `clojurescript` directory 19 | * `M-x set-variable inferior-lisp-program` 20 | * Set to `"script/repl"` 21 | * `M-x run-lisp` 22 | 23 | * Once the REPL is running, evaluate: 24 | 25 | (use 'cljs.closure) 26 | (def opts {:output-to "samples/twitterbuzz/twitterbuzz.js" :output-dir "samples/twitterbuzz/out"}) 27 | 28 | (build "samples/twitterbuzz/src" opts) 29 | 30 | The reason we set the `:output-dir` is because the `index.html` script tag is specifically pointing to that directory. 31 | 32 | * See `cljs.closure` source for more compilation examples. 33 | 34 | ## Compile in Advanced Mode 35 | 36 | `cljsc` can be run with a Clojure map of compiler options. To compile using `cljsc` and Closure Compiler's "advanced" optimization setting: 37 | 38 | cljsc src '{:optimizations :advanced}' > twitterbuzz.js 39 | 40 | Because advanced mode results in only one `.js` file, `twitterbuzz.js`, only one ` 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /samples/twitterbuzz/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | TwitterBuzz: A ClojureScript Demo 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 |
    28 |
    29 |

    TwitterBuzz: A ClojureScript Demo

    30 |
    Learn more: 31 | ClojureScript | 32 | Documentation | 33 | Source Code 35 |
    36 |

    Clojure

    37 |
    38 |
    39 | 40 |
    41 |
    42 | 43 | 44 | Not Connected 45 |
    46 |
    47 | 48 |
    49 |
    50 | 51 |
    52 |
    53 | 54 |
    55 |

    Leaderboard

    56 |
    57 |
    58 |
    59 | 60 |
    61 |

    Timeline

    62 |
    63 |
    64 |
    65 | 66 |
    67 |
    68 | 69 |
    70 |
    71 | 72 | 75 | 76 | 77 | 78 | 79 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /samples/twitterbuzz/reset.css: -------------------------------------------------------------------------------- 1 | /* Eric Meyer's Reset Reloaded */ 2 | html, body, div, span, applet, object, iframe, 3 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 4 | a, abbr, acronym, address, big, cite, code, 5 | del, dfn, em, font, img, ins, kbd, q, s, samp, 6 | small, strike, strong, sub, sup, tt, var, 7 | dl, dt, dd, ol, ul, li, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td { 10 | margin: 0; 11 | padding: 0; 12 | border: 0; 13 | outline: 0; 14 | font-weight: inherit; 15 | font-style: inherit; 16 | font-size: 100%; 17 | font-family: inherit; 18 | vertical-align: baseline; 19 | } 20 | /* remember to define focus styles! */ 21 | :focus { 22 | outline: 0; 23 | } 24 | body { 25 | line-height: 1; 26 | color: black; 27 | background: white; 28 | } 29 | ol, ul { 30 | list-style: none; 31 | } 32 | /* tables still need 'cellspacing="0"' in the markup */ 33 | table { 34 | border-collapse: separate; 35 | border-spacing: 0; 36 | } 37 | caption, th, td { 38 | text-align: left; 39 | font-weight: normal; 40 | } 41 | blockquote:before, blockquote:after, 42 | q:before, q:after { 43 | content: ""; 44 | } 45 | blockquote, q { 46 | quotes: "" ""; 47 | } 48 | 49 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/anneal.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.anneal) 10 | 11 | (defn exp [x] 12 | (js/Math.exp x)) 13 | 14 | (defn abs [x] 15 | (js/Math.abs x)) 16 | 17 | (defn random [] 18 | (js/Math.random)) 19 | 20 | (defn standard-prob [e e1 temp] 21 | (if (< e1 e) 22 | 1 23 | (exp (/ (- e e1) temp)))) 24 | 25 | (defn linear-cooling [steps] 26 | (let [min (- 1 (/ steps (dec steps)))] 27 | (fn [t] 28 | (max min (- 1 (/ t steps)))))) 29 | 30 | (defn anneal 31 | "Given an energy scoring function, a temperature function 32 | (calculates temp given iteration t), a permutation function (creates 33 | a candidate next state given a current state and iteration t), and 34 | an acceptance probability function (of last next energy and temp), 35 | yields a lazy seq of (accepted?) states of the form 36 | {:state s :score :best best :best-score :t t}" 37 | 38 | [energy ;;(energy state) -> score 39 | temp ;;(temp t) -> 0-1.0 40 | permute ;;(permute state t) -> new-state 41 | prob ;;(prob e e1 temp) -> 0-1.0 42 | state] 43 | 44 | (let [init state 45 | init-score (energy state) 46 | step (fn step [{:keys [state score best best-score t]:as ret}] 47 | (loop [next (permute state) t (inc t)] 48 | (let [next-score (energy next)] 49 | (if (> (prob score next-score (temp t)) (random)) 50 | (let [ret {:state next :score next-score :t t 51 | :best (if (< next-score best-score) next best) 52 | :best-score (min next-score best-score)}] 53 | (lazy-seq (cons ret (step ret)))) 54 | (recur (permute state) (inc t))))))] 55 | (step {:state init :score init-score :best init :best-score init-score :t 0}))) 56 | 57 | 58 | (comment 59 | 60 | (take 10 (take-nth 100 61 | (anneal #(abs (- % 42)) 62 | (linear-cooling 1000) 63 | (fn [s _] (+ s (- (random) 0.5))) 64 | standard-prob 65 | 55))) 66 | ) 67 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/dom-helpers.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.dom-helpers 10 | (:require [clojure.string :as string] 11 | [goog.dom :as dom])) 12 | 13 | (defn get-element 14 | "Return the element with the passed id." 15 | [id] 16 | (dom/getElement (name id))) 17 | 18 | (defn append 19 | "Append all children to parent." 20 | [parent & children] 21 | (do (doseq [child children] 22 | (dom/appendChild parent child)) 23 | parent)) 24 | 25 | (defn set-text 26 | "Set the text content for the passed element returning the 27 | element. If a keyword is passed in the place of e, the element with 28 | that id will be used and returned." 29 | [e s] 30 | (let [e (if (keyword? e) (get-element e) e)] 31 | (doto e (dom/setTextContent s)))) 32 | 33 | (defn normalize-args [tag args] 34 | (let [parts (string/split (name tag) #"(\.|#)") 35 | [tag attrs] [(first parts) 36 | (apply hash-map (map #(cond (= % ".") :class 37 | (= % "#") :id 38 | :else %) 39 | (rest parts)))]] 40 | (if (map? (first args)) 41 | [tag (merge attrs (first args)) (rest args)] 42 | [tag attrs args]))) 43 | 44 | (defn element 45 | "Create a dom element using a keyword for the element name and a map 46 | for the attributes. Append all children to parent. If the first 47 | child is a string then the string will be set as the text content of 48 | the parent and all remaining children will be appended." 49 | [tag & args] 50 | (let [[tag attrs children] (normalize-args tag args) 51 | parent (dom/createDom (name tag) 52 | (reduce (fn [o [k v]] 53 | (aset o k v)) 54 | (js-obj) 55 | (map #(vector (name %1) %2) 56 | (keys attrs) 57 | (vals attrs)))) 58 | [parent children] (if (string? (first children)) 59 | [(set-text (element tag attrs) (first children)) 60 | (rest children)] 61 | [parent children])] 62 | (apply append parent children))) 63 | 64 | (defn remove-children 65 | "Remove all children from the element with the passed id." 66 | [id] 67 | (let [parent (dom/getElement (name id))] 68 | (do (dom/removeChildren parent)))) 69 | 70 | (defn html 71 | "Create a dom element from an html string." 72 | [s] 73 | (dom/htmlToDocumentFragment s)) 74 | 75 | (defn- element-arg? [x] 76 | (or (keyword? x) 77 | (map? x) 78 | (string? x))) 79 | 80 | (defn build 81 | "Build up a dom element from nested vectors." 82 | [x] 83 | (if (vector? x) 84 | (let [[parent children] (if (keyword? (first x)) 85 | [(apply element (take-while element-arg? x)) 86 | (drop-while element-arg? x)] 87 | [(first x) (rest x)]) 88 | children (map build children)] 89 | (apply append parent children)) 90 | x)) 91 | 92 | (defn insert-at 93 | "Insert a child element at a specific location." 94 | [parent child index] 95 | (dom/insertChildAt parent child index)) 96 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/layout.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.layout 10 | (:require [twitterbuzz.anneal :as ann] 11 | [twitterbuzz.radial :as rad] 12 | [goog.math :as math])) 13 | 14 | (defn random-loc [] 15 | {:x (ann/random) :y (ann/random)}) 16 | 17 | (defn sqr [x] 18 | (* x x)) 19 | 20 | (defn sqrt [x] 21 | (js/Math.sqrt x)) 22 | 23 | (defn dist [{x1 :x y1 :y} {x2 :x y2 :y}] 24 | (sqrt (+ (sqr (- x2 x1)) (sqr (- y2 y1))))) 25 | 26 | (defn init-state [mentions-data] 27 | (let [connected (reduce (fn [ret [k {:keys [mentions]}]] 28 | (if (pos? (count mentions)) 29 | (into (conj ret k) (keys mentions)) 30 | ret)) 31 | #{} mentions-data) 32 | mentions-data (select-keys mentions-data connected)] 33 | {:locs (zipmap connected (repeatedly #(random-loc))) 34 | :mentions mentions-data})) 35 | 36 | (defn roots [mentions-data] 37 | (let [parents (reduce (fn [ret [k {:keys [mentions]}]] 38 | (if (pos? (count mentions)) 39 | (conj ret k) 40 | ret)) 41 | #{} mentions-data)] 42 | (reduce disj parents (mapcat #(keys (:mentions %)) (vals mentions-data))))) 43 | 44 | (defn radial 45 | [mentions-data] 46 | (let [mentions #(rad/get-mentions mentions-data %) 47 | weights (rad/weights 48 | (into (set (roots mentions-data)) (mapcat mentions (keys mentions-data))) 49 | mentions)] 50 | {:mentions mentions-data 51 | :locs (-> (rad/layout (roots mentions-data) weights mentions) 52 | (rad/polar->cartesian 3))})) 53 | 54 | (defn score [{:keys [locs mentions]}] 55 | (let [metric (fn [d w] (sqr (- 1 (* d w)))) 56 | score-user (fn [[k {:keys [mentions]}]] 57 | (if (zero? (count mentions)) 58 | 0 59 | (let [loc (locs k)] 60 | (reduce (fn [score [ok w]] 61 | (+ score (metric (dist loc (locs ok)) w))) 62 | 0 63 | mentions))))] 64 | (reduce + (map score-user mentions)))) 65 | 66 | (defn permute-swap [{:keys [locs mentions]} t] 67 | ;;first cut - swap 68 | (let [xys (vec (vals locs)) 69 | swap1 (math/randomInt (count xys)) 70 | swap2 (math/randomInt (count xys)) 71 | temp (xys swap1) 72 | xys (assoc xys swap1 (xys swap2)) 73 | xys (assoc xys swap2 temp)] 74 | {:locs (zipmap (keys locs) xys) 75 | :mentions mentions})) 76 | 77 | (defn permute-move [{:keys [locs mentions]} t] 78 | (let [adj #(min 1.0 (max 0 (+ % (- (* (ann/random) 0.1) 0.05)))) 79 | move (fn [{:keys [x y] :as loc}] 80 | (if true ;;(> (ann/random) 0.8) 81 | {:x (adj x) 82 | :y (adj y)} 83 | loc)) 84 | xys (vec (vals locs))] 85 | {:locs (zipmap (keys locs) (map move (vals locs))) 86 | :mentions mentions})) 87 | 88 | (comment 89 | (def test-data {}) 90 | 91 | (def init (init-state test-data)) 92 | 93 | (map (fn [x] {:best-score (:best-score x) :t (:t x)}) 94 | (take 10 (take-nth 100 95 | (ann/anneal score 96 | (ann/linear-cooling 1000) 97 | permute-move 98 | ann/standard-prob 99 | init)))) 100 | ) 101 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/leaderboard.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.leaderboard 10 | (:require [twitterbuzz.core :as buzz] 11 | [twitterbuzz.dom-helpers :as dom])) 12 | 13 | (defn leaderboard-element 14 | "Create a leaderboard element from a user map." 15 | [user] 16 | (dom/build [:div.tweet 17 | [:img.profile-pic {:src (:image-url user)}] 18 | [:div.tweet-details 19 | [:div.user-name (:username user)] 20 | [:div.tweet-text (dom/html (buzz/markup (:last-tweet user)))] 21 | [:div (str (buzz/num-mentions user))]]])) 22 | 23 | (defn leaders 24 | "Given a map of users, return a sequence of users in order of the 25 | greatest to least number of mentions." 26 | [nodes] 27 | (reverse (sort-by #(buzz/num-mentions (second %)) nodes))) 28 | 29 | (defn update-leaderboard 30 | "Put the top 5 mentioned users in the leaderboard." 31 | [graph] 32 | (do (dom/remove-children :leaderboard-content) 33 | (doseq [next-node (take 5 (leaders (seq graph)))] 34 | (dom/append (dom/get-element :leaderboard-content) 35 | (leaderboard-element (second next-node)))))) 36 | 37 | ;; Register event listeners. 38 | 39 | (buzz/register :track-clicked #(dom/remove-children :leaderboard-content)) 40 | (buzz/register :graph-update update-leaderboard) 41 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/radial.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.radial 10 | (:require [clojure.set :as set] 11 | [goog.math :as math])) 12 | 13 | (defn get-mentions 14 | "Returns the set of mentions for k in mentions-data" 15 | [mentions-data k] 16 | (-> (get-in mentions-data [k :mentions]) 17 | keys 18 | set)) 19 | 20 | (defn get-descendants 21 | "Given child-fn (a map of parent to child), and k, return the 22 | set of all k's descendants. Set includes k." 23 | [child-fn k] 24 | (loop [kids #{k} 25 | check #{k}] 26 | (let [[c] (seq check)] 27 | (if c 28 | (recur (into kids (child-fn c)) 29 | (into (disj check c) (remove kids (child-fn c)))) 30 | kids)))) 31 | 32 | (defn weight 33 | "Weight of noce, given child-fn (mapping of node to set 34 | of kids)." 35 | [node child-fn] 36 | (if-let [kids (seq (child-fn node))] 37 | (reduce + (map #(weight % child-fn) kids)) 38 | 1)) 39 | 40 | (defn weights 41 | "Return a map of node to its weight, 42 | using child-fn to get the set of children for a node." 43 | [nodes child-fn] 44 | (reduce 45 | (fn [m n] (assoc m n (weight n child-fn))) 46 | {} 47 | nodes)) 48 | 49 | (defn layout 50 | "Returns a map of node => :radius, :slice, :angle. 51 | 52 | weight-fn: one arg fn of node returning weight 53 | child-fn: one arg fn of node returning set of nodes" 54 | ([nodes weight-fn child-fn] 55 | (layout nodes weight-fn child-fn 1 0 360 #{})) 56 | ([nodes weight-fn child-fn radius a1 a2 seen] 57 | (let [slice (- a2 a1) 58 | total-weight (reduce + (map #(or (weight-fn %) 59 | (throw (str "No weight for " %))) nodes)) 60 | seen (into seen nodes)] 61 | (loop [m {} 62 | c1 a1 63 | [node & more] (seq nodes)] 64 | (if node 65 | (let [s (* slice (/ (weight-fn node) total-weight)) 66 | c2 (+ c1 s)] 67 | (recur 68 | (merge 69 | m 70 | {node {:radius radius :slice s :angle (/ (+ c1 c2) 2)}} 71 | (when-let [children (seq (remove seen (child-fn node)))] 72 | (layout children weight-fn child-fn (inc radius) c1 c2 seen))) 73 | c2 74 | more)) 75 | m))))) 76 | 77 | (defn polar->cartesian 78 | "Convert polar coordinates (from layout) into 79 | cartesian coordinates on the unit square, assuming the 80 | square will display max-rings rings." 81 | [polar-map max-rings] 82 | (reduce 83 | (fn [m [k {:keys [radius angle]}]] 84 | (let [r (/ radius (+ 0.5 max-rings) 2)] 85 | (assoc m k {:x (+ 0.5 (math/angleDx angle r)) 86 | :y (+ 0.5 (math/angleDy angle r))}))) 87 | {} 88 | polar-map)) 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/showgraph.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.showgraph 10 | (:require [twitterbuzz.core :as buzz] 11 | [twitterbuzz.layout :as layout] 12 | [twitterbuzz.dom-helpers :as dom] 13 | [twitterbuzz.timeline :as timeline] 14 | [goog.events :as events] 15 | [goog.style :as style] 16 | [goog.math.Coordinate :as Coordinate] 17 | [goog.ui.HoverCard :as HoverCard] 18 | [goog.graphics.Font :as Font] 19 | [goog.graphics.Stroke :as Stroke] 20 | [goog.graphics.SolidFill :as SolidFill] 21 | [goog.graphics :as graphics])) 22 | 23 | ; Drawing configuration 24 | (def avatar-size 32) ; used for both x and y dimensions of avatars 25 | ; fail whale 26 | ;(def default-avatar "http://farm3.static.flickr.com/2562/4140195522_e207b97280_s.jpg") 27 | ; google+ silhouette 28 | (def default-avatar "http://ssl.gstatic.com/s2/profiles/images/silhouette48.png") 29 | (defn debug [_]) 30 | ;(defn debug [a] (str "t: " (:t a) " score: " (:best-score a))) 31 | 32 | ; BAD HACK: don't change globals like this -- find a better way: 33 | ;(set! anim/TIMEOUT 500) 34 | 35 | (def edge-stroke (graphics/Stroke. 1 "#009")) 36 | 37 | (def g 38 | (doto (graphics/createGraphics "100%" "100%") 39 | (.render (dom/get-element :network)))) 40 | 41 | (def font (graphics/Font. 12 "Arial")) 42 | (def fill (graphics/SolidFill. "#f00")) 43 | 44 | (defn unit-to-pixel [unit-arg canvas-size] 45 | (+ (* unit-arg (- canvas-size avatar-size)) (/ avatar-size 2))) 46 | 47 | (defn log [& args] 48 | (js/console.log (apply pr-str args))) 49 | 50 | (def avatar-hover 51 | (doto 52 | (goog.ui/HoverCard. (js-obj)) ; svg IMAGE tags don't work here 53 | (.setElement (dom/get-element :avatar-hover)))) 54 | 55 | (defn hide-tooltip [event] 56 | (.setVisible avatar-hover false)) 57 | 58 | (defn attach-tooltip [img canvas-offset px py tweet] 59 | (events/listen img events/EventType.MOUSEOUT hide-tooltip) 60 | (events/listen 61 | img events/EventType.MOUSEOVER 62 | (fn [event] 63 | (hide-tooltip event) 64 | (.setPosition avatar-hover 65 | (goog.ui/Tooltip.CursorTooltipPosition. 66 | (Coordinate/sum (goog.math/Coordinate. px py) 67 | canvas-offset))) 68 | (dom/remove-children :avatar-hover-body) 69 | (dom/append (dom/get-element :avatar-hover-body) 70 | (timeline/timeline-element tweet)) 71 | (.triggerForElement avatar-hover img)))) 72 | 73 | (defn draw-graph [{:keys [locs mentions]} text] 74 | (let [canvas-size (. g (getPixelSize)) 75 | canvas-offset (style/getPageOffset (dom/get-element :network))] 76 | (. g (clear)) 77 | 78 | ; Draw mention edges 79 | (doseq [[username {ux1 :x, uy1 :y}] locs 80 | :let [x1 (unit-to-pixel ux1 (.-width canvas-size)) 81 | y1 (unit-to-pixel uy1 (.-height canvas-size))] 82 | [mention-name mention-count] (:mentions (get mentions username))] 83 | (when-let [{ux2 :x, uy2 :y} (get locs mention-name)] 84 | (let [x2 (unit-to-pixel ux2 (.-width canvas-size)) 85 | y2 (unit-to-pixel uy2 (.-height canvas-size))] 86 | (.drawPath g 87 | (-> (. g (createPath)) (.moveTo x1 y1) (.lineTo x2 y2)) 88 | edge-stroke nil)))) 89 | 90 | ; Draw avatar nodes 91 | (doseq [[username {:keys [x y] :as foo}] locs] 92 | ;(log (pr-str foo)) 93 | (let [px (- (unit-to-pixel x (.-width canvas-size)) (/ avatar-size 2)) 94 | py (- (unit-to-pixel y (.-height canvas-size)) (/ avatar-size 2)) 95 | user (get mentions username) 96 | image-url (get user :image-url default-avatar) 97 | img (.drawImage g px py avatar-size avatar-size image-url)] 98 | (attach-tooltip img canvas-offset px py 99 | {:profile_image_url image-url 100 | :text (:last-tweet user) 101 | :from_user (:username user)}))) 102 | 103 | (let [text (if (empty? locs) 104 | "No locations to graph" 105 | text)] 106 | (when text 107 | (.drawTextOnLine g text 5 20 (.-width canvas-size) 20 108 | "left" font nil fill))))) 109 | 110 | (def graph-data (atom nil)) 111 | 112 | ;; Register event listeners. 113 | 114 | (buzz/register :graph-update 115 | (fn [data] 116 | (reset! graph-data data) 117 | (draw-graph (layout/radial data) nil))) 118 | 119 | (events/listen (dom/get-element :network) events/EventType.CLICK 120 | #(draw-graph (layout/radial @graph-data) nil)) 121 | (buzz/register :track-clicked #(. g (clear))) 122 | -------------------------------------------------------------------------------- /samples/twitterbuzz/src/twitterbuzz/timeline.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns twitterbuzz.timeline 10 | (:require [twitterbuzz.core :as buzz] 11 | [twitterbuzz.dom-helpers :as dom])) 12 | 13 | (defn timeline-element 14 | "Return a timeline dom element for the given tweet." 15 | [tweet] 16 | (dom/build [:div.tweet 17 | [:img.profile-pic {:src (:profile_image_url tweet)}] 18 | [:div.user-name (:from_user tweet)] 19 | [:div.tweet-text (dom/html (buzz/markup (:text tweet)))]])) 20 | 21 | (defn update-status 22 | "Set the current tweet count in the status box." 23 | [_] 24 | (buzz/set-tweet-status :okay (str (:tweet-count @buzz/state) " tweets"))) 25 | 26 | (defn update-timeline 27 | "Given a list of tweets in chronological order, add them to the top 28 | of the list view." 29 | [tweets] 30 | (doseq [tweet (reverse tweets)] 31 | (dom/insert-at (dom/get-element :timeline-content) 32 | (timeline-element tweet) 33 | 0))) 34 | 35 | ;; Register event listeners. 36 | 37 | (buzz/register :track-clicked #(dom/remove-children :timeline-content)) 38 | (buzz/register :new-tweets update-timeline) 39 | (buzz/register :new-tweets update-status) 40 | -------------------------------------------------------------------------------- /script/benchmark: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf out 4 | mkdir -p out 5 | 6 | #bin/cljsc benchmark > out/core-benchmark.js 7 | bin/cljsc benchmark "{:optimizations :advanced}" >out/core-advanced-benchmark.js 8 | 9 | if [ "$V8_HOME" = "" ]; then 10 | echo "V8_HOME not set, skipping V8 benchmarks" 11 | else 12 | echo "Benchmarking with V8" 13 | "${V8_HOME}/d8" out/core-advanced-benchmark.js 14 | # TODO: figure out path problem when not in advanced mode 15 | # "${V8_HOME}/d8" out/core-benchmark.js 16 | fi 17 | 18 | if [ "$SPIDERMONKEY_HOME" = "" ]; then 19 | echo "SPIDERMONKEY_HOME not set, skipping SpiderMonkey benchmarks" 20 | else 21 | echo "Benchmarking with SpiderMonkey" 22 | "${SPIDERMONKEY_HOME}/js" -m -n -a -f out/core-advanced-benchmark.js 23 | fi 24 | 25 | if [ "$JSC_HOME" = "" ]; then 26 | echo "JSC_HOME not set, skipping JavaScriptCore benchmarks" 27 | else 28 | echo "Benchmarking with JavaScriptCore" 29 | "${JSC_HOME}/jsc" -f out/core-advanced-benchmark.js 30 | fi 31 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | mkdir -p lib 6 | 7 | echo "Fetching Clojure..." 8 | curl -O -s http://repo1.maven.org/maven2/org/clojure/clojure/1.5.1/clojure-1.5.1.zip 9 | unzip -qu clojure-1.5.1.zip 10 | echo "Copying clojure-1.5.1/clojure-1.5.1.jar to lib/clojure.jar..." 11 | cp clojure-1.5.1/clojure-1.5.1.jar lib/clojure.jar 12 | echo "Cleaning up Clojure directory..." 13 | rm -rf clojure-1.5.1/ 14 | echo "Cleaning up Clojure archive..." 15 | rm clojure-1.5.1.zip 16 | 17 | echo "Fetching Google Closure library..." 18 | mkdir -p closure/library 19 | cd closure/library 20 | if [ "$1" = "--closure-library-head" ] ; then 21 | echo "Building against HEAD of Google Closure library..." 22 | 23 | # Check if svn present 24 | type svn >/dev/null 2>&1 || { echo >&2 "Need svn command to checkout HEAD of Google Closure library. Aborting."; exit 1; } 25 | 26 | # Existing checkout? 27 | if svn info --non-interactive >/dev/null 2>&1; then 28 | echo "Updating Google Closure library from HEAD..." 29 | svn update -q --non-interactive 30 | else 31 | echo "Checking out HEAD of Google Closure library..." 32 | rm -rf * 33 | svn checkout -q --non-interactive http://closure-library.googlecode.com/svn/trunk/ ./ 34 | fi 35 | else 36 | echo "Fetching Google Closure library..." 37 | f=closure-library-20130212-95c19e7f0f5f.zip 38 | curl -O -s "http://closure-library.googlecode.com/files/$f" 39 | unzip -qu "$f" 40 | echo "Cleaning up Google Closure library archive..." 41 | rm "$f" 42 | fi 43 | cd .. 44 | 45 | echo "Fetching Google Closure compiler..." 46 | mkdir -p compiler 47 | cd compiler 48 | curl -O -s http://dl.google.com/closure-compiler/compiler-latest.zip 49 | unzip -qu compiler-latest.zip 50 | echo "Cleaning up Google Closure compiler archive..." 51 | rm compiler-latest.zip 52 | cd ../.. 53 | echo "Building lib/goog.jar..." 54 | echo "jar cf ./lib/goog.jar -C closure/library/closure/ goog" 55 | jar cf ./lib/goog.jar -C closure/library/closure/ goog 56 | 57 | echo "Fetching Rhino..." 58 | curl -O -s http://ftp.mozilla.org/pub/mozilla.org/js/rhino1_7R3.zip 59 | unzip -qu rhino1_7R3.zip 60 | echo "Copying rhino1_7R3/js.jar to lib/js.jar..." 61 | cp rhino1_7R3/js.jar lib/js.jar 62 | echo "Cleaning up Rhino directory..." 63 | rm -rf rhino1_7R3/ 64 | echo "Cleaning up Rhino archive..." 65 | rm rhino1_7R3.zip 66 | 67 | echo "Copying closure/compiler/compiler.jar to lib/compiler.jar" 68 | cp closure/compiler/compiler.jar lib 69 | 70 | echo "[Bootstrap Completed]" 71 | -------------------------------------------------------------------------------- /script/browser-repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$CLOJURESCRIPT_HOME" = "" ]; then 4 | CLOJURESCRIPT_HOME="`dirname $0`/.." 5 | fi 6 | 7 | CLJSC_CP='' 8 | for next in lib/*: src/clj: src/cljs: test/cljs; do 9 | CLJSC_CP=$CLJSC_CP$CLOJURESCRIPT_HOME'/'$next 10 | done 11 | 12 | java -server -cp $CLJSC_CP clojure.main -e " 13 | (require '[cljs.repl :as r]) 14 | (require '[cljs.repl.browser :as b]) 15 | (r/repl (b/repl-env)) 16 | " 17 | -------------------------------------------------------------------------------- /script/build: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script must be run within the ClojureScript top-level project 4 | # directory. 5 | 6 | set -ex 7 | 8 | cd `dirname $0`/.. 9 | 10 | DATE=`date '+%Y%m%d%H%M%S'` 11 | WORKING="clojurescript_release_$DATE" 12 | mkdir "$WORKING" 13 | 14 | POM_TEMPLATE="pom.template.xml" 15 | 16 | # The command `git describe --match v0.0` will return a string like 17 | # 18 | # v0.0-856-g329708b 19 | # 20 | # where 856 is the number of commits since the v0.0 tag. It will always 21 | # find the v0.0 tag and will always return the total number of commits (even 22 | # if the tag is v0.0.1). 23 | REVISION=`git --no-replace-objects describe --match v0.0` 24 | 25 | # Extract the version number from the string. Do this in two steps so 26 | # it is a little easier to understand. 27 | REVISION=${REVISION:5} # drop the first 5 characters 28 | REVISION=${REVISION:0:${#REVISION}-9} # drop the last 9 characters 29 | 30 | TAG=r$REVISION 31 | 32 | POM_FILE="$WORKING/clojurescript-0.0-$REVISION.pom" 33 | JAR_FILE="$WORKING/clojurescript-0.0-$REVISION.jar" 34 | 35 | 36 | # `jar cf` errors on duplicate entries, 37 | # so we have to assemble the directory manually 38 | mkdir "$WORKING/jar_contents" 39 | 40 | cp -R epl-v10.html src/clj/cljs src/cljs/cljs src/cljs/clojure \ 41 | "$WORKING/jar_contents" 42 | 43 | jar cf "$JAR_FILE" -C "$WORKING/jar_contents" . 44 | 45 | sed -e s/CLOJURESCRIPT_VERSION/0.0-$REVISION/ < "$POM_TEMPLATE" > "$POM_FILE" 46 | 47 | mvn install:install-file -Dfile="$JAR_FILE" -DpomFile="$POM_FILE" 48 | 49 | # For Hudson server 50 | if [ "$HUDSON" = "true" ]; then 51 | echo "Creating tag $TAG" 52 | git tag -f "$TAG" 53 | git push origin "$TAG" 54 | 55 | mvn gpg:sign-and-deploy-file -Durl=https://oss.sonatype.org/service/local/staging/deploy/maven2/ -DrepositoryId=sonatype-nexus-staging -DpomFile="$POM_FILE" -Dfile="$JAR_FILE" 56 | mvn nexus:staging-close nexus:staging-release -DtargetRepositoryId=releases -Dnexus.promote.autoSelectOverride=true 57 | else 58 | echo "Skipping Maven deployment and Git push because we are not on Hudson." 59 | fi 60 | -------------------------------------------------------------------------------- /script/clean: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf closure 4 | rm -rf compilation 5 | rm -f lib/goog.jar -------------------------------------------------------------------------------- /script/closure-library-release/google-closure-library-third-party.pom.template: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.clojure 4 | google-closure-library-third-party 5 | RELEASE_VERSION 6 | jar 7 | Google Closure Library Third-Party Extensions 8 | 9 | http://code.google.com/p/closure-library/ 10 | 11 | 12 | The Google Closure Library is a collection of JavaScript code 13 | designed for use with the Google Closure JavaScript Compiler. 14 | 15 | This non-official distribution was prepared by the ClojureScript 16 | team at http://clojure.org/ 17 | 18 | This package contains extensions to the Google Closure Library 19 | using third-party components, which may be distributed under 20 | licenses other than the Apache license. Licenses for individual 21 | library components may be found in source-code comments. 22 | 23 | 24 | 25 | 26 | The Apache Software License, Version 2.0 27 | http://www.apache.org/licenses/LICENSE-2.0.html 28 | repo 29 | 30 | 31 | 32 | 33 | Google 34 | http://www.google.com 35 | 36 | 37 | 38 | Google, Inc. 39 | Mohamed Mansourhello@mohamedmansour.com 40 | Bjorn Tiplingbjorn.tipling@gmail.com 41 | SameGoal LLChelp@samegoal.com 42 | Guido Tapiaguido.tapia@gmail.com 43 | Andrew Mattieamattie@gmail.com 44 | Ilia Mirkinibmirkin@gmail.com 45 | Ivan Kozikivan.kozik@gmail.com 46 | Rich Doughertyrich@rd.gen.nz 47 | 48 | 49 | 50 | scm:svn:http://closure-library.googlecode.com/svn/trunk 51 | scm:svn:http://closure-library.googlecode.com/svn/trunk 52 | http://code.google.com/p/closure-library/source/browse/#svn/trunk 53 | 54 | 55 | 56 | code.google.com 57 | http://code.google.com/p/closure-library/issues 58 | 59 | -------------------------------------------------------------------------------- /script/closure-library-release/google-closure-library.pom.template: -------------------------------------------------------------------------------- 1 | 2 | 4.0.0 3 | org.clojure 4 | google-closure-library 5 | RELEASE_VERSION 6 | jar 7 | Google Closure Library 8 | 9 | http://code.google.com/p/closure-library/ 10 | 11 | 12 | The Google Closure Library is a collection of JavaScript code 13 | designed for use with the Google Closure JavaScript Compiler. 14 | 15 | This non-official distribution was prepared by the ClojureScript 16 | team at http://clojure.org/ 17 | 18 | 19 | 20 | 21 | The Apache Software License, Version 2.0 22 | http://www.apache.org/licenses/LICENSE-2.0.html 23 | repo 24 | 25 | 26 | 27 | 28 | Google 29 | http://www.google.com 30 | 31 | 32 | 33 | Google, Inc. 34 | Mohamed Mansourhello@mohamedmansour.com 35 | Bjorn Tiplingbjorn.tipling@gmail.com 36 | SameGoal LLChelp@samegoal.com 37 | Guido Tapiaguido.tapia@gmail.com 38 | Andrew Mattieamattie@gmail.com 39 | Ilia Mirkinibmirkin@gmail.com 40 | Ivan Kozikivan.kozik@gmail.com 41 | Rich Doughertyrich@rd.gen.nz 42 | 43 | 44 | 45 | scm:svn:http://closure-library.googlecode.com/svn/trunk 46 | scm:svn:http://closure-library.googlecode.com/svn/trunk 47 | http://code.google.com/p/closure-library/source/browse/#svn/trunk 48 | 49 | 50 | 51 | code.google.com 52 | http://code.google.com/p/closure-library/issues 53 | 54 | -------------------------------------------------------------------------------- /script/closure-library-release/make-closure-library-jars.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | ## Set the version numbers to download and release: 6 | 7 | ZIP_VERSION="20111110-r1376" 8 | RELEASE_VERSION="0.0-1376-2" 9 | 10 | ## These only need to change if the URL or file names change: 11 | 12 | ZIP_BASE="closure-library-${ZIP_VERSION}" 13 | ZIP_FILE="${ZIP_BASE}.zip" 14 | ZIP_URL="http://closure-library.googlecode.com/files/${ZIP_FILE}" 15 | 16 | RELEASE_BASE="google-closure-library-${RELEASE_VERSION}" 17 | JAR_FILE="$RELEASE_BASE.jar" 18 | POM_FILE="$RELEASE_BASE.pom" 19 | 20 | THIRD_PARTY_RELEASE_BASE="google-closure-library-third-party-${RELEASE_VERSION}" 21 | THIRD_PARTY_JAR_FILE="$THIRD_PARTY_RELEASE_BASE.jar" 22 | THIRD_PARTY_POM_FILE="$THIRD_PARTY_RELEASE_BASE.pom" 23 | 24 | POM_TEMPLATE_FILE="google-closure-library.pom.template" 25 | THIRD_PARTY_POM_TEMPLATE_FILE="google-closure-library-third-party.pom.template" 26 | 27 | ## Main script begins: 28 | 29 | cd `dirname $0` 30 | 31 | DATE=`date "+%Y%m%d%H%M%S"` 32 | WORKING="closure-release-${DATE}" 33 | 34 | rm -rf "$WORKING" 35 | mkdir "$WORKING" 36 | 37 | if [ ! -e "$ZIP_FILE" ]; then 38 | curl "$ZIP_URL" -o "$ZIP_FILE" 39 | fi 40 | 41 | if [ ! -d "$WORKING/$ZIP_BASE" ]; then 42 | ( cd "$WORKING" && unzip "../$ZIP_FILE" ) 43 | fi 44 | 45 | cd "$WORKING" 46 | 47 | ## Modify deps.js for third-party JAR; see CLJS-276: 48 | 49 | perl -p -i -e 's/..\/..\/third_party\/closure\/goog\///go' \ 50 | closure/goog/deps.js 51 | 52 | rm -f ./third_party/closure/goog/base.js \ 53 | ./third_party/closure/goog/deps.js 54 | 55 | ## Build the JARs: 56 | 57 | jar cf "$JAR_FILE" \ 58 | AUTHORS \ 59 | LICENSE \ 60 | README \ 61 | -C closure goog \ 62 | -C closure css 63 | 64 | jar cf "$THIRD_PARTY_JAR_FILE" \ 65 | AUTHORS \ 66 | LICENSE \ 67 | README \ 68 | -C third_party/closure goog 69 | 70 | ## Generate the POM files: 71 | 72 | perl -p -e "s/RELEASE_VERSION/$RELEASE_VERSION/go" \ 73 | "../$POM_TEMPLATE_FILE" \ 74 | > "$POM_FILE" 75 | 76 | perl -p -e "s/RELEASE_VERSION/$RELEASE_VERSION/go" \ 77 | "../$THIRD_PARTY_POM_TEMPLATE_FILE" \ 78 | > "$THIRD_PARTY_POM_FILE" 79 | 80 | ## Uncomment these lines for an official release: 81 | 82 | # for FILE in "$JAR_FILE" "$THIRD_PARTY_JAR_FILE" "$POM_FILE" "$THIRD_PARTY_POM_FILE" 83 | # do 84 | # gpg --verbose --armor --detach-sign \ 85 | # --default-key "Clojure/core (build.clojure.org Release Key version 2) " \ 86 | # "$FILE" 87 | # done 88 | -------------------------------------------------------------------------------- /script/compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -f core.js 4 | 5 | java -server -Xmx2G -Xms2G -Xmn256m -cp 'lib/*:src/clj:src/cljs' clojure.main - < coresimple.js 25 | 26 | java -jar closure/compiler/compiler.jar \ 27 | --compilation_level=ADVANCED_OPTIMIZATIONS \ 28 | --warning_level=VERBOSE \ 29 | --formatting=PRETTY_PRINT \ 30 | --jscomp_off=missingProperties \ 31 | --js closure/library/closure/goog/base.js \ 32 | --js closure/library/closure/goog/string/string.js \ 33 | --js closure/library/closure/goog/useragent/jscript.js \ 34 | --js closure/library/closure/goog/string/stringbuffer.js \ 35 | --js closure/library/closure/goog/object/object.js \ 36 | --js closure/library/closure/goog/debug/error.js \ 37 | --js closure/library/closure/goog/asserts/asserts.js \ 38 | --js closure/library/closure/goog/array/array.js \ 39 | --js core.js \ 40 | > coreadvanced.js 41 | 42 | -------------------------------------------------------------------------------- /script/repl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$CLOJURESCRIPT_HOME" = "" ]; then 4 | CLOJURESCRIPT_HOME="`dirname $0`/.." 5 | fi 6 | 7 | CLJSC_CP='' 8 | for next in lib/*: src/clj: src/cljs: test/cljs; do 9 | CLJSC_CP="${CLJSC_CP}${CLOJURESCRIPT_HOME}/${next}" 10 | done 11 | 12 | java -server -cp "$CLJSC_CP" clojure.main 13 | 14 | -------------------------------------------------------------------------------- /script/repl.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setLocal EnableDelayedExpansion 3 | 4 | if "%CLOJURESCRIPT_HOME%" == "" set CLOJURESCRIPT_HOME=%~dp0..\ 5 | 6 | set CLASSPATH=%CLOJURESCRIPT_HOME%src\clj;%CLOJURESCRIPT_HOME%src\cljs" 7 | for /R "%CLOJURESCRIPT_HOME%\lib" %%a in (*.jar) do ( 8 | set CLASSPATH=!CLASSPATH!;%%a 9 | ) 10 | set CLASSPATH=!CLASSPATH!" 11 | 12 | java -server -cp "%CLASSPATH%" clojure.main 13 | 14 | -------------------------------------------------------------------------------- /script/repljs: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ "$CLOJURESCRIPT_HOME" = "" ]; then 4 | CLOJURESCRIPT_HOME="`dirname $0`/.." 5 | fi 6 | 7 | CLJSC_CP='' 8 | for next in lib/*: src/clj: src/cljs: test/cljs; do 9 | CLJSC_CP="${CLJSC_CP}${CLOJURESCRIPT_HOME}/${next}" 10 | done 11 | 12 | java -server -cp "$CLJSC_CP" clojure.main -e \ 13 | "(require '[cljs.repl :as repl]) 14 | (require '[cljs.repl.rhino :as rhino]) 15 | (repl/repl (rhino/repl-env) :warn-on-undeclared true)" 16 | -------------------------------------------------------------------------------- /script/repljs.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | setLocal EnableDelayedExpansion 3 | 4 | if "%CLOJURESCRIPT_HOME%" == "" set CLOJURESCRIPT_HOME=%~dp0..\ 5 | 6 | set CLASSPATH=%CLOJURESCRIPT_HOME%src\clj;%CLOJURESCRIPT_HOME%src\cljs" 7 | for /R "%CLOJURESCRIPT_HOME%\lib" %%a in (*.jar) do ( 8 | set CLASSPATH=!CLASSPATH!;%%a 9 | ) 10 | set CLASSPATH=!CLASSPATH!" 11 | 12 | set REPL_CLJ="(require '[cljs.repl :as repl])(require '[cljs.repl.rhino :as rhino])(repl/repl (rhino/repl-env))" 13 | 14 | java -server -cp "%CLASSPATH%" clojure.main -e %REPL_CLJ% 15 | -------------------------------------------------------------------------------- /script/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -rf out 4 | mkdir -p out 5 | 6 | possible=3 7 | ran=0 8 | 9 | #bin/cljsc test >out/core-test.js 10 | bin/cljsc test "{:optimizations :advanced}" >out/core-advanced-test.js 11 | 12 | if [ "$V8_HOME" = "" ]; then 13 | echo "V8_HOME not set, skipping V8 tests" 14 | else 15 | echo "Testing with V8" 16 | "${V8_HOME}/d8" out/core-advanced-test.js 17 | # TODO: figure out path problem when not in advanced mode 18 | # "${V8_HOME}/d8" out/core-test.js 19 | ran=$[ran+1] 20 | fi 21 | 22 | if [ "$SPIDERMONKEY_HOME" = "" ]; then 23 | echo "SPIDERMONKEY_HOME not set, skipping SpiderMonkey tests" 24 | else 25 | echo "Testing with SpiderMonkey" 26 | ${SPIDERMONKEY_HOME}/js -m -n -a -f out/core-advanced-test.js 27 | ran=$[ran+1] 28 | fi 29 | 30 | if [ "$JSC_HOME" = "" ]; then 31 | echo "JSC_HOME not set, skipping JavaScriptCore tests" 32 | else 33 | echo "Testing with JavaScriptCore" 34 | "${JSC_HOME}/jsc" -f out/core-advanced-test.js 35 | ran=$[ran+1] 36 | fi 37 | 38 | echo "Tested with $ran out of $possible possible js targets" 39 | -------------------------------------------------------------------------------- /script/test-compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Generating sample javascript" 4 | mkdir compilation 5 | 6 | cat >compilation/test.js < {:foo 1}" 14 | [m key-set] 15 | {:pre [(map? m) 16 | (set? key-set)]} 17 | (reduce (fn [coll key] 18 | (if (contains? key-set key) 19 | coll 20 | (dissoc coll key))) 21 | m (keys m))) 22 | 23 | (defn- get-meta [sym] 24 | (let [ns (symbol (namespace sym)) 25 | n (symbol (name sym))] 26 | (if-let [sym-meta (get (:defs (get @analyzer/namespaces ns)) n)] 27 | (-> (dissoc-unless sym-meta 28 | #{:name :method-params :doc :line :file}) 29 | (update-in [:name] str) 30 | (update-in [:method-params] #(str (vec %))))))) 31 | 32 | (defn macroexpand [form] 33 | "Fully expands a cljs macro form." 34 | (let [mform (analyzer/macroexpand-1 {} form)] 35 | (if (identical? form mform) 36 | mform 37 | (macroexpand mform)))) 38 | 39 | (defn- url-decode [encoded & [encoding]] 40 | (java.net.URLDecoder/decode encoded (or encoding "UTF-8"))) 41 | 42 | (def read-url-string (comp read-string url-decode)) 43 | 44 | (defn parse-param 45 | "Parses the query parameter of a path of the form \"/reflect?var=foo\" 46 | into the vector [\"var\" \"foo\"]." 47 | [path] 48 | (-> (str/split path #"\?") 49 | (last) 50 | (str/split #"="))) 51 | 52 | (defn- compile-and-return 53 | "Compiles a form to javascript and returns it on conn." 54 | [conn form] 55 | (let [ast (analyzer/analyze {:ns {:name 'cljs.user}} form) 56 | js (try (compiler/emit-str ast) 57 | (catch Exception e (println e)))] 58 | (server/send-and-close conn 200 js "text/javascript"))) 59 | 60 | (defmulti handle-reflect-query (fn [[param _] & _] param)) 61 | 62 | (defmethod handle-reflect-query "var" 63 | [[_ sym] req conn opts] 64 | (let [sym (read-url-string sym)] 65 | (compile-and-return conn (get-meta sym)))) 66 | 67 | (defmethod handle-reflect-query "macroform" 68 | [[_ mform] req conn opts] 69 | (let [mform (-> mform read-url-string macroexpand)] 70 | (server/send-and-close conn 200 (with-out-str (pprint/pprint mform))))) 71 | 72 | (server/dispatch-on :get 73 | (fn [{:keys [path]} _ _] (.startsWith path "/reflect")) 74 | (fn [{:keys [path] :as req} conn opts] 75 | (handle-reflect-query (parse-param path) req conn opts))) 76 | -------------------------------------------------------------------------------- /src/clj/cljs/repl/rhino.clj: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns cljs.repl.rhino 10 | (:refer-clojure :exclude [loaded-libs]) 11 | (:require [clojure.string :as string] 12 | [clojure.java.io :as io] 13 | [cljs.compiler :as comp] 14 | [cljs.analyzer :as ana] 15 | [cljs.repl :as repl]) 16 | (:import cljs.repl.IJavaScriptEnv 17 | [org.mozilla.javascript Context ScriptableObject])) 18 | 19 | (def current-repl-env (atom nil)) 20 | (def loaded-libs (atom #{})) 21 | 22 | ;;todo - move to core.cljs, using js 23 | (def ^String bootjs (str "goog.require = function(rule){" 24 | "Packages.clojure.lang.RT[\"var\"](\"cljs.repl.rhino\",\"goog-require\")" 25 | ".invoke(rule);}")) 26 | 27 | (defprotocol IEval 28 | (-eval [this env filename line])) 29 | 30 | (extend-protocol IEval 31 | 32 | java.lang.String 33 | (-eval [this {:keys [cx scope]} filename line] 34 | (.evaluateString cx scope this filename line nil)) 35 | 36 | java.io.Reader 37 | (-eval [this {:keys [cx scope]} filename line] 38 | (.evaluateReader cx scope this filename line nil)) 39 | ) 40 | 41 | (defmulti stacktrace class) 42 | 43 | (defmethod stacktrace :default [e] 44 | (apply str (interpose "\n" (map #(str " " (.toString %)) (.getStackTrace e))))) 45 | 46 | (defmethod stacktrace org.mozilla.javascript.RhinoException [e] 47 | (.getScriptStackTrace e)) 48 | 49 | (defmulti eval-result class) 50 | 51 | (defmethod eval-result :default [r] 52 | (.toString r)) 53 | 54 | (defmethod eval-result nil [_] "") 55 | 56 | (defmethod eval-result org.mozilla.javascript.Undefined [_] "") 57 | 58 | (defn rhino-eval 59 | [repl-env filename line js] 60 | (try 61 | (let [linenum (or line Integer/MIN_VALUE)] 62 | {:status :success 63 | :value (eval-result (-eval js repl-env filename linenum))}) 64 | (catch Throwable ex 65 | {:status :exception 66 | :value (.toString ex) 67 | :stacktrace (stacktrace ex)}))) 68 | 69 | (defn goog-require [rule] 70 | (when-not (contains? @loaded-libs rule) 71 | (let [repl-env @current-repl-env 72 | path (string/replace (comp/munge rule) \. java.io.File/separatorChar) 73 | cljs-path (str path ".cljs") 74 | js-path (str "goog/" 75 | (-eval (str "goog.dependencies_.nameToPath['" rule "']") 76 | repl-env 77 | "" 78 | 1))] 79 | (if-let [res (io/resource cljs-path)] 80 | (binding [ana/*cljs-ns* 'cljs.user] 81 | (repl/load-stream repl-env res)) 82 | (if-let [res (io/resource js-path)] 83 | (-eval (io/reader res) repl-env js-path 1) 84 | (throw (Exception. (str "Cannot find " cljs-path " or " js-path " in classpath"))))) 85 | (swap! loaded-libs conj rule)))) 86 | 87 | (defn load-javascript [repl-env ns url] 88 | (let [missing (remove #(contains? @loaded-libs %) ns)] 89 | (when (seq missing) 90 | (do (try 91 | (-eval (io/reader url) repl-env (.toString url) 1) 92 | ;; TODO: don't show errors for goog/base.js line number 105 93 | (catch Throwable ex (println (.getMessage ex)))) 94 | (swap! loaded-libs (partial apply conj) missing))))) 95 | 96 | (defn rhino-setup [repl-env] 97 | (let [env (ana/empty-env) 98 | scope (:scope repl-env)] 99 | (repl/load-file repl-env "cljs/core.cljs") 100 | (swap! loaded-libs conj "cljs.core") 101 | (repl/evaluate-form repl-env 102 | env 103 | "" 104 | '(ns cljs.user)) 105 | (ScriptableObject/putProperty scope 106 | "out" 107 | (Context/javaToJS System/out scope)) 108 | (repl/evaluate-form repl-env 109 | env 110 | "" 111 | '(set! *print-fn* (fn [x] (.print js/out x)))))) 112 | 113 | (defrecord RhinoEnv [] 114 | repl/IJavaScriptEnv 115 | (-setup [this] 116 | (rhino-setup this)) 117 | (-evaluate [this filename line js] 118 | (rhino-eval this filename line js)) 119 | (-load [this ns url] 120 | (load-javascript this ns url)) 121 | (-tear-down [_] (Context/exit))) 122 | 123 | (defn repl-env 124 | "Returns a fresh JS environment, suitable for passing to repl. 125 | Hang on to return for use across repl calls." 126 | [] 127 | (let [cx (Context/enter) 128 | scope (.initStandardObjects cx) 129 | base (io/resource "goog/base.js") 130 | deps (io/resource "goog/deps.js") 131 | new-repl-env (merge (RhinoEnv.) {:cx cx :scope scope})] 132 | (assert base "Can't find goog/base.js in classpath") 133 | (assert deps "Can't find goog/deps.js in classpath") 134 | (swap! current-repl-env (fn [old] new-repl-env)) 135 | (with-open [r (io/reader base)] 136 | (-eval r new-repl-env "goog/base.js" 1)) 137 | (-eval bootjs new-repl-env "bootjs" 1) 138 | ;; Load deps.js line-by-line to avoid 64K method limit 139 | (doseq [^String line (line-seq (io/reader deps))] 140 | (-eval line new-repl-env "goog/deps.js" 1)) 141 | new-repl-env)) 142 | 143 | (comment 144 | 145 | (require '[cljs.repl :as repl]) 146 | (require '[cljs.repl.rhino :as rhino]) 147 | (def env (rhino/repl-env)) 148 | (repl/repl env) 149 | (+ 1 1) 150 | "hello" 151 | {:a "hello"} 152 | (:a {:a "hello"}) 153 | (:a {:a :b}) 154 | (reduce + [1 2 3 4 5]) 155 | (time (reduce + [1 2 3 4 5])) 156 | (even? :a) 157 | (throw (js/Error. "There was an error")) 158 | (load-file "clojure/string.cljs") 159 | (clojure.string/triml " hello") 160 | (clojure.string/reverse " hello") 161 | 162 | (load-namespace 'clojure.set) 163 | 164 | (ns test.crypt 165 | (:require [goog.crypt :as c])) 166 | (c/stringToByteArray "Hello") 167 | 168 | (load-namespace 'goog.date.Date) 169 | (goog.date.Date.) 170 | 171 | ) 172 | -------------------------------------------------------------------------------- /src/clj/cljs/tagged_literals.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.tagged-literals 2 | (:require [clojure.instant :as inst])) 3 | 4 | (defn read-queue 5 | [form] 6 | (assert (vector? form) "Queue literal expects a vector for its elements.") 7 | (list 'cljs.core/into 'cljs.core.PersistentQueue/EMPTY form)) 8 | 9 | (defn read-uuid 10 | [form] 11 | (assert (string? form) "UUID literal expects a string as its representation.") 12 | (try 13 | (let [uuid (java.util.UUID/fromString form)] 14 | (list (symbol "UUID.") form)) 15 | (catch Throwable e 16 | (throw (RuntimeException. (.getMessage e)))))) 17 | 18 | (defn read-inst 19 | [form] 20 | (assert (string? form) "Instance literal expects a string for its timestamp.") 21 | (try 22 | (let [^java.util.Date d (inst/read-instant-date form)] 23 | (list (symbol "js/Date.") (.getTime d))) 24 | (catch Throwable e 25 | (throw (RuntimeException. (.getMessage e)))))) 26 | 27 | (def ^:dynamic *cljs-data-readers* 28 | {'queue read-queue 29 | 'uuid read-uuid 30 | 'inst read-inst}) 31 | -------------------------------------------------------------------------------- /src/cljs/cljs/analyzer_macros.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.analyzer-macros) 2 | 3 | (defmacro disallowing-recur [& body] 4 | `(binding [cljs.analyzer/*recur-frames* (cons nil cljs.analyzer/*recur-frames*)] ~@body)) 5 | -------------------------------------------------------------------------------- /src/cljs/cljs/analyzer_macros.cljs: -------------------------------------------------------------------------------- 1 | analyzer_macros.clj -------------------------------------------------------------------------------- /src/cljs/cljs/compiler_macros.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.compiler-macros) 2 | 3 | (defmacro emit-wrap [env & body] 4 | `(let [env# ~env] 5 | (when (= :return (:context env#)) (cljs.compiler/emits "return ")) 6 | ~@body 7 | (when-not (= :expr (:context env#)) (cljs.compiler/emitln ";")))) 8 | 9 | (defmacro with-core-cljs 10 | "Ensure that core.cljs has been loaded." 11 | [& body] 12 | `(do (when-not (:defs (get @cljs.analyzer/namespaces 'cljs.core)) 13 | (println "// analyzing cljs/core.cljs") 14 | (cljs.analyzer/analyze-file "cljs/core.cljs")) 15 | ~@body)) 16 | 17 | -------------------------------------------------------------------------------- /src/cljs/cljs/compiler_macros.cljs: -------------------------------------------------------------------------------- 1 | compiler_macros.clj -------------------------------------------------------------------------------- /src/cljs/cljs/core_macros.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.core-macros) 2 | 3 | (def 4 | 5 | ^{:doc "Like defn, but the resulting function name is declared as a 6 | macro and will be used as a macro by the compiler when it is 7 | called." 8 | :arglists '([name doc-string? attr-map? [params*] body] 9 | [name doc-string? attr-map? ([params*] body)+ attr-map?]) 10 | :added "1.0"} 11 | clj-defmacro (fn [&form &env 12 | name & args] 13 | (let [prefix (loop [p (list name) args args] 14 | (let [f (first args)] 15 | (if (string? f) 16 | (recur (cons f p) (next args)) 17 | (if (map? f) 18 | (recur (cons f p) (next args)) 19 | p)))) 20 | fdecl (loop [fd args] 21 | (if (string? (first fd)) 22 | (recur (next fd)) 23 | (if (map? (first fd)) 24 | (recur (next fd)) 25 | fd))) 26 | fdecl (if (vector? (first fdecl)) 27 | (list fdecl) 28 | fdecl) 29 | add-implicit-args (fn [fd] 30 | (let [args (first fd)] 31 | (cons (vec (cons '&form (cons '&env args))) (next fd)))) 32 | add-args (fn [acc ds] 33 | (if (nil? ds) 34 | acc 35 | (let [d (first ds)] 36 | (if (map? d) 37 | (conj acc d) 38 | (recur (conj acc (add-implicit-args d)) (next ds)))))) 39 | fdecl (seq (add-args [] fdecl)) 40 | decl (loop [p prefix d fdecl] 41 | (if p 42 | (recur (next p) (cons (first p) d)) 43 | d))] 44 | (list 'do 45 | #_(list 'def (first decl) (cons `fn* (first (rest decl)))) 46 | (cons `defn decl) 47 | #_(list '. (list 'var name) '(setMacro)) 48 | (list 'cljs.core/setMacro (list 'quote name)) 49 | #_(list 'var name))))) 50 | 51 | (. (var clj-defmacro) (setMacro)) 52 | #_(setMacro 'cljs.core/defmacro) 53 | -------------------------------------------------------------------------------- /src/cljs/cljs/core_top.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns cljs.core) 10 | -------------------------------------------------------------------------------- /src/cljs/cljs/nodejs.cljs: -------------------------------------------------------------------------------- 1 | ; Projects compiled with :target :nodejs can 'require' this namespace 2 | ; to get the nodejs globals loaded into cljs.nodejs and get 3 | ; ClojureScript's 'print' set up correctly. 4 | (ns cljs.nodejs) 5 | 6 | ; Define namespaced references to Node's externed globals: 7 | (def require (js* "require")) 8 | (def process (js* "process")) 9 | 10 | ; Have ClojureScript print using Node's sys.print function 11 | (set! cljs.core/string-print (.-print (require "util"))) 12 | -------------------------------------------------------------------------------- /src/cljs/cljs/nodejs_externs.js: -------------------------------------------------------------------------------- 1 | function require(){} 2 | function process(){} 3 | -------------------------------------------------------------------------------- /src/cljs/cljs/nodejscli.cljs: -------------------------------------------------------------------------------- 1 | ; Projects compiled with :target :nodejs have this file appended. Its 2 | ; job is to make sure cljs.nodejs is loaded and that the *main-cli-fn* 3 | ; is called with the script's command-line arguments. 4 | (ns cljs.nodejscli 5 | (:require [cljs.nodejs :as nodejs])) 6 | 7 | ; Call the user's main function 8 | (apply cljs.core/*main-cli-fn* (drop 2 (.-argv nodejs/process))) 9 | 10 | -------------------------------------------------------------------------------- /src/cljs/cljs/repl.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.repl 2 | (:require [cljs.analyzer :as ana] 3 | [cljs.compiler :as comp] 4 | [cljs.reader :as reader])) 5 | 6 | (def ^:dynamic *debug* false) 7 | 8 | (defn prompt [] (str *ns-sym* "=> ")) 9 | 10 | (defn evaluate-next-form 11 | "Evaluates next clojure form in reader. Returns a map, containing 12 | either resulting value and emitted javascript, or an error 13 | object, or {:finished true}." 14 | [rdr] 15 | (try 16 | (let [form (reader/read rdr false ::finished-reading) 17 | _ (when *debug* (println "READ:" (pr-str form)))] 18 | (if (= form ::finished-reading) 19 | {:finished true} 20 | (let [env (assoc (ana/empty-env) :context :expr) 21 | body (ana/analyze env form) 22 | _ (when *debug* (println "ANALYZED:" (pr-str (:form body)))) 23 | res (comp/emit-str body) 24 | _ (when *debug* (println "EMITTED:" (pr-str res))) 25 | value (js/eval res)] 26 | {:value value :js res}))) 27 | (catch js/Error e 28 | {:error e :line-number (reader/get-line-number rdr)}))) 29 | 30 | (defn evaluate-code 31 | "Evaluates some text from REPL input. If multiple forms are 32 | present, evaluates in sequence until one throws an error 33 | or the last form is reached. The result from the last 34 | evaluated form is returned. *1, *2, *3, and *e are updated 35 | appropriately." 36 | [text] 37 | (let [rdr (reader/indexing-push-back-reader text)] 38 | (loop [last-output nil] 39 | (let [output (evaluate-next-form rdr)] 40 | (if-not (:finished output) 41 | (if-let [err (:error output)] 42 | (do (set! cljs.core/*e err) 43 | output) 44 | (recur output)) 45 | (do (set! *3 *2) 46 | (set! *2 *1) 47 | (set! *1 (:value last-output)) 48 | last-output)))))) 49 | 50 | (defn print-error [{:keys [error line-number]}] 51 | (print error "at line" line-number)) 52 | 53 | (defn eval-print [input] 54 | (let [evaluated (evaluate-code input)] 55 | (if (:error evaluated) 56 | (binding [*out* *err*] (print-error evaluated)) 57 | (try 58 | (binding [*out* *rtn*] (pr (:value evaluated))) 59 | (catch js/Error e 60 | (binding [*out* *err*] (println err))))))) 61 | 62 | (defn complete-form? [text] 63 | (try 64 | (reader/read-string text) 65 | true 66 | (catch js/Error e 67 | (not (re-find #"EOF while reading" (.-message e)))))) 68 | 69 | (defn init [] 70 | ;; Bootstrap an empty version of the cljs.user namespace 71 | (swap! comp/*emitted-provides* conj (symbol "cljs.user")) 72 | (.provide js/goog "cljs.user") 73 | (set! cljs.core/*ns-sym* (symbol "cljs.user"))) 74 | 75 | -------------------------------------------------------------------------------- /src/cljs/cljsc.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns cljsc 10 | (:require [cljs.closure :as closure])) 11 | 12 | (defn transform-cl-args 13 | [args] 14 | (let [source (first args) 15 | opts-string (apply str (interpose " " (rest args))) 16 | options (when (> (count opts-string) 1) 17 | (try (read-string opts-string) 18 | (catch Exception e (println e))))] 19 | {:source source :options (merge {:output-to :print} options)})) 20 | 21 | (defn- -main 22 | [& cmdline-args] 23 | 24 | ;; Setup the print function 25 | (set! *out* #(.write (.-stdout js/process) %)) 26 | (set! *err* #(.write (.-stderr js/process) %)) 27 | (set! *print-fn* #(*out* %)) 28 | 29 | (let [args (transform-cl-args cmdline-args)] 30 | (closure/build (:source args) (:options args)))) 31 | 32 | (set! *main-cli-fn* -main) 33 | -------------------------------------------------------------------------------- /src/cljs/clojure/browser/dom.cljs: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.browser.dom 10 | (:require [goog.dom :as gdom] 11 | [goog.object :as gobject])) 12 | 13 | (defn append [parent & children] 14 | (apply gdom/append parent children) 15 | parent) 16 | 17 | (defprotocol DOMBuilder 18 | (-element [this] [this attrs-or-children] [this attrs children])) 19 | 20 | (defn log [& args] 21 | (.log js/console (apply pr-str args))) 22 | 23 | (defn log-obj [obj] 24 | (.log js/console obj)) 25 | 26 | (extend-protocol DOMBuilder 27 | 28 | string 29 | (-element 30 | ([this] 31 | (log "string (-element " this ")") 32 | (cond (keyword? this) (gdom/createElement (name this)) 33 | :else (gdom/createTextNode (name this)))) 34 | 35 | ([this attrs-or-children] 36 | (log "string (-element " this " " attrs-or-children ")") 37 | (let [attrs (first attrs-or-children)] 38 | (if (map? attrs) 39 | (-element this attrs (rest attrs-or-children)) 40 | (-element this nil attrs-or-children)))) 41 | 42 | ([this attrs children] 43 | (log "string (-element " this " " attrs " " children ")") 44 | (let [str-attrs (if (and (map? attrs) (seq attrs)) 45 | (reduce (fn [o [k v]] 46 | (let [o (if (nil? o) (js-obj) o)] 47 | (log "o = " o) 48 | (log "k = " k) 49 | (log "v = " v) 50 | (when (or (keyword? k) 51 | (string? k)) 52 | (doto o (aset (name k) v))))) 53 | (js-obj) 54 | attrs) 55 | nil)] 56 | (log-obj str-attrs) 57 | (if (seq children) 58 | (apply gdom/createDom 59 | (name this) 60 | str-attrs 61 | (map -element children)) 62 | (gdom/createDom (name this) 63 | str-attrs))))) 64 | 65 | PersistentVector 66 | (-element 67 | [this] 68 | (log "PersistentVector (-element " this ")") 69 | (let [tag (first this) 70 | attrs (second this) 71 | children (drop 2 this)] 72 | (if (map? attrs) 73 | (-element tag attrs children) 74 | (-element tag nil (rest this))))) 75 | 76 | js/Element 77 | (-element [this] 78 | (log "js/Element (-element " this ")") 79 | this)) 80 | 81 | (defn element 82 | ([tag-or-text] 83 | (log "(element " tag-or-text ")") 84 | (-element tag-or-text)) 85 | ([tag & children] 86 | (log "(element " tag " " children ")") 87 | (let [attrs (first children)] 88 | (if (map? attrs) 89 | (-element tag attrs (rest children)) 90 | (-element tag nil children))))) 91 | 92 | (defn remove-children 93 | "Remove all children from the element with the passed id." 94 | [id] 95 | (let [parent (gdom/getElement (name id))] 96 | (do (gdom/removeChildren parent)))) 97 | 98 | (defn get-element [id] 99 | (gdom/getElement (name id))) 100 | 101 | (defn html->dom [s] 102 | (gdom/htmlToDocumentFragment s)) 103 | 104 | (defn insert-at [parent child index] 105 | (gdom/insertChildAt parent child index)) 106 | 107 | (defn ensure-element 108 | "Coerce the argument to a dom element if possible." 109 | [e] 110 | (cond (keyword? e) (get-element e) 111 | (string? e) (html->dom e) 112 | :else e)) 113 | 114 | (defn replace-node 115 | "Replace old-node with new-node. old-node can be an element or a 116 | keyword which is the id of the node to replace. new-node can be an 117 | element or an html string." 118 | [old-node new-node] 119 | (let [old-node (ensure-element old-node) 120 | new-node (ensure-element new-node)] 121 | (gdom/replaceNode new-node old-node) 122 | new-node)) 123 | 124 | (defn set-text 125 | "Set the text content for the passed element returning the 126 | element. If a keyword is passed in the place of e, the element with 127 | that id will be used and returned." 128 | [e s] 129 | (gdom/setTextContent (ensure-element e) s)) 130 | 131 | (defn get-value 132 | "Get the value of an element." 133 | [e] 134 | (.-value (ensure-element e))) 135 | 136 | (defn set-properties 137 | "Set properties on an element" 138 | [e m] 139 | (gdom/setProperties (ensure-element e) 140 | (apply gobject/create (interleave (keys m) (vals m))))) 141 | 142 | (defn set-value 143 | "Set the value property for an element." 144 | [e v] 145 | (set-properties e {"value" v})) 146 | 147 | (defn click-element 148 | [e] 149 | (.click (ensure-element e) ())) 150 | 151 | ;; TODO CSS class manipulation 152 | ;; TODO Query syntax 153 | -------------------------------------------------------------------------------- /src/cljs/clojure/browser/event.cljs: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^{:doc "This namespace contains functions to work with browser 10 | events. It is based on the Google Closure Library event system." 11 | :author "Bobby Calderwood"} 12 | clojure.browser.event 13 | (:require [goog.events :as events] 14 | [goog.events.EventTarget :as gevent-target] 15 | [goog.events.EventType :as gevent-type])) 16 | 17 | (defprotocol EventType 18 | (event-types [this])) 19 | 20 | (extend-protocol EventType 21 | 22 | goog.events.EventTarget 23 | (event-types 24 | [this] 25 | (into {} 26 | (map 27 | (fn [[k v]] 28 | [(keyword (. k (toLowerCase))) 29 | v]) 30 | (merge 31 | (js->clj goog.events.EventType))))) 32 | 33 | js/Element 34 | (event-types 35 | [this] 36 | (into {} 37 | (map 38 | (fn [[k v]] 39 | [(keyword (. k (toLowerCase))) 40 | v]) 41 | (merge 42 | (js->clj goog.events.EventType)))))) 43 | 44 | (defn listen 45 | ([src type fn] 46 | (listen src type fn false)) 47 | ([src type fn capture?] 48 | (goog.events/listen src 49 | (get (event-types src) type type) 50 | fn 51 | capture?))) 52 | 53 | (defn listen-once 54 | ([src type fn] 55 | (listen-once src type fn false)) 56 | ([src type fn capture?] 57 | (goog.events/listenOnce src 58 | (get (event-types src) type type) 59 | fn 60 | capture?))) 61 | 62 | (defn unlisten 63 | ([src type fn] 64 | (unlisten src type fn false)) 65 | ([src type fn capture?] 66 | (goog.events/unlisten src 67 | (get (event-types src) type type) 68 | fn 69 | capture?))) 70 | 71 | (defn unlisten-by-key 72 | [key] 73 | (goog.events/unlistenByKey key)) 74 | 75 | (defn dispatch-event 76 | [src event] 77 | (goog.events/dispatchEvent src event)) 78 | 79 | (defn expose [e] 80 | (goog.events/expose e)) 81 | 82 | (defn fire-listeners 83 | [obj type capture event]) 84 | 85 | (defn total-listener-count [] 86 | (goog.events/getTotalListenerCount)) 87 | 88 | ;; TODO 89 | (defn get-listener [src type listener opt_capt opt_handler]); ⇒ ?Listener 90 | (defn all-listeners [obj type capture]); ⇒ Array. 91 | 92 | (defn unique-event-id [event-type]); ⇒ string 93 | 94 | (defn has-listener [obj opt_type opt_capture]); ⇒ boolean 95 | ;; TODO? (defn listen-with-wrapper [src wrapper listener opt_capt opt_handler]) 96 | ;; TODO? (defn protect-browser-event-entry-point [errorHandler]) 97 | 98 | (defn remove-all [opt_obj opt_type opt_capt]); ⇒ number 99 | ;; TODO? (defn unlisten-with-wrapper [src wrapper listener opt_capt opt_handler]) 100 | 101 | -------------------------------------------------------------------------------- /src/cljs/clojure/browser/net.cljs: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^{:doc "Network communication library, wrapping goog.net. 10 | Includes a common API over XhrIo, CrossPageChannel, and Websockets." 11 | :author "Bobby Calderwood and Alex Redington"} 12 | clojure.browser.net 13 | (:require [clojure.browser.event :as event] 14 | [goog.net.XhrIo :as gxhrio] 15 | [goog.net.EventType :as gnet-event-type] 16 | [goog.net.xpc.CfgFields :as gxpc-config-fields] 17 | [goog.net.xpc.CrossPageChannel :as xpc] 18 | #_[goog.net.WebSocket :as gwebsocket] 19 | [goog.json :as gjson])) 20 | 21 | (def *timeout* 10000) 22 | 23 | (def event-types 24 | (into {} 25 | (map 26 | (fn [[k v]] 27 | [(keyword (. k (toLowerCase))) 28 | v]) 29 | (merge 30 | (js->clj goog.net.EventType))))) 31 | 32 | (defprotocol IConnection 33 | (connect 34 | [this] 35 | [this opt1] 36 | [this opt1 opt2] 37 | [this opt1 opt2 opt3]) 38 | (transmit 39 | [this opt] 40 | [this opt opt2] 41 | [this opt opt2 opt3] 42 | [this opt opt2 opt3 opt4] 43 | [this opt opt2 opt3 opt4 opt5]) 44 | (close [this])) 45 | 46 | (extend-type goog.net.XhrIo 47 | 48 | IConnection 49 | (transmit 50 | ([this uri] 51 | (transmit this uri "GET" nil nil *timeout*)) 52 | ([this uri method] 53 | (transmit this uri method nil nil *timeout*)) 54 | ([this uri method content] 55 | (transmit this uri method content nil *timeout*)) 56 | ([this uri method content headers] 57 | (transmit this uri method content headers *timeout*)) 58 | ([this uri method content headers timeout] 59 | (.setTimeoutInterval this timeout) 60 | (.send this uri method content headers))) 61 | 62 | 63 | event/EventType 64 | (event-types [this] 65 | (into {} 66 | (map 67 | (fn [[k v]] 68 | [(keyword (. k (toLowerCase))) 69 | v]) 70 | (merge 71 | (js->clj goog.net.EventType)))))) 72 | 73 | ;; TODO jQuery/sinatra/RestClient style API: (get [uri]), (post [uri payload]), (put [uri payload]), (delete [uri]) 74 | 75 | (def xpc-config-fields 76 | (into {} 77 | (map 78 | (fn [[k v]] 79 | [(keyword (. k (toLowerCase))) 80 | v]) 81 | (js->clj goog.net.xpc.CfgFields)))) 82 | 83 | (defn xhr-connection 84 | "Returns an XhrIo connection" 85 | [] 86 | (goog.net.XhrIo.)) 87 | 88 | (defprotocol ICrossPageChannel 89 | (register-service [this service-name fn] [this service-name fn encode-json?])) 90 | 91 | (extend-type goog.net.xpc.CrossPageChannel 92 | 93 | ICrossPageChannel 94 | (register-service 95 | ([this service-name fn] 96 | (register-service this service-name fn false)) 97 | ([this service-name fn encode-json?] 98 | (.registerService this (name service-name) fn encode-json?))) 99 | 100 | IConnection 101 | (connect 102 | ([this] 103 | (connect this nil)) 104 | ([this on-connect-fn] 105 | (.connect this on-connect-fn)) 106 | ([this on-connect-fn config-iframe-fn] 107 | (connect this on-connect-fn config-iframe-fn (.-body js/document))) 108 | ([this on-connect-fn config-iframe-fn iframe-parent] 109 | (.createPeerIframe this iframe-parent config-iframe-fn) 110 | (.connect this on-connect-fn))) 111 | 112 | (transmit [this service-name payload] 113 | (.send this (name service-name) payload)) 114 | 115 | (close [this] 116 | (.close this ()))) 117 | 118 | (defn xpc-connection 119 | "When passed with a config hash-map, returns a parent 120 | CrossPageChannel object. Keys in the config hash map are downcased 121 | versions of the goog.net.xpc.CfgFields enum keys, 122 | e.g. goog.net.xpc.CfgFields.PEER_URI becomes :peer_uri in the config 123 | hash. 124 | 125 | When passed with no args, creates a child CrossPageChannel object, 126 | and the config is automatically taken from the URL param 'xpc', as 127 | per the CrossPageChannel API." 128 | ([] 129 | (when-let [config (.getParameterValue 130 | (goog.Uri. (.-href (.-location js/window))) 131 | "xpc")] 132 | (goog.net.xpc.CrossPageChannel. (gjson/parse config)))) 133 | ([config] 134 | (goog.net.xpc.CrossPageChannel. 135 | (reduce (fn [sum [k v]] 136 | (if-let [field (get xpc-config-fields k)] 137 | (doto sum (aset field v)) 138 | sum)) 139 | (js-obj) 140 | config)))) 141 | 142 | ;; WebSocket is not supported in the 3/23/11 release of Google 143 | ;; Closure, but will be included in the next release. 144 | 145 | #_(defprotocol IWebSocket 146 | (open? [this])) 147 | 148 | #_(extend-type goog.net.WebSocket 149 | 150 | IWebSocket 151 | (open? [this] 152 | (.isOpen this ())) 153 | 154 | IConnection 155 | (connect 156 | ([this url] 157 | (connect this url nil)) 158 | ([this url protocol] 159 | (.open this url protocol))) 160 | 161 | (transmit [this message] 162 | (.send this message)) 163 | 164 | (close [this] 165 | (.close this ())) 166 | 167 | event/EventType 168 | (event-types [this] 169 | (into {} 170 | (map 171 | (fn [[k v]] 172 | [(keyword (. k (toLowerCase))) 173 | v]) 174 | (merge 175 | (js->clj goog.net.WebSocket/EventType)))))) 176 | 177 | #_(defn websocket-connection 178 | ([] 179 | (websocket-connection nil nil)) 180 | ([auto-reconnect?] 181 | (websocket-connection auto-reconnect? nil)) 182 | ([auto-reconnect? next-reconnect-fn] 183 | (goog.net.WebSocket. auto-reconnect? next-reconnect-fn))) -------------------------------------------------------------------------------- /src/cljs/clojure/browser/repl.cljs: -------------------------------------------------------------------------------- 1 | ;; Copyright (c) Rich Hickey. All rights reserved. 2 | ;; The use and distribution terms for this software are covered by the 3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ;; which can be found in the file epl-v10.html at the root of this distribution. 5 | ;; By using this software in any fashion, you are agreeing to be bound by 6 | ;; the terms of this license. 7 | ;; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^{:doc "Receive - Eval - Print - Loop 10 | 11 | Receive a block of JS (presumably generated by a ClojureScript compiler) 12 | Evaluate it naively 13 | Print the result of evaluation to a string 14 | Send the resulting string back to the server Loop!" 15 | 16 | :author "Bobby Calderwood and Alex Redington"} 17 | clojure.browser.repl 18 | (:require [clojure.browser.net :as net] 19 | [clojure.browser.event :as event])) 20 | 21 | (def xpc-connection (atom nil)) 22 | 23 | (defn repl-print [data] 24 | (if-let [conn @xpc-connection] 25 | (net/transmit conn :print (pr-str data)))) 26 | 27 | (defn evaluate-javascript 28 | "Process a single block of JavaScript received from the server" 29 | [conn block] 30 | (let [result (try {:status :success :value (str (js* "eval(~{block})"))} 31 | (catch js/Error e 32 | {:status :exception :value (pr-str e) 33 | :stacktrace (if (.hasOwnProperty e "stack") 34 | (.-stack e) 35 | "No stacktrace available.")}))] 36 | (pr-str result))) 37 | 38 | (defn send-result [connection url data] 39 | (net/transmit connection url "POST" data nil 0)) 40 | 41 | (defn send-print 42 | "Send data to be printed in the REPL. If there is an error, try again 43 | up to 10 times." 44 | ([url data] 45 | (send-print url data 0)) 46 | ([url data n] 47 | (let [conn (net/xhr-connection)] 48 | (event/listen conn :error 49 | (fn [_] 50 | (if (< n 10) 51 | (send-print url data (inc n)) 52 | (.log js/console (str "Could not send " data " after " n " attempts."))))) 53 | (net/transmit conn url "POST" data nil 0)))) 54 | 55 | (def order (atom 0)) 56 | 57 | (defn wrap-message [t data] 58 | (pr-str {:type t :content data :order (swap! order inc)})) 59 | 60 | (defn start-evaluator 61 | "Start the REPL server connection." 62 | [url] 63 | (if-let [repl-connection (net/xpc-connection)] 64 | (let [connection (net/xhr-connection)] 65 | (event/listen connection 66 | :success 67 | (fn [e] 68 | (net/transmit 69 | repl-connection 70 | :evaluate-javascript 71 | (.getResponseText e/currentTarget 72 | ())))) 73 | 74 | (net/register-service repl-connection 75 | :send-result 76 | (fn [data] 77 | (send-result connection url (wrap-message :result data)))) 78 | 79 | (net/register-service repl-connection 80 | :print 81 | (fn [data] 82 | (send-print url (wrap-message :print data)))) 83 | 84 | (net/connect repl-connection 85 | (constantly nil)) 86 | 87 | (js/setTimeout #(send-result connection url (wrap-message :ready "ready")) 50)) 88 | (js/alert "No 'xpc' param provided to child iframe."))) 89 | 90 | (defn connect 91 | "Connects to a REPL server from an HTML document. After the 92 | connection is made, the REPL will evaluate forms in the context of 93 | the document that called this function." 94 | [repl-server-url] 95 | (let [repl-connection (net/xpc-connection 96 | {:peer_uri repl-server-url})] 97 | (swap! xpc-connection (constantly repl-connection)) 98 | (net/register-service repl-connection 99 | :evaluate-javascript 100 | (fn [js] 101 | (net/transmit 102 | repl-connection 103 | :send-result 104 | (evaluate-javascript repl-connection js)))) 105 | (net/connect repl-connection 106 | (constantly nil) 107 | (fn [iframe] 108 | (set! (.-display (.-style iframe)) 109 | "none"))))) 110 | -------------------------------------------------------------------------------- /src/cljs/clojure/data.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns 10 | ^{:author "Stuart Halloway", 11 | :doc "Non-core data functions."} 12 | clojure.data 13 | (:require [clojure.set :as set])) 14 | 15 | (declare diff) 16 | 17 | (defn- atom-diff 18 | "Internal helper for diff." 19 | [a b] 20 | (if (= a b) [nil nil a] [a b nil])) 21 | 22 | ;; for big things a sparse vector class would be better 23 | (defn- vectorize 24 | "Convert an associative-by-numeric-index collection into 25 | an equivalent vector, with nil for any missing keys" 26 | [m] 27 | (when (seq m) 28 | (reduce 29 | (fn [result [k v]] (assoc result k v)) 30 | (vec (repeat (apply max (keys m)) nil)) 31 | m))) 32 | 33 | (defn- diff-associative-key 34 | "Diff associative things a and b, comparing only the key k." 35 | [a b k] 36 | (let [va (get a k) 37 | vb (get b k) 38 | [a* b* ab] (diff va vb) 39 | in-a (contains? a k) 40 | in-b (contains? b k) 41 | same (and in-a in-b 42 | (or (not (nil? ab)) 43 | (and (nil? va) (nil? vb))))] 44 | [(when (and in-a (or (not (nil? a*)) (not same))) {k a*}) 45 | (when (and in-b (or (not (nil? b*)) (not same))) {k b*}) 46 | (when same {k ab}) 47 | ])) 48 | 49 | (defn- diff-associative 50 | "Diff associative things a and b, comparing only keys in ks (if supplied)." 51 | ([a b] 52 | (diff-associative a b (set/union (keys a) (keys b)))) 53 | ([a b ks] 54 | (reduce 55 | (fn [diff1 diff2] 56 | (doall (map merge diff1 diff2))) 57 | [nil nil nil] 58 | (map 59 | (partial diff-associative-key a b) 60 | ks)))) 61 | 62 | (defn- diff-sequential 63 | [a b] 64 | (vec (map vectorize (diff-associative 65 | (if (vector? a) a (vec a)) 66 | (if (vector? b) b (vec b)) 67 | (range (max (count a) (count b))))))) 68 | 69 | (defn- diff-set 70 | [a b] 71 | [(not-empty (set/difference a b)) 72 | (not-empty (set/difference b a)) 73 | (not-empty (set/intersection a b))]) 74 | 75 | (defprotocol EqualityPartition 76 | "Implementation detail. Subject to change." 77 | (equality-partition [x] "Implementation detail. Subject to change.")) 78 | 79 | (defprotocol Diff 80 | "Implementation detail. Subject to change." 81 | (diff-similar [a b] "Implementation detail. Subject to change.")) 82 | 83 | (extend-protocol EqualityPartition 84 | nil 85 | (equality-partition [x] :atom) 86 | 87 | string 88 | (equality-partition [x] :atom) 89 | 90 | number 91 | (equality-partition [x] :atom) 92 | 93 | array 94 | (equality-partition [x] :sequential) 95 | 96 | function 97 | (equality-partition [x] :atom) 98 | 99 | boolean 100 | (equality-partition [x] :atom) 101 | 102 | default 103 | (equality-partition [x] 104 | (cond 105 | (satisfies? IMap x) :map 106 | (satisfies? ISet x) :set 107 | (satisfies? ISequential x) :sequential 108 | :default :atom))) 109 | 110 | (extend-protocol Diff 111 | nil 112 | (diff-similar [a b] 113 | (atom-diff a b)) 114 | 115 | string 116 | (diff-similar [a b] 117 | (atom-diff a b)) 118 | 119 | number 120 | (diff-similar [a b] 121 | (atom-diff a b)) 122 | 123 | array 124 | (diff-similar [a b] 125 | (diff-sequential a b)) 126 | 127 | function 128 | (diff-similar [a b] 129 | (atom-diff a b)) 130 | 131 | boolean 132 | (diff-similar [a b] 133 | (atom-diff a b)) 134 | 135 | default 136 | (diff-similar [a b] 137 | ((case (equality-partition a) 138 | :atom atom-diff 139 | :set diff-set 140 | :sequential diff-sequential 141 | :map diff-associative) 142 | a b))) 143 | 144 | (defn diff 145 | "Recursively compares a and b, returning a tuple of 146 | [things-only-in-a things-only-in-b things-in-both]. 147 | Comparison rules: 148 | 149 | * For equal a and b, return [nil nil a]. 150 | * Maps are subdiffed where keys match and values differ. 151 | * Sets are never subdiffed. 152 | * All sequential things are treated as associative collections 153 | by their indexes, with results returned as vectors. 154 | * Everything else (including strings!) is treated as 155 | an atom and compared for equality." 156 | [a b] 157 | (if (= a b) 158 | [nil nil a] 159 | (if (= (equality-partition a) (equality-partition b)) 160 | (diff-similar a b) 161 | (atom-diff a b)))) 162 | 163 | -------------------------------------------------------------------------------- /src/cljs/clojure/reflect.cljs: -------------------------------------------------------------------------------- 1 | (ns clojure.reflect 2 | (:refer-clojure :exclude [meta]) 3 | (:require [clojure.browser.net :as net] 4 | [clojure.browser.event :as event])) 5 | 6 | (defn- evaluate-javascript [block] 7 | (let [result (try (js* "eval(~{block})") 8 | (catch js/Error e 9 | (.log js/console e)))] 10 | result)) 11 | 12 | (defn- query-reflection 13 | "Issues a GET to /reflect with a single query-parameter string. 14 | Calls cb with the result." 15 | [query-param cb] 16 | (let [conn (net/xhr-connection) 17 | url (str "/reflect?" query-param)] 18 | (event/listen conn :success (fn [e] 19 | (let [resp (.getResponseText e/currentTarget ())] 20 | (cb resp)))) 21 | (event/listen conn :error #(println "Reflection query failed.")) 22 | (net/transmit conn url))) 23 | 24 | (defn meta 25 | "Queries the reflection api with a fully qualified symbol, then calls 26 | callback fn cb with the evaluated cljs map containing that symbol's 27 | meta information." 28 | [sym cb] 29 | (query-reflection (str "var=" (js/encodeURIComponent (str sym))) 30 | #(cb (evaluate-javascript %)))) 31 | 32 | (defn macroexpand 33 | "Queries the reflection api with a quoted macro form, then calls the 34 | callback function with the macroexpanded form, as a string." 35 | [form] 36 | (query-reflection (str "macroform=" (js/encodeURIComponent (str form))) println)) 37 | 38 | (defn print-doc [{:keys [name method-params doc]}] 39 | (when-not (empty? name) 40 | (println name) 41 | (println method-params) 42 | (println doc))) 43 | 44 | (defn doc 45 | "Queries the reflection api with a fully qualified symbol, then prints 46 | documentation information at the repl." 47 | [sym] 48 | (meta sym print-doc)) 49 | -------------------------------------------------------------------------------- /src/cljs/clojure/set.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns ^{:doc "Set operations such as union/intersection." 10 | :author "Rich Hickey"} 11 | clojure.set) 12 | 13 | (defn- bubble-max-key [k coll] 14 | "Move a maximal element of coll according to fn k (which returns a number) 15 | to the front of coll." 16 | (let [max (apply max-key k coll)] 17 | (cons max (remove #(identical? max %) coll)))) 18 | 19 | (defn union 20 | "Return a set that is the union of the input sets" 21 | ([] #{}) 22 | ([s1] s1) 23 | ([s1 s2] 24 | (if (< (count s1) (count s2)) 25 | (reduce conj s2 s1) 26 | (reduce conj s1 s2))) 27 | ([s1 s2 & sets] 28 | (let [bubbled-sets (bubble-max-key count (conj sets s2 s1))] 29 | (reduce into (first bubbled-sets) (rest bubbled-sets))))) 30 | 31 | (defn intersection 32 | "Return a set that is the intersection of the input sets" 33 | ([s1] s1) 34 | ([s1 s2] 35 | (if (< (count s2) (count s1)) 36 | (recur s2 s1) 37 | (reduce (fn [result item] 38 | (if (contains? s2 item) 39 | result 40 | (disj result item))) 41 | s1 s1))) 42 | ([s1 s2 & sets] 43 | (let [bubbled-sets (bubble-max-key #(- (count %)) (conj sets s2 s1))] 44 | (reduce intersection (first bubbled-sets) (rest bubbled-sets))))) 45 | 46 | (defn difference 47 | "Return a set that is the first set without elements of the remaining sets" 48 | ([s1] s1) 49 | ([s1 s2] 50 | (if (< (count s1) (count s2)) 51 | (reduce (fn [result item] 52 | (if (contains? s2 item) 53 | (disj result item) 54 | result)) 55 | s1 s1) 56 | (reduce disj s1 s2))) 57 | ([s1 s2 & sets] 58 | (reduce difference s1 (conj sets s2)))) 59 | 60 | 61 | (defn select 62 | "Returns a set of the elements for which pred is true" 63 | [pred xset] 64 | (reduce (fn [s k] (if (pred k) s (disj s k))) 65 | xset xset)) 66 | 67 | (defn project 68 | "Returns a rel of the elements of xrel with only the keys in ks" 69 | [xrel ks] 70 | (set (map #(select-keys % ks) xrel))) 71 | 72 | (defn rename-keys 73 | "Returns the map with the keys in kmap renamed to the vals in kmap" 74 | [map kmap] 75 | (reduce 76 | (fn [m [old new]] 77 | (if (and (not= old new) 78 | (contains? m old)) 79 | (-> m (assoc new (get m old)) (dissoc old)) 80 | m)) 81 | map kmap)) 82 | 83 | (defn rename 84 | "Returns a rel of the maps in xrel with the keys in kmap renamed to the vals in kmap" 85 | [xrel kmap] 86 | (set (map #(rename-keys % kmap) xrel))) 87 | 88 | (defn index 89 | "Returns a map of the distinct values of ks in the xrel mapped to a 90 | set of the maps in xrel with the corresponding values of ks." 91 | [xrel ks] 92 | (reduce 93 | (fn [m x] 94 | (let [ik (select-keys x ks)] 95 | (assoc m ik (conj (get m ik #{}) x)))) 96 | {} xrel)) 97 | 98 | (defn map-invert 99 | "Returns the map with the vals mapped to the keys." 100 | [m] (reduce (fn [m [k v]] (assoc m v k)) {} m)) 101 | 102 | (defn join 103 | "When passed 2 rels, returns the rel corresponding to the natural 104 | join. When passed an additional keymap, joins on the corresponding 105 | keys." 106 | ([xrel yrel] ;natural join 107 | (if (and (seq xrel) (seq yrel)) 108 | (let [ks (intersection (set (keys (first xrel))) (set (keys (first yrel)))) 109 | [r s] (if (<= (count xrel) (count yrel)) 110 | [xrel yrel] 111 | [yrel xrel]) 112 | idx (index r ks)] 113 | (reduce (fn [ret x] 114 | (let [found (idx (select-keys x ks))] 115 | (if found 116 | (reduce #(conj %1 (merge %2 x)) ret found) 117 | ret))) 118 | #{} s)) 119 | #{})) 120 | ([xrel yrel km] ;arbitrary key mapping 121 | (let [[r s k] (if (<= (count xrel) (count yrel)) 122 | [xrel yrel (map-invert km)] 123 | [yrel xrel km]) 124 | idx (index r (vals k))] 125 | (reduce (fn [ret x] 126 | (let [found (idx (rename-keys (select-keys x (keys k)) k))] 127 | (if found 128 | (reduce #(conj %1 (merge %2 x)) ret found) 129 | ret))) 130 | #{} s)))) 131 | 132 | (defn subset? 133 | "Is set1 a subset of set2?" 134 | [set1 set2] 135 | (and (<= (count set1) (count set2)) 136 | (every? #(contains? set2 %) set1))) 137 | 138 | (defn superset? 139 | "Is set1 a superset of set2?" 140 | [set1 set2] 141 | (and (>= (count set1) (count set2)) 142 | (every? #(contains? set1 %) set2))) 143 | 144 | (comment 145 | (refer 'set) 146 | (def xs #{{:a 11 :b 1 :c 1 :d 4} 147 | {:a 2 :b 12 :c 2 :d 6} 148 | {:a 3 :b 3 :c 3 :d 8 :f 42}}) 149 | 150 | (def ys #{{:a 11 :b 11 :c 11 :e 5} 151 | {:a 12 :b 11 :c 12 :e 3} 152 | {:a 3 :b 3 :c 3 :e 7 }}) 153 | 154 | (join xs ys) 155 | (join xs (rename ys {:b :yb :c :yc}) {:a :a}) 156 | 157 | (union #{:a :b :c} #{:c :d :e }) 158 | (difference #{:a :b :c} #{:c :d :e}) 159 | (intersection #{:a :b :c} #{:c :d :e}) 160 | 161 | (index ys [:b])) 162 | 163 | -------------------------------------------------------------------------------- /src/cljs/clojure/string.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | (ns clojure.string 10 | (:refer-clojure :exclude [replace reverse]) 11 | (:require [goog.string :as gstring] 12 | [goog.string.StringBuffer :as gstringbuf])) 13 | 14 | (defn- seq-reverse 15 | [coll] 16 | (reduce conj () coll)) 17 | 18 | (defn reverse 19 | "Returns s with its characters reversed." 20 | [s] 21 | (.. s (split "") (reverse) (join ""))) 22 | 23 | (defn replace 24 | "Replaces all instance of match with replacement in s. 25 | match/replacement can be: 26 | 27 | string / string 28 | pattern / (string or function of match)." 29 | [s match replacement] 30 | (cond (string? match) 31 | (.replace s (js/RegExp. (gstring/regExpEscape match) "g") replacement) 32 | (.hasOwnProperty match "source") 33 | (.replace s (js/RegExp. (.-source match) "g") replacement) 34 | :else (throw (str "Invalid match arg: " match)))) 35 | 36 | (defn replace-first 37 | "Replaces the first instance of match with replacement in s. 38 | match/replacement can be: 39 | 40 | string / string 41 | pattern / (string or function of match)." 42 | [s match replacement] 43 | (.replace s match replacement)) 44 | 45 | (defn join 46 | "Returns a string of all elements in coll, as returned by (seq coll), 47 | separated by an optional separator." 48 | ([coll] 49 | (apply str coll)) 50 | ([separator coll] 51 | (apply str (interpose separator coll)))) 52 | 53 | (defn upper-case 54 | "Converts string to all upper-case." 55 | [s] 56 | (. s (toUpperCase))) 57 | 58 | (defn lower-case 59 | "Converts string to all lower-case." 60 | [s] 61 | (. s (toLowerCase))) 62 | 63 | (defn capitalize 64 | "Converts first character of the string to upper-case, all other 65 | characters to lower-case." 66 | [s] 67 | (if (< (count s) 2) 68 | (upper-case s) 69 | (str (upper-case (subs s 0 1)) 70 | (lower-case (subs s 1))))) 71 | 72 | ;; The JavaScript split function takes a limit argument but the return 73 | ;; value is not the same as the Java split function. 74 | ;; 75 | ;; Java: (.split "a-b-c" #"-" 2) => ["a" "b-c"] 76 | ;; JavaScript: (.split "a-b-c" #"-" 2) => ["a" "b"] 77 | ;; 78 | ;; For consistency, the three arg version has been implemented to 79 | ;; mimic Java's behavior. 80 | 81 | (defn split 82 | "Splits string on a regular expression. Optional argument limit is 83 | the maximum number of splits. Not lazy. Returns vector of the splits." 84 | ([s re] 85 | (vec (.split (str s) re))) 86 | ([s re limit] 87 | (if (< limit 1) 88 | (vec (.split (str s) re)) 89 | (loop [s s 90 | limit limit 91 | parts []] 92 | (if (= limit 1) 93 | (conj parts s) 94 | (if-let [m (re-find re s)] 95 | (let [index (.indexOf s m)] 96 | (recur (.substring s (+ index (count m))) 97 | (dec limit) 98 | (conj parts (.substring s 0 index)))) 99 | (conj parts s))))))) 100 | 101 | (defn split-lines 102 | "Splits s on \n or \r\n." 103 | [s] 104 | (split s #"\n|\r\n")) 105 | 106 | (defn trim 107 | "Removes whitespace from both ends of string." 108 | [s] 109 | (gstring/trim s)) 110 | 111 | (defn triml 112 | "Removes whitespace from the left side of string." 113 | [s] 114 | (gstring/trimLeft s)) 115 | 116 | (defn trimr 117 | "Removes whitespace from the right side of string." 118 | [s] 119 | (gstring/trimRight s)) 120 | 121 | (defn trim-newline 122 | "Removes all trailing newline \\n or return \\r characters from 123 | string. Similar to Perl's chomp." 124 | [s] 125 | (loop [index (.-length s)] 126 | (if (zero? index) 127 | "" 128 | (let [ch (get s (dec index))] 129 | (if (or (= ch \newline) (= ch \return)) 130 | (recur (dec index)) 131 | (.substring s 0 index)))))) 132 | 133 | (defn blank? 134 | "True is s is nil, empty, or contains only whitespace." 135 | [s] 136 | (gstring/isEmptySafe s)) 137 | 138 | (defn escape 139 | "Return a new string, using cmap to escape each character ch 140 | from s as follows: 141 | 142 | If (cmap ch) is nil, append ch to the new string. 143 | If (cmap ch) is non-nil, append (str (cmap ch)) instead." 144 | [s cmap] 145 | (let [buffer (gstring/StringBuffer.) 146 | length (.-length s)] 147 | (loop [index 0] 148 | (if (= length index) 149 | (. buffer (toString)) 150 | (let [ch (.charAt s index)] 151 | (if-let [replacement (get cmap ch)] 152 | (.append buffer (str replacement)) 153 | (.append buffer ch)) 154 | (recur (inc index))))))) 155 | -------------------------------------------------------------------------------- /src/cljs/clojure/walk.cljs: -------------------------------------------------------------------------------- 1 | ; Copyright (c) Rich Hickey. All rights reserved. 2 | ; The use and distribution terms for this software are covered by the 3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 4 | ; which can be found in the file epl-v10.html at the root of this distribution. 5 | ; By using this software in any fashion, you are agreeing to be bound by 6 | ; the terms of this license. 7 | ; You must not remove this notice, or any other, from this software. 8 | 9 | ;;; walk.cljs - generic tree walker with replacement 10 | 11 | ;; by Stuart Sierra 12 | ;; Jul5 17, 2011 13 | 14 | ;; CHANGE LOG: 15 | ;; 16 | ;; * July 17, 2011: Port to ClojureScript 17 | ;; 18 | ;; * December 15, 2008: replaced 'walk' with 'prewalk' & 'postwalk' 19 | ;; 20 | ;; * December 9, 2008: first version 21 | 22 | 23 | (ns 24 | ^{:author "Stuart Sierra", 25 | :doc "This file defines a generic tree walker for Clojure data 26 | structures. It takes any data structure (list, vector, map, set, 27 | seq), calls a function on every element, and uses the return value 28 | of the function in place of the original. This makes it fairly 29 | easy to write recursive search-and-replace functions, as shown in 30 | the examples. 31 | 32 | Note: \"walk\" supports all Clojure data structures EXCEPT maps 33 | created with sorted-map-by. There is no (obvious) way to retrieve 34 | the sorting function."} 35 | clojure.walk) 36 | 37 | (defn walk 38 | "Traverses form, an arbitrary data structure. inner and outer are 39 | functions. Applies inner to each element of form, building up a 40 | data structure of the same type, then applies outer to the result. 41 | Recognizes all Clojure data structures. Consumes seqs as with doall." 42 | 43 | {:added "1.1"} 44 | [inner outer form] 45 | (cond 46 | (seq? form) (outer (doall (map inner form))) 47 | (coll? form) (outer (into (empty form) (map inner form))) 48 | :else (outer form))) 49 | 50 | (defn postwalk 51 | "Performs a depth-first, post-order traversal of form. Calls f on 52 | each sub-form, uses f's return value in place of the original. 53 | Recognizes all Clojure data structures. Consumes seqs as with doall." 54 | {:added "1.1"} 55 | [f form] 56 | (walk (partial postwalk f) f form)) 57 | 58 | (defn prewalk 59 | "Like postwalk, but does pre-order traversal." 60 | {:added "1.1"} 61 | [f form] 62 | (walk (partial prewalk f) identity (f form))) 63 | 64 | (defn keywordize-keys 65 | "Recursively transforms all map keys from strings to keywords." 66 | {:added "1.1"} 67 | [m] 68 | (let [f (fn [[k v]] (if (string? k) [(keyword k) v] [k v]))] 69 | ;; only apply to maps 70 | (postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m))) 71 | 72 | (defn stringify-keys 73 | "Recursively transforms all map keys from keywords to strings." 74 | {:added "1.1"} 75 | [m] 76 | (let [f (fn [[k v]] (if (keyword? k) [(name k) v] [k v]))] 77 | ;; only apply to maps 78 | (postwalk (fn [x] (if (map? x) (into {} (map f x)) x)) m))) 79 | 80 | (defn prewalk-replace 81 | "Recursively transforms form by replacing keys in smap with their 82 | values. Like clojure/replace but works on any data structure. Does 83 | replacement at the root of the tree first." 84 | {:added "1.1"} 85 | [smap form] 86 | (prewalk (fn [x] (if (contains? smap x) (smap x) x)) form)) 87 | 88 | (defn postwalk-replace 89 | "Recursively transforms form by replacing keys in smap with their 90 | values. Like clojure/replace but works on any data structure. Does 91 | replacement at the leaves of the tree first." 92 | {:added "1.1"} 93 | [smap form] 94 | (postwalk (fn [x] (if (contains? smap x) (smap x) x)) form)) 95 | -------------------------------------------------------------------------------- /src/cljs/goog.js: -------------------------------------------------------------------------------- 1 | // Simple module wrapper around Google Closure Library 2 | // goog/ directory should be in the same directory as this file 3 | 4 | goog = exports; 5 | path_ = require("path"); 6 | googDir_ = path_.join(path_.dirname(module.filename), "goog"); 7 | 8 | rawLoaded_ = {}; 9 | rawLoad_ = function(file) { 10 | var path = path_.resolve(googDir_, file); 11 | //console.log("rawLoad_ file:", file, "path:", path); 12 | 13 | if (rawLoaded_[path]) { return; } 14 | rawLoaded_[path] = true; 15 | 16 | var contents = require('fs').readFileSync(path); 17 | // TODO: cljs.nodejscli needs require, but this is gross 18 | global.require = require; 19 | process.binding('evals').NodeScript. 20 | runInThisContext.call(global, contents, file); 21 | }; 22 | 23 | rawLoad_('base.js'); 24 | goog.global = goog.window = global.top = global; 25 | rawLoad_('deps.js'); 26 | 27 | // Override goog.require script loader/evaluator 28 | goog.writeScriptTag_ = function(file) { 29 | try { 30 | rawLoad_(file); 31 | } catch (exc) { 32 | console.error('Could not goog.require("' + file + '")\n' + exc.stack); 33 | process.exit(1); 34 | } 35 | return false; 36 | }; 37 | 38 | -------------------------------------------------------------------------------- /src/cljs/nodecljs.cljs: -------------------------------------------------------------------------------- 1 | (ns nodecljs 2 | (:require [cljs.repl :as repl])) 3 | 4 | (defn -main [file & args] 5 | (repl/init) 6 | 7 | ;; Setup the print function 8 | (set! *out* #(.write (.-stdout js/process) %)) 9 | (set! *rtn* identity) 10 | (set! *err* #(.write (.-stderr js/process) %)) 11 | (set! *print-fn* #(*out* %1)) 12 | 13 | ;(set! repl/*debug* true) 14 | (let [fs (js/require "fs") 15 | text (.toString (.readFileSync fs file)) 16 | res (repl/eval-print text) 17 | ret (:value res)] 18 | (.exit js/process (if (number? ret) ret 0)))) 19 | 20 | (set! *main-cli-fn* -main) 21 | 22 | -------------------------------------------------------------------------------- /src/cljs/noderepl.cljs: -------------------------------------------------------------------------------- 1 | (ns noderepl 2 | (:require [cljs.repl :as repl])) 3 | 4 | (defn pep [text] 5 | (println (str (repl/prompt) text)) 6 | (repl/eval-print text) 7 | (println)) 8 | 9 | (defn -main [& args] 10 | (repl/init) 11 | 12 | ;; Setup the print function 13 | (set! *out* #(.write (.-stdout js/process) %)) 14 | (set! *rtn* #(.write (.-stdout js/process) %)) 15 | (set! *err* #(.write (.-stderr js/process) %)) 16 | (set! *print-fn* #(*out* %)) 17 | 18 | (println ";; ClojureScript") 19 | (println ";; - http://github.com/kanaka/clojurescript") 20 | (println ";; - A port of the ClojureScript compiler to ClojureScript") 21 | (pep "(+ 1 2)") 22 | (pep "(defn sqr [x] (* x x))") 23 | (pep "(sqr 8)") 24 | (pep "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))") 25 | (pep "(unless false :yep :nope)") 26 | 27 | (let [readline (js/require "readline") 28 | rl (.createInterface readline js/process.stdin js/process.stdout)] 29 | (.setPrompt rl (repl/prompt)) 30 | (.prompt rl) 31 | (.on rl "line" (fn [line] 32 | (when (seq (filter #(not= " " %) line)) 33 | (repl/eval-print line) 34 | (println)) 35 | (.setPrompt rl (repl/prompt)) 36 | (.prompt rl))) 37 | (.on rl "close" (fn [] (.exit js/process 0))))) 38 | 39 | (set! *main-cli-fn* -main) 40 | 41 | -------------------------------------------------------------------------------- /src/cljs/webconsole.cljs: -------------------------------------------------------------------------------- 1 | (ns webconsole 2 | (:require [cljs.repl :as repl])) 3 | 4 | (defn start-prompt 5 | "Starts a new REPL prompt and optionally pre-populates user input field 6 | with initial-text." 7 | ([jqconsole initial-text] 8 | (let [prompt-label (str "\n" (repl/prompt)) 9 | continue-label (str (apply str (repeat (- (count prompt-label) 4) " ")) 10 | "...")] 11 | (.SetPromptLabel jqconsole prompt-label continue-label) 12 | (.Prompt jqconsole "true" 13 | (fn [input] 14 | (repl/eval-print input) 15 | (start-prompt jqconsole)) 16 | #(if (repl/complete-form? %) 17 | false 18 | 0)) 19 | (when-not (empty? initial-text) 20 | (.SetPromptText jqconsole initial-text))) 21 | jqconsole) 22 | ([jqconsole] (start-prompt jqconsole nil))) 23 | 24 | (defn cancel-input 25 | "Cancel the REPL prompt and write a message to output." 26 | [jqconsole message] 27 | (let [prompt-text (.GetPromptText jqconsole false)] 28 | (doto jqconsole 29 | .ClearPromptText 30 | .AbortPrompt 31 | (.Write message "jqconsole-output")) 32 | prompt-text)) 33 | 34 | (defn register-shortcuts [jqconsole shortcut-map] 35 | (doseq [[key callback] shortcut-map] 36 | (.RegisterShortcut jqconsole key callback))) 37 | 38 | (defn console 39 | "Create and initialize the REPL console, with a shortcut-map that 40 | maps keys to callback functions." 41 | [console-selector] 42 | (repl/init) 43 | (let [jqconsole 44 | (.jqconsole (js/$ console-selector) 45 | "ClojureScript-in-ClojureScript Web REPL" 46 | "\n>>> " 47 | "")] 48 | (.SetIndentWidth jqconsole 1) 49 | ;; Setup the print function 50 | (set! *out* #(.Write jqconsole %)) 51 | (set! *rtn* #(.Write jqconsole % "jqconsole-output")) 52 | (set! *err* #(.Write jqconsole % "jqconsole-message-error")) 53 | (set! *print-fn* #(*out* %1)) 54 | (start-prompt jqconsole))) -------------------------------------------------------------------------------- /src/cljs/webedit.cljs: -------------------------------------------------------------------------------- 1 | (ns webedit 2 | (:require [cljs.repl :as repl])) 3 | 4 | 5 | ;; file storage 6 | 7 | (defn store-item 8 | "Writes text at key in localStorage." 9 | [key text] 10 | (-> js/window .-localStorage (.setItem key text))) 11 | 12 | (defn load-item 13 | "Reads text at key in localStorage." 14 | [key] 15 | (-> js/window .-localStorage (.getItem key))) 16 | 17 | ;; editor keys 18 | 19 | (defn- map->js [m] 20 | (let [out (js-obj)] 21 | (doseq [[k v] m] 22 | (aset out (name k) v)) 23 | out)) 24 | 25 | (defn str-contains? [s x] 26 | (not= (.indexOf s x) -1)) 27 | 28 | (defn mac? [] 29 | (str-contains? (str (.-platform js/navigator)) "Mac")) 30 | 31 | (def command-prefix (if (mac?) "Cmd" "Ctrl")) 32 | 33 | (defn register-shortcuts [editor key-map] 34 | (let [js-key-map 35 | (->> (for [[k callback] key-map] 36 | [(str command-prefix "-" k) callback]) 37 | (into {}) 38 | map->js)] 39 | (.addKeyMap editor js-key-map))) 40 | 41 | ;; show/hide editor 42 | 43 | (def editor-visible (atom false)) 44 | 45 | (def editor-visible-key "__editor_visible") 46 | 47 | (defn update-editor-visibility [show?] 48 | (let [container (js/$ "#editor-container")] 49 | (if show? 50 | (.slideDown container 100) 51 | (.slideUp container 100)))) 52 | 53 | (defn store-editor-visibility [show?] 54 | (store-item editor-visible-key (str show?))) 55 | 56 | (defn update-link [show?] 57 | (.html (js/$ "#toggle-editor") 58 | (str (if show? "Hide" "Show") 59 | " file editor"))) 60 | 61 | (defn add-updating-watch [reference fun] 62 | (add-watch reference fun (fn [_ _ _ value] (fun value)))) 63 | 64 | (defn setup-editor-toggling [] 65 | (add-updating-watch editor-visible update-editor-visibility) 66 | (add-updating-watch editor-visible store-editor-visibility) 67 | (add-updating-watch editor-visible update-link) 68 | (.click (js/$ "#toggle-editor") #(swap! editor-visible not)) 69 | (reset! editor-visible (= "true" (load-item editor-visible-key)))) 70 | 71 | ;; main editor function 72 | 73 | (defn editor [] 74 | (let [eval-cmd (str command-prefix "-E")] 75 | (setup-editor-toggling) 76 | (.html (js/$ "#tiny-note") 77 | (str "Press " eval-cmd 78 | " to evaluate file in REPL.")) 79 | (doto 80 | (.fromTextArea js/CodeMirror 81 | (.getElementById js/document "editor") 82 | (map->js {:mode "clojure" 83 | :lineNumbers true 84 | :matchBrackets true})) 85 | (.setValue (or (load-item "scratch") 86 | ";; Develop your clojurescript program here"))))) 87 | -------------------------------------------------------------------------------- /src/cljs/webrepl.cljs: -------------------------------------------------------------------------------- 1 | (ns webrepl 2 | (:require [cljs.repl :as repl])) 3 | 4 | (def append-dom) 5 | 6 | (defn dom [o] 7 | (if (coll? o) 8 | (let [[tag attrs & body] o] 9 | (if (keyword? tag) 10 | (let [elem (.createElement js/document (name tag))] 11 | (when (map? attrs) 12 | (doseq [[k v] attrs] 13 | (when v (.setAttribute elem (name k) v)))) 14 | [(append-dom elem (if (map? attrs) body (cons attrs body)))]) 15 | (mapcat dom o))) 16 | (when o 17 | [(.createTextNode js/document (str o))]))) 18 | 19 | (defn append-dom [parent v] 20 | (doseq [i (dom v)] 21 | (.appendChild parent i)) 22 | parent) 23 | 24 | (defn repl-print [log text cls] 25 | (doseq [line (.split (str text) #"\n")] 26 | (append-dom log 27 | [:div {:class (str "cg " 28 | (when cls 29 | (str " " cls)))} 30 | line])) 31 | (set! (.-scrollTop log) (.-scrollHeight log))) 32 | 33 | (defn postexpr [log text] 34 | (append-dom log 35 | [:table 36 | [:tbody 37 | [:tr 38 | [:td {:class "cg"} (repl/prompt)] 39 | [:td (.replace text #"\n$" "")]]]])) 40 | 41 | (defn pep [log text] 42 | (postexpr log text) 43 | (repl/eval-print text)) 44 | 45 | (set! (.-onload js/window) (fn [] 46 | (repl/init) 47 | 48 | (let [log (.getElementById js/document "log") 49 | input (.getElementById js/document "input") 50 | status1 (.getElementById js/document "status1") 51 | status2 (.getElementById js/document "status2")] 52 | 53 | ;; Setup the print function 54 | ;; Setup the print function 55 | (set! *out* #(repl-print log % nil)) 56 | (set! *rtn* #(repl-print log % "rtn")) 57 | (set! *err* #(repl-print log % "err")) 58 | (set! *print-fn* #(*out* %1)) 59 | 60 | (println ";; ClojureScript") 61 | (append-dom log [:div {:class "cg"} 62 | ";; - " 63 | [:a {:href "http://github.com/kanaka/clojurescript"} 64 | "http://github.com/kanaka/clojurescript"]]) 65 | (println ";; - A port of the ClojureScript compiler to ClojureScript") 66 | (pep log "(+ 1 2)") 67 | (pep log "(defn sqr [x] (* x x))") 68 | (pep log "(sqr 8)") 69 | (pep log "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))") 70 | (pep log "(unless false :yep :nope)") 71 | 72 | (set! (.-onkeypress input) 73 | (fn [ev] 74 | (when (== (.-keyCode (or ev event)) 13) 75 | (let [line (.-value input)] 76 | (if (repl/complete-form? line) 77 | (do 78 | (pep log line) 79 | (js/setTimeout #(set! (.-value input) "") 0) 80 | (set! (.-visibility (.-style status1)) "visible") 81 | (set! (.-visibility (.-style status2)) "hidden") 82 | (set! (.-innerText (.getElementById js/document "ns")) (repl/prompt))) 83 | (do 84 | (set! (.-visibility (.-style status1)) "hidden") 85 | (set! (.-visibility (.-style status2)) "visible"))))))) 86 | 87 | (.focus input)))) 88 | -------------------------------------------------------------------------------- /src/cljs/webrepl2.cljs: -------------------------------------------------------------------------------- 1 | (ns webrepl 2 | (:require webconsole)) 3 | 4 | (.ready (js/jQuery js/document) 5 | (fn [] 6 | (webconsole/console "#console" {}) 7 | ;; print,evaluate,print some example forms 8 | ;(pep "(+ 1 2)") 9 | ;(pep "(let [sqr #(* % %)] (sqr 8))") 10 | ;(pep "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))") 11 | ;(pep "(unless false :yep :nope)") 12 | )) 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/cljs/webrepl3.cljs: -------------------------------------------------------------------------------- 1 | (ns webrepl 2 | (:require [cljs.repl :as repl] 3 | [webconsole :as webconsole] 4 | [webedit :as webedit])) 5 | 6 | (defn evaluate-file 7 | "Evaluates the editor's file in the REPL console." 8 | [editor console] 9 | (let [text (.getValue editor) 10 | prompt-text (webconsole/cancel-input console "Evaluating file...\n")] 11 | (repl/eval-print text) 12 | (webedit/store-item "scratch" text) 13 | (webconsole/start-prompt console prompt-text))) 14 | 15 | (defn start-app [] 16 | (let [editor (webedit/editor) 17 | console (webconsole/console "#console")] 18 | (webconsole/register-shortcuts console 19 | {"E" #(this-as this-console 20 | (evaluate-file editor this-console))}) 21 | (webedit/register-shortcuts editor 22 | {"E" #(evaluate-file % console)}))) 23 | 24 | (.ready (js/jQuery js/document) start-app) 25 | 26 | 27 | -------------------------------------------------------------------------------- /test/cljs/cljs/binding_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.binding-test 2 | (:require [cljs.binding-test-other-ns :as o])) 3 | 4 | (defn test-binding [] 5 | (binding [o/*foo* 2] 6 | (assert (= o/*foo* 2))) 7 | (assert (= o/*foo* 1))) -------------------------------------------------------------------------------- /test/cljs/cljs/binding_test_other_ns.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.binding-test-other-ns) 2 | 3 | (def ^:dynamic *foo* 1) -------------------------------------------------------------------------------- /test/cljs/cljs/import_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.import-test 2 | (:import goog.math.Long 3 | cljs.import-test.foo.Bar 4 | cljs.import-test.foo.Quux)) 5 | 6 | (defn test-import [] 7 | (assert (fn? Long)) 8 | (assert (.equals (Long. 4 6) (.add (Long. 1 2) (Long. 3 4)))) 9 | (assert (= "12" (Long/fromInt 12))) 10 | (assert (= 12 (.-x (Bar. 12)))) 11 | (assert (= 12 (.-x (Quux. 12))))) 12 | -------------------------------------------------------------------------------- /test/cljs/cljs/import_test/foo.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.import-test.foo) 2 | 3 | (defrecord Bar [x]) 4 | 5 | (deftype Quux [x]) 6 | -------------------------------------------------------------------------------- /test/cljs/cljs/letfn_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.letfn-test) 2 | 3 | (defn test-letfn [] 4 | (letfn [(ev? [x] 5 | (if (zero? x) 6 | true 7 | (od? (dec x)))) 8 | (od? [x] 9 | (if (zero? x) 10 | false 11 | (ev? (dec x))))] 12 | (assert (ev? 0)) 13 | (assert (ev? 10)) 14 | (assert (not (ev? 1))) 15 | (assert (not (ev? 11))) 16 | (assert (not (od? 0))) 17 | (assert (not (od? 10))) 18 | (assert (od? 1)) 19 | (assert (od? 11)))) 20 | -------------------------------------------------------------------------------- /test/cljs/cljs/macro_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.macro-test 2 | (:refer-clojure :exclude [==]) 3 | (:use-macros [cljs.macro-test.macros :only [==]])) 4 | 5 | (defn test-macros [] 6 | (assert (= (== 1 1) 2))) -------------------------------------------------------------------------------- /test/cljs/cljs/macro_test/macros.clj: -------------------------------------------------------------------------------- 1 | (ns cljs.macro-test.macros 2 | (:refer-clojure :exclude [==])) 3 | 4 | (defmacro == [a b] 5 | `(+ ~a ~b)) -------------------------------------------------------------------------------- /test/cljs/cljs/ns_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test 2 | (:refer-clojure :exclude [+]) 3 | (:require [cljs.ns-test.foo :refer [baz]]) 4 | (:use [cljs.ns-test.bar :only [quux]])) 5 | 6 | (def + -) 7 | 8 | (defn test-ns [] 9 | (assert (= 4 (clojure.core/+ 2 1 1))) 10 | (assert (= 0 (cljs.ns-test/+ 2 1 1))) 11 | (assert (= 0 (+ 2 1 1))) 12 | (assert (= 123 (baz))) 13 | (assert (= 123 (quux))) 14 | :ok) 15 | -------------------------------------------------------------------------------- /test/cljs/cljs/ns_test/bar.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test.bar) 2 | 3 | (defn quux [] 123) 4 | -------------------------------------------------------------------------------- /test/cljs/cljs/ns_test/foo.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.ns-test.foo) 2 | 3 | (defn baz [] 123) 4 | 5 | (def kw ::foo) 6 | 7 | (assert (= (str kw) ":cljs.ns-test.foo/foo")) 8 | -------------------------------------------------------------------------------- /test/cljs/cljs/quick.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.test.quick-tests) 2 | 3 | (defmacro quick-mac [x] x) 4 | (defmacro quick-unless [pred a b] `(if (not ~pred) ~a ~b)) 5 | 6 | (defn run-tests [] 7 | 8 | ;; Function reader 9 | (assert (= '(1) (#(list %1) 1))) 10 | (assert (= '(:a) (#(list %1) :a))) 11 | (assert (= 11 (#(+ 1 %) 10))) 12 | 13 | ;; Keywords 14 | (assert (= ':foo (keyword "foo"))) 15 | (assert (= ':bar/foo (keyword "bar" "foo"))) 16 | (assert (= *ns-sym* (symbol (namespace ::foo)))) 17 | 18 | (assert (= (namespace :foo) nil) "ns isn't nil") 19 | (assert (= (name :foo) "foo") "name isn't foo") 20 | (assert (= (name ::foo) "foo") "name isn't foo") 21 | (assert (= (namespace ::foo) (str *ns-sym*)) "wrong ns") 22 | 23 | (assert (= (namespace :1) nil) "ns isn't nil") 24 | (assert (= (name :1) \1) "name isn't 1") 25 | (assert (= (namespace ::2) (str *ns-sym*)) "wrong ns") 26 | (assert (= (name ::2) \2) "name isn't 2") 27 | 28 | ;; symbols 29 | (assert (= 'mysym (symbol "mysym"))) 30 | (assert (= 'bar/mysym (symbol "bar" "mysym"))) 31 | (assert (= true (symbol? 'blah))) 32 | (assert (= true (symbol? (symbol "blah")))) 33 | (assert (= false (symbol? :blah))) 34 | (assert (= 'blah (with-meta 'blah {:a 1}))) 35 | (assert (= {:a 1} (meta (with-meta 'blah {:a 1})))) 36 | (assert (= "cljs.user" (namespace (with-meta 'cljs.user/foo {:a 1})))) 37 | (assert (= "cljs.user" (namespace (with-meta (with-meta 'cljs.user/foo {:a 1}) {:b 2})))) 38 | 39 | ;; hexs 40 | (assert (= 0x7e7 2023) "hexs are read and parsed") 41 | 42 | ;; regex 43 | (assert (= '("/a" "/d" "/g") (re-seq #"/." "/abc/def/ghi"))) 44 | (assert (= 1 (count (take 2 (re-seq #"^$" ""))))) 45 | 46 | 47 | ;; arrays 48 | (assert (= '(3 6 9 12) (seq (let [a (array 1 2 3 4)] (amap a i ret (* 3 (aget a i))))))) 49 | (assert (= 25 (let [a (array 1 2 3 4 5)] (areduce a i ret 10 (+ ret (aget a i)))))) 50 | 51 | ;; unicode 52 | (assert (= "ü" "\u00fc") "unicodes are read properly") 53 | 54 | ;; Macros 55 | (assert (= 5 (quick-mac 5))) 56 | 57 | (assert (= :yep (quick-unless false :yep :nope))) 58 | (assert (= :nope (quick-unless true :yep :nope))) 59 | 60 | 61 | ;; destructuring 62 | (assert (= [4 3 2 1] (let [[a b] [1 2] {:keys [c d]} {:c 3 :d 4}] [d c b a]))) 63 | (assert (= [2 1] ((fn [a b] [b a]) 1 2))) 64 | (assert (= [2 1] ((fn [[a b]] [b a]) [1 2]))) 65 | (assert (= [20 10] ((fn [{:keys [a b]}] [b a]) {:a 10 :b 20}))) 66 | 67 | 68 | ;; with-out-str, time, regex, for 69 | (assert (= "01234" (with-out-str (doseq [n (range 5)] (print n))))) 70 | 71 | ;; try, throw 72 | (assert (= 3 (try (+ 1 2) (catch js/Error e :exc)))) 73 | (assert (= :exc (try (throw (js/Error. "err")) (catch js/Error e :exc)))) 74 | 75 | ;; .. 76 | (assert (= "6" (.. (array 4 5 6) (pop) (toString)))) 77 | 78 | ;; doto 79 | (assert (= "b" (aget (doto (new js/Array) (.push "a") (.push "b")) 1))) 80 | 81 | ;; memfn 82 | (assert (= '(:a "1" "[object Object]") (map (memfn toString) [:a 1 (new js/Object)]))) 83 | 84 | ;; letfn 85 | (assert (= [20 300] (letfn [(twice [x] (* 2 x)) (thrice [x] (* 3 x))] [(twice 10) (thrice 100)]))) 86 | 87 | ;; for 88 | (assert (= '([1 2] [3 6]) (for [x [1 2 3 4] :let [y (* x 2)] :when (odd? x)] [x y]))) 89 | 90 | ;; while 91 | (def w-a (atom 5)) 92 | (assert (= "5\n4\n3\n2\n1\n" (with-out-str (while (pos? @w-a) (do (println @w-a) (swap! w-a dec)))))) 93 | 94 | ;; doseq 95 | (assert (= "[1 2]\n[3 6]\n" (with-out-str (doseq [x [1 2 3 4] :let [y (* x 2)] :when (odd? x)] (println [x y]))))) 96 | 97 | ;; dotimes 98 | (assert (= "01234" (with-out-str (dotimes [n 5] (print n))))) 99 | 100 | ;; delay 101 | (assert (= 50 @(delay (* 10 5)))) 102 | 103 | ;; lazy-seq 104 | (defn positive-numbers ([] (positive-numbers 1)) ([n] (cons n (lazy-seq (positive-numbers (inc n)))))) 105 | (assert (= '(1 2 3 4 5) (take 5 (positive-numbers)))) 106 | 107 | ;; condp 108 | (defn tcp [v] (condp = v 1 "one" 2 "two" 3 "three" (str v " ???"))) 109 | (assert (= "three" (tcp 3))) 110 | (assert (= "4 ???" (tcp 4))) 111 | 112 | ;; case 113 | (defn tc [v] (case v "" "empty" "hello" "hello world" (str (count v) " chars"))) 114 | (assert (= "empty" (tc ""))) 115 | (assert (= "hello world" (tc "hello"))) 116 | (assert (= "4 chars" (tc "blah"))) 117 | (defn tc2 [v] (case v (1 3 5 7 9) "odd" (0 2 4 6 8) "even")) 118 | (assert (= "odd" (tc2 1))) 119 | (assert (= "even" (tc2 2))) 120 | (assert (= :exc (try (tc2 10) (catch js/Error e :exc)))) 121 | 122 | 123 | ;; deftype, defrecord, defprotocol 124 | (deftype MyType [] INext (-next [_] "mytype next")) 125 | (assert (= "mytype next" (next (MyType.)))) 126 | (deftype Fn-ish [a] IFn (-invoke [_] a)) 127 | (assert (= 1 ((Fn-ish. 1)))) 128 | 129 | (defrecord Banana [qty]) 130 | (defprotocol Fruit (-subtotal [item])) 131 | (extend-type Banana Fruit (-subtotal [item] (* 158 (:qty item)))) 132 | (def myb (Banana. 10)) 133 | (assert (= 10 (:qty myb))) 134 | (assert (= true (satisfies? Fruit myb))) 135 | (assert (= 1580 (-subtotal myb))) 136 | 137 | ;; extend-protocol 138 | (defprotocol Wonderful (-wonder [x])) 139 | (extend-protocol Wonderful 140 | nil (-wonder [x] "What a wonderful protocol!")) 141 | (assert (= "What a wonderful protocol!" (-wonder nil))) 142 | 143 | ;; reify 144 | (assert (= "foo-reified" (str (let [f "foo"] (reify Object (toString [this] (str f "-reified"))))))) 145 | (assert (= "reified ISeqable" (seq (reify ISeqable (-seq [_] "reified ISeqable"))))) 146 | 147 | 148 | ;; multimethods 149 | (defmulti bar (fn [x y] (type x))) 150 | (defmethod bar cljs.core/Symbol [x y] (str "got a symbol and " y)) 151 | (defmethod bar cljs.core/PersistentVector[x y] (str "got a vector and " y)) 152 | (assert (= "got a symbol and 1" (bar 'blah 1))) 153 | (assert (= "got a vector and 2" (bar [] 2))) 154 | 155 | ;; with-out-str, time, regex, for 156 | (re-find #"Elapsed time: \d* msecs" (with-out-str (time (apply str (for [n (range 100)] (with-out-str (print (format "%d/" n)))))))) 157 | 158 | (println "All tests finished successfully")) 159 | -------------------------------------------------------------------------------- /test/cljs/cljs/reader_test.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.reader-test 2 | (:require [cljs.reader :as reader] 3 | [goog.object :as o])) 4 | 5 | (deftype T [a b]) 6 | (defrecord R [a b]) 7 | 8 | (defn test-reader 9 | [] 10 | (assert (= 1 (reader/read-string "1"))) 11 | (assert (= 2 (reader/read-string "#_nope 2"))) 12 | (assert (= -1 (reader/read-string "-1"))) 13 | (assert (= -1.5 (reader/read-string "-1.5"))) 14 | (assert (= [3 4] (reader/read-string "[3 4]"))) 15 | (assert (= "foo" (reader/read-string "\"foo\""))) 16 | (assert (= :hello (reader/read-string ":hello"))) 17 | (assert (= 'goodbye (reader/read-string "goodbye"))) 18 | (assert (= #{1 2 3} (reader/read-string "#{1 2 3}"))) 19 | (assert (= '(7 8 9) (reader/read-string "(7 8 9)"))) 20 | (assert (= '(deref foo) (reader/read-string "@foo"))) 21 | (assert (= '(quote bar) (reader/read-string "'bar"))) 22 | (assert (= 'foo/bar (reader/read-string "foo/bar"))) 23 | (assert (= \a (reader/read-string "\\a"))) 24 | (assert (= {:tag 'String} (meta (reader/read-string "^String {:a 1}")))) 25 | (assert (= [:a 'b #{'c {:d [:e :f :g]}}] 26 | (reader/read-string "[:a b #{c {:d [:e :f :g]}}]"))) 27 | (assert (= :foo/bar (reader/read-string ":foo/bar"))) 28 | (assert (= nil (reader/read-string "nil"))) 29 | (assert (= true (reader/read-string "true"))) 30 | (assert (= false (reader/read-string "false"))) 31 | (assert (= "string" (reader/read-string "\"string\""))) 32 | (assert (= "escape chars \t \r \n \\ \" \b \f" (reader/read-string "\"escape chars \\t \\r \\n \\\\ \\\" \\b \\f\""))) 33 | 34 | ;; queue literals 35 | (assert (= cljs.core.PersistentQueue/EMPTY 36 | (reader/read-string "#queue []"))) 37 | 38 | (assert (= (-> cljs.core.PersistentQueue/EMPTY (conj 1)) 39 | (reader/read-string "#queue [1]"))) 40 | 41 | (assert (= (into cljs.core.PersistentQueue/EMPTY [1 2]) 42 | (reader/read-string "#queue [1 2]"))) 43 | 44 | ;; inst 45 | (let [est-inst (reader/read-string "#inst \"2010-11-12T13:14:15.666-05:00\"") 46 | utc-inst (reader/read-string "#inst \"2010-11-12T18:14:15.666-00:00\"")] 47 | 48 | (assert (= (.valueOf (js/Date. "2010-11-12T13:14:15.666-05:00")) 49 | (.valueOf est-inst))) 50 | 51 | (assert (= (.valueOf est-inst) 52 | (.valueOf (reader/read-string (pr-str est-inst))))) 53 | 54 | (assert (= (.valueOf est-inst) 55 | (.valueOf utc-inst))) 56 | 57 | (doseq [month (range 1 13) day (range 1 29) hour (range 1 23)] 58 | (let [s (str "#inst \"2010-" month "-" day "T" hour ":14:15.666-06:00\"")] 59 | (assert (= (-> s reader/read-string .valueOf) 60 | (-> s reader/read-string pr-str reader/read-string .valueOf)))))) 61 | 62 | ;; uuid literals 63 | (let [u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")] 64 | (assert (= u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\""))) 65 | 66 | (assert (not (identical? u (reader/read-string "#uuid \"550e8400-e29b-41d4-a716-446655440000\"")))) 67 | 68 | (assert (= u (-> u pr-str reader/read-string)))) 69 | 70 | ;; new tag parsers 71 | 72 | (reader/register-tag-parser! 'foo identity) 73 | 74 | (assert (= [1 2] (reader/read-string "#foo [1 2]"))) 75 | 76 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 77 | ;; Unicode Tests 78 | 79 | ; sample unicode strings, symbols, keywords 80 | (doseq [unicode 81 | ["اختبار" ; arabic 82 | "ทดสอบ" ; thai 83 | "こんにちは" ; japanese hiragana 84 | "你好" ; chinese traditional 85 | "אַ גוט יאָר" ; yiddish 86 | "cześć" ; polish 87 | "привет" ; russian 88 | 89 | ;; RTL languages skipped below because tricky to insert 90 | ;; ' and : at the "start" 91 | 92 | 'ทดสอบ 93 | 'こんにちは 94 | '你好 95 | 'cześć 96 | 'привет 97 | 98 | :ทดสอบ 99 | :こんにちは 100 | :你好 101 | :cześć 102 | :привет 103 | 104 | ;compound data 105 | {:привет :ru "你好" :cn} 106 | ]] 107 | (let [input (pr-str unicode) 108 | read (reader/read-string input)] 109 | (assert (= unicode read) 110 | (str "Failed to read-string \"" unicode "\" from: " input)))) 111 | 112 | ; unicode error cases 113 | (doseq [unicode-error 114 | ["\"abc \\ua\"" ; truncated 115 | "\"abc \\x0z ...etc\"" ; incorrect code 116 | "\"abc \\u0g00 ..etc\"" ; incorrect code 117 | ]] 118 | (let [r (try 119 | (reader/read-string unicode-error) 120 | :failed-to-throw 121 | (catch js/Error e :ok))] 122 | (assert (= r :ok) (str "Failed to throw reader error for: " unicode-error)))) 123 | 124 | :ok) 125 | -------------------------------------------------------------------------------- /test/cljs/cljs/top-level.cljs: -------------------------------------------------------------------------------- 1 | (ns cljs.top-level) 2 | 3 | (let [foo 1] 4 | (defn bar [] 5 | foo)) 6 | 7 | (let [foo 2] 8 | (defn baz [] 9 | foo)) 10 | 11 | (defn test [] 12 | (assert (= (bar) 1)) 13 | (assert (= (baz) 2))) -------------------------------------------------------------------------------- /test/cljs/clojure/data_test.cljs: -------------------------------------------------------------------------------- 1 | (ns clojure.data-test 2 | (:require [clojure.data :refer [diff]])) 3 | 4 | (defn test-data [] 5 | (assert (= [nil nil nil] (diff nil nil))) 6 | (assert (= [1 2 nil] (diff 1 2))) 7 | (assert (= [nil nil [1 2 3]] (diff [1 2 3] '(1 2 3)))) 8 | (assert (= [1 [:a :b] nil] (diff 1 [:a :b]))) 9 | (assert (= [{:a 1} :b nil] (diff {:a 1} :b))) 10 | (assert (= [:team #{:p1 :p2} nil] (diff :team #{:p1 :p2}))) 11 | (assert (= [{0 :a} [:a] nil] (diff {0 :a} [:a]))) 12 | (assert (= [nil [nil 2] [1]] (diff [1] [1 2]))) 13 | (assert (= [nil nil [1 2]] (diff [1 2] (into-array [1 2])))) 14 | (assert (= [#{:a} #{:b} #{:c :d}] (diff #{:a :c :d} #{:b :c :d}))) 15 | (assert (= [nil nil {:a 1}] (diff {:a 1} {:a 1}))) 16 | (assert (= [{:a #{2}} {:a #{4}} {:a #{3}}] (diff {:a #{2 3}} {:a #{3 4}}))) 17 | (assert (= [nil nil [1 2]] (diff [1 2] (into-array [1 2])))) 18 | (assert (= [nil nil [1 2]] (diff (into-array [1 2]) [1 2]))) 19 | (assert (= [{:a {:c [1]}} {:a {:c [0]}} {:a {:c [nil 2] :b 1}}] 20 | (diff {:a {:b 1 :c [1 2]}} {:a {:b 1 :c [0 2]}}))) 21 | (assert (= [{:a nil} {:a false} {:b nil :c false}] 22 | (diff {:a nil :b nil :c false} {:a false :b nil :c false})))) 23 | -------------------------------------------------------------------------------- /test/cljs/clojure/string_test.cljs: -------------------------------------------------------------------------------- 1 | (ns clojure.string-test 2 | (:require [clojure.string :as s])) 3 | 4 | (defn test-string 5 | [] 6 | ;; reverse 7 | (assert (= "" (s/reverse ""))) 8 | (assert (= "tab" (s/reverse "bat"))) 9 | ;; replace 10 | (assert (= "faabar" (s/replace "foobar" \o \a))) 11 | (assert (= "barbarbar" (s/replace "foobarfoo" "foo" "bar"))) 12 | (assert (= "FOObarFOO" (s/replace "foobarfoo" #"foo" s/upper-case))) 13 | (assert (= "barbar)foo" (s/replace "foo(bar)foo" "foo(" "bar"))) 14 | ;; join 15 | (assert (= "" (s/join nil))) 16 | (assert (= "" (s/join []))) 17 | (assert (= "1" (s/join [1]))) 18 | (assert (= "12" (s/join [1 2]))) 19 | (assert (= "1,2,3" (s/join \, [1 2 3]))) 20 | (assert (= "" (s/join \, []))) 21 | (assert (= "1 and-a 2 and-a 3" (s/join " and-a " [1 2 3]))) 22 | ;; capitalize 23 | (assert (= "FOOBAR" (s/upper-case "Foobar"))) 24 | (assert (= "foobar" (s/lower-case "FooBar"))) 25 | (assert (= "Foobar" (s/capitalize "foobar"))) 26 | (assert (= "Foobar" (s/capitalize "FOOBAR"))) 27 | ;; split 28 | (assert (= ["a" "b"] (s/split "a-b" #"-"))) 29 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" -1))) 30 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 0))) 31 | (assert (= ["a-b-c"] (s/split "a-b-c" #"-" 1))) 32 | (assert (= ["a" "b-c"] (s/split "a-b-c" #"-" 2))) 33 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 3))) 34 | (assert (= ["a" "b" "c"] (s/split "a-b-c" #"-" 4))) 35 | (assert (vector? (s/split "abc" #"-"))) 36 | (assert (= ["a-b-c"] (s/split "a-b-c" #"x" 2))) 37 | ;; split-lines 38 | (let [result (s/split-lines "one\ntwo\r\nthree")] 39 | (assert (= ["one" "two" "three"] result)) 40 | (assert (vector? result))) 41 | (assert (= (list "foo") (s/split-lines "foo"))) 42 | ;; blank 43 | (assert (s/blank? nil)) 44 | (assert (s/blank? "")) 45 | (assert (s/blank? " ")) 46 | (assert (s/blank? " \t \n \r ")) 47 | (assert (not (s/blank? " foo "))) 48 | ;; escape 49 | (assert (= "<foo&bar>" 50 | (s/escape "" {\& "&" \< "<" \> ">"}))) 51 | (assert (= " \\\"foo\\\" " 52 | (s/escape " \"foo\" " {\" "\\\""}))) 53 | (assert (= "faabor" 54 | (s/escape "foobar" {\a \o, \o \a}))) 55 | ;; replace-first 56 | (assert (= "barbarfoo" (s/replace-first "foobarfoo" "foo" "bar"))) 57 | (assert (= "barbarfoo" (s/replace-first "foobarfoo" #"foo" "bar"))) 58 | (assert (= "z.ology" (s/replace-first "zoology" \o \.))) 59 | (assert (= "FOObarfoo" (s/replace-first "foobarfoo" #"foo" s/upper-case))) 60 | ;; trim 61 | (assert (= "foo " (s/triml " foo "))) 62 | (assert (= "" (s/triml " "))) 63 | (assert (= " foo" (s/trimr " foo "))) 64 | (assert (= "" (s/trimr " "))) 65 | (assert (= "foo" (s/trim " foo \r\n"))) 66 | ;; trim-newline 67 | (assert (= "foo" (s/trim-newline "foo\n"))) 68 | (assert (= "foo" (s/trim-newline "foo\r\n"))) 69 | (assert (= "foo" (s/trim-newline "foo"))) 70 | (assert (= "foo\r " (s/trim-newline "foo\r "))) 71 | (assert (= "" (s/trim-newline ""))) 72 | :ok) 73 | 74 | (comment 75 | 76 | (deftest char-sequence-handling 77 | (are [result f args] (let [[^CharSequence s & more] args] 78 | (= result (apply f (StringBuffer. s) more))) 79 | "paz" s/reverse ["zap"] 80 | "foo:bar" s/replace ["foo-bar" \- \:] 81 | "ABC" s/replace ["abc" #"\w" s/upper-case] 82 | "faa" s/replace ["foo" #"o" (StringBuffer. "a")] 83 | "baz::quux" s/replace-first ["baz--quux" #"--" "::"] 84 | "baz::quux" s/replace-first ["baz--quux" (StringBuffer. "--") (StringBuffer. "::")] 85 | "zim-zam" s/replace-first ["zim zam" #" " (StringBuffer. "-")] 86 | "Pow" s/capitalize ["POW"] 87 | "BOOM" s/upper-case ["boom"] 88 | "whimper" s/lower-case ["whimPER"] 89 | ["foo" "bar"] s/split ["foo-bar" #"-"] 90 | "calvino" s/trim [" calvino "] 91 | "calvino " s/triml [" calvino "] 92 | " calvino" s/trimr [" calvino "] 93 | "the end" s/trim-newline ["the end\r\n\r\r\n"] 94 | true s/blank? [" "] 95 | ["a" "b"] s/split-lines ["a\nb"] 96 | "fa la la" s/escape ["fo lo lo" {\o \a}])) 97 | ) 98 | -------------------------------------------------------------------------------- /test/cljs/foo/ns_shadow_test.cljs: -------------------------------------------------------------------------------- 1 | (ns foo.ns-shadow-test) 2 | 3 | (defn bar [] 1) 4 | 5 | (defn quux [foo] 6 | (+ (foo.ns-shadow-test/bar) foo)) 7 | 8 | (defn test-shadow [] 9 | (assert (= (quux 2) 3))) -------------------------------------------------------------------------------- /test/cljs/test_runner.cljs: -------------------------------------------------------------------------------- 1 | (ns test-runner 2 | (:require [cljs.core-test :as core-test] 3 | [cljs.reader-test :as reader-test] 4 | [cljs.binding-test :as binding-test] 5 | [cljs.ns-test :as ns-test] 6 | [clojure.string-test :as string-test] 7 | [clojure.data-test :as data-test] 8 | [cljs.macro-test :as macro-test] 9 | [cljs.letfn-test :as letfn-test] 10 | [foo.ns-shadow-test :as ns-shadow-test] 11 | [cljs.top-level :as top-level])) 12 | 13 | (set! *print-fn* js/print) 14 | 15 | (core-test/test-stuff) 16 | (reader-test/test-reader) 17 | (string-test/test-string) 18 | (data-test/test-data) 19 | (binding-test/test-binding) 20 | (ns-test/test-ns) 21 | (macro-test/test-macros) 22 | (letfn-test/test-letfn) 23 | (ns-shadow-test/test-shadow) 24 | (top-level/test) 25 | 26 | (println "Tests completed without exception") 27 | 28 | 29 | -------------------------------------------------------------------------------- /web/blank.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/blank.gif -------------------------------------------------------------------------------- /web/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname ${0}) 4 | 5 | echo "Building webrepl.js" 6 | time ../bin/cljsc ../src/cljs/webrepl.cljs > webrepl.js 7 | -------------------------------------------------------------------------------- /web/build2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname ${0}) 4 | 5 | echo "Building webrepl2.js" 6 | time ../bin/cljsc ../src/cljs/webrepl2.cljs > webrepl2.js 7 | -------------------------------------------------------------------------------- /web/build3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd $(dirname ${0}) 4 | 5 | echo "Building webrepl3.js" 6 | time ../bin/cljsc ../src/cljs/webrepl3.cljs > webrepl3.js 7 | -------------------------------------------------------------------------------- /web/dots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/dots.png -------------------------------------------------------------------------------- /web/images/bg-body.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/images/bg-body.png -------------------------------------------------------------------------------- /web/images/bg-rule.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/images/bg-rule.png -------------------------------------------------------------------------------- /web/images/github-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/images/github-icon.png -------------------------------------------------------------------------------- /web/jsrepl.css: -------------------------------------------------------------------------------- 1 | .code { 2 | font-family: Monaco,monospace; 3 | font-size: 10pt; 4 | } 5 | .pad { 6 | height: 20em; 7 | } 8 | #log { 9 | height: 25em; 10 | overflow: auto; 11 | white-space: pre-wrap; 12 | } 13 | #log table { 14 | border-collapse: collapse; 15 | } 16 | #log td { 17 | vertical-align: top; 18 | padding: 0; 19 | } 20 | .ns { 21 | float: left; 22 | } 23 | .cg { 24 | color: #00b; 25 | } 26 | .err { 27 | color: #b00; 28 | } 29 | .rtn { 30 | color: #000; 31 | } 32 | textarea#input { 33 | padding: 0; 34 | margin: 0; 35 | border: none; 36 | width: 75%; 37 | height: 6em; 38 | background: #f3f3f3; 39 | } 40 | -------------------------------------------------------------------------------- /web/jsrepl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ClojureScript REPL 5 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 |
    16 |
    17 |
    18 |
    19 | cljs.user=> 
    20 | 21 | 22 |
    23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-black-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-black-webfont.eot -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-black-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-black-webfont.ttf -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-black-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-black-webfont.woff -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-bold-webfont.eot -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-bold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-bold-webfont.ttf -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-bold-webfont.woff -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-regular-webfont.eot -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-regular-webfont.ttf -------------------------------------------------------------------------------- /web/stylesheets/fonts/exo-regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kanaka/clojurescript/10c8bc0b5adfd6f129641d6c6838c8369cdcb1c4/web/stylesheets/fonts/exo-regular-webfont.woff -------------------------------------------------------------------------------- /web/stylesheets/himera.css: -------------------------------------------------------------------------------- 1 | /* Additional Classes --------------------------------------------- */ 2 | 3 | .source { 4 | font-family: "ExoRegular"; 5 | font-size: 18px; 6 | height: 31px; 7 | margin-top: 20px; 8 | text-align: right; 9 | } 10 | 11 | .source img { 12 | margin-left: 5px; 13 | vertical-align: sub; 14 | } 15 | 16 | .source a { 17 | text-decoration: none; 18 | } 19 | 20 | .rule { 21 | background: url(../images/bg-rule.png); 22 | height: 12px; 23 | clear: both; 24 | margin-top: 20px; 25 | margin-bottom: 20px; 26 | } 27 | 28 | .cheat-box-container { 29 | background-color: rgba(213,207,180,0.4); 30 | border-radius: 5px; 31 | -moz-border-radius: 5px; 32 | margin-top: 20px; 33 | } 34 | 35 | .cheat-box { 36 | padding: 20px; 37 | } 38 | 39 | table { 40 | font-family: monospace; 41 | margin-top: 20px; 42 | width: 100%; 43 | } 44 | 45 | td { 46 | padding: 3px; 47 | } 48 | 49 | .row-one { 50 | background-color: #f2efe4; 51 | } 52 | 53 | .row-label { 54 | color: #666; 55 | font-family: "ExoBold"; 56 | text-transform: uppercase; 57 | } 58 | 59 | .footer-logo { 60 | font-size: 18px; 61 | font-family: "ExoBlack"; 62 | text-transform: uppercase; 63 | color: #8f4732; 64 | } 65 | 66 | ul.footer-links { 67 | float: right; 68 | } 69 | 70 | .footer-links li { 71 | font-family: "ExoRegular"; 72 | font-size: 14px; 73 | display: inline; 74 | list-style-type: none; 75 | margin-left: 10px; 76 | text-transform: uppercase; 77 | } 78 | 79 | .footer-links li a { 80 | color: #327a8e; 81 | text-decoration: none; 82 | } 83 | 84 | .footer-links li a:hover { 85 | color: #333; 86 | } 87 | 88 | .tiny-note { 89 | font-size: small; 90 | } 91 | 92 | /* Editor ---------------------------------------------- */ 93 | 94 | .CodeMirror { 95 | position: relative; 96 | height: 320px; 97 | background: #fbfbf8; 98 | border-radius: 5px; 99 | -moz-border-radius: 5px; 100 | border: 1px solid #d5ceb4; 101 | } 102 | 103 | /* Console --------------------------------------------- */ 104 | 105 | #console { 106 | position: relative; 107 | height: 220px; 108 | background: #fbfbf8; 109 | border-radius: 5px; 110 | -moz-border-radius: 5px; 111 | border: 1px solid #d5ceb4; 112 | } 113 | 114 | /* Console --------------------------------------------- */ 115 | /* The console container element */ 116 | #console { 117 | position: relative; 118 | height: 320px; 119 | background-color:#fbfbf8;; 120 | } 121 | /* The inner console element. */ 122 | .jqconsole { 123 | background: #fbfbf8; 124 | border-radius: 5px; 125 | -moz-border-radius: 5px; 126 | border: 1px solid #d5ceb4; 127 | padding: 10px; 128 | 129 | white-space: pre-wrap; 130 | word-wrap: break-word; 131 | } 132 | /* The cursor. */ 133 | .jqconsole-cursor { 134 | font-weight: normal; 135 | font-family:monospace; 136 | background-color: #000; 137 | } 138 | /* The cursor color when the console looses focus. */ 139 | .jqconsole-blurred .jqconsole-cursor { 140 | font-weight: normal; 141 | font-family:monospace; 142 | background-color: #7F7F7F; 143 | } 144 | /* The current prompt text color */ 145 | .jqconsole-prompt { 146 | font-weight: normal; 147 | font-family:monospace; 148 | color: #000; 149 | } 150 | /* The command history */ 151 | .jqconsole-old-prompt { 152 | font-weight: normal; 153 | font-family:monospace; 154 | color: #000; 155 | } 156 | /* The text color when in input mode. */ 157 | .jqconsole-input { 158 | font-weight: normal; 159 | font-family:monospace; 160 | color: #000; 161 | } 162 | /* Previously entered input. */ 163 | .jqconsole-old-input { 164 | color: #000; 165 | font-weight: normal; 166 | font-family:monospace; 167 | } 168 | /* The text color of the output. */ 169 | .jqconsole-output { 170 | font-weight: normal; 171 | font-family:monospace; 172 | color: #000; 173 | } 174 | 175 | .jqconsole-inner { 176 | /*width:580px;*/ 177 | height:200px; 178 | margin: 10px 10px; 179 | overflow:auto; 180 | text-align:left; 181 | } 182 | 183 | .jqconsole-message-value { 184 | color:#333; 185 | font-family:monospace; 186 | padding:0.1em; 187 | } 188 | 189 | .jqconsole-prompt-box { 190 | color:#444; font-family:monospace; 191 | } 192 | 193 | .jqconsole-focus span.jquery-console-cursor { 194 | background:#333; color:#eee; font-weight:bold; 195 | } 196 | 197 | .jqconsole-message-error { 198 | font-family:sans-serif; 199 | font-weight:bold; 200 | padding:0.1em; 201 | color:#ef0505; 202 | } 203 | 204 | .jqconsole-message-success { 205 | color:#187718; font-family:monospace; 206 | padding:0.1em; 207 | } 208 | 209 | 210 | .ebnf { 211 | color:#444; font-family:monospace; 212 | text-transform: uppercase; 213 | } 214 | 215 | .doc-link { 216 | font-size: 0.65em; 217 | text-decoration: none; 218 | } 219 | 220 | /* Synonym Styles */ 221 | 222 | #himera-synonym h1 { 223 | margin-left: 10px; 224 | } 225 | 226 | #himera-synonym h1 div { 227 | font-size: 16px; 228 | color: black; 229 | } 230 | 231 | #himera-synonym h4, 232 | #himera-synonym h5 { 233 | margin-left: 10px; 234 | } 235 | 236 | #himera-synonym .cheat-box-container { 237 | margin-top: 0px; 238 | background-color: rgb(255, 250, 240); 239 | border: 1px solid #ccc; 240 | box-sizing: border-box; 241 | -webkit-box-sizing: border-box; 242 | -moz-box-sizing: border-box; 243 | -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); 244 | -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); 245 | -o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); 246 | -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); 247 | box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); 248 | } 249 | 250 | #himera-synonym pre { 251 | font-size: 13px; 252 | font-family: monospace; 253 | } 254 | 255 | .syn-section { 256 | clear: both; 257 | float: left; 258 | margin-bottom: 20px; 259 | } 260 | 261 | #himera-synonym table { 262 | margin: 0; 263 | padding: 0; 264 | } 265 | 266 | #himera-synonym .container { 267 | margin: 0; 268 | overflow-x: hidden !important; 269 | overflow-y: hidden !important; 270 | } 271 | 272 | h1 a { 273 | text-decoration: none; 274 | color: inherit; 275 | } 276 | 277 | h1 a:visited { 278 | text-decoration: none; 279 | color: inherit; 280 | } 281 | -------------------------------------------------------------------------------- /web/stylesheets/layout.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Skeleton V1.0.2 3 | * Copyright 2011, Dave Gamache 4 | * www.getskeleton.com 5 | * Free to use under the MIT license. 6 | * http://www.opensource.org/licenses/mit-license.php 7 | * 5/20/2011 8 | */ 9 | 10 | /* Table of Content 11 | ================================================== 12 | #Site Styles 13 | #Page Styles 14 | #Media Queries 15 | #Font-Face */ 16 | 17 | /* #Site Styles 18 | ================================================== */ 19 | 20 | /* #Page Styles 21 | ================================================== */ 22 | 23 | /* #Media Queries 24 | ================================================== */ 25 | 26 | /* iPad Portrait/Browser */ 27 | @media only screen and (min-width: 768px) and (max-width: 991px) {} 28 | 29 | /* Mobile/Browser */ 30 | @media only screen and (max-width: 767px) {} 31 | 32 | /* Mobile Landscape/Browser */ 33 | @media only screen and (min-width: 480px) and (max-width: 767px) {} 34 | 35 | /* Anything smaller than standard 960 */ 36 | @media only screen and (max-width: 959px) { 37 | h1 { 38 | font-size: 48px; 39 | } 40 | h2 { 41 | font-size: 16px; 42 | float: none; 43 | line-height: 150%; 44 | margin-top: -10px; 45 | } 46 | h3 { 47 | font-size: 18px; 48 | } 49 | h4 { 50 | font-size: 14px; 51 | } 52 | .source p { 53 | font-size: 16px; 54 | } 55 | } 56 | 57 | /* iPad Portrait Only */ 58 | @media only screen and (min-width: 768px) and (max-width: 991px) and (max-device-width: 1000px) {} 59 | 60 | /* Mobile Only */ 61 | @media only screen and (max-width: 767px) and (max-device-width: 1000px) {} 62 | 63 | /* Mobile Landscape Only */ 64 | @media only screen and (min-width: 480px) and (max-width: 767px) and (max-device-width: 1000px) {} 65 | 66 | 67 | /* Fonts --------------------------------------------- */ 68 | 69 | @font-face { 70 | font-family: 'ExoBold'; 71 | src: url('fonts/exo-bold-webfont.eot'); 72 | src: url('fonts/exo-bold-webfont.eot?#iefix') format('embedded-opentype'), 73 | url('fonts/exo-bold-webfont.woff') format('woff'), 74 | url('fonts/exo-bold-webfont.ttf') format('truetype'), 75 | url('fonts/exo-bold-webfont.svg#ExoBold') format('svg'); 76 | font-weight: normal; 77 | font-style: normal; 78 | } 79 | 80 | @font-face { 81 | font-family: 'ExoBlack'; 82 | src: url('fonts/exo-black-webfont.eot'); 83 | src: url('fonts/exo-black-webfont.eot?#iefix') format('embedded-opentype'), 84 | url('fonts/exo-black-webfont.woff') format('woff'), 85 | url('fonts/exo-black-webfont.ttf') format('truetype'), 86 | url('fonts/exo-black-webfont.svg#ExoBlack') format('svg'); 87 | font-weight: normal; 88 | font-style: normal; 89 | } 90 | 91 | @font-face { 92 | font-family: 'ExoRegular'; 93 | src: url('fonts/exo-regular-webfont.eot'); 94 | src: url('fonts/exo-regular-webfont.eot?#iefix') format('embedded-opentype'), 95 | url('fonts/exo-regular-webfont.woff') format('woff'), 96 | url('fonts/exo-regular-webfont.ttf') format('truetype'), 97 | url('fonts/exo-regular-webfont.svg#ExoRegular') format('svg'); 98 | font-weight: normal; 99 | font-style: normal; 100 | } -------------------------------------------------------------------------------- /web/vendor/shBrushJScript.js: -------------------------------------------------------------------------------- 1 | ;(function() 2 | { 3 | // CommonJS 4 | SyntaxHighlighter = SyntaxHighlighter || (typeof require !== 'undefined'? require('shCore').SyntaxHighlighter : null); 5 | 6 | function Brush() 7 | { 8 | var keywords = 'break case catch continue ' + 9 | 'default delete do else false ' + 10 | 'for function if in instanceof ' + 11 | 'new null return super switch ' + 12 | 'this throw true try typeof var while with' 13 | ; 14 | 15 | var r = SyntaxHighlighter.regexLib; 16 | 17 | this.regexList = [ 18 | { regex: r.multiLineDoubleQuotedString, css: 'string' }, // double quoted strings 19 | { regex: r.multiLineSingleQuotedString, css: 'string' }, // single quoted strings 20 | { regex: r.singleLineCComments, css: 'comments' }, // one line comments 21 | { regex: r.multiLineCComments, css: 'comments' }, // multiline comments 22 | { regex: /\s*#.*/gm, css: 'preprocessor' }, // preprocessor tags like #region and #endregion 23 | { regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword' } // keywords 24 | ]; 25 | 26 | this.forHtmlScript(r.scriptScriptTags); 27 | }; 28 | 29 | Brush.prototype = new SyntaxHighlighter.Highlighter(); 30 | Brush.aliases = ['js', 'jscript', 'javascript']; 31 | 32 | SyntaxHighlighter.brushes.JScript = Brush; 33 | 34 | // CommonJS 35 | typeof(exports) != 'undefined' ? exports.Brush = Brush : null; 36 | })(); 37 | -------------------------------------------------------------------------------- /web/vendor/shThemeMarginalia.css: -------------------------------------------------------------------------------- 1 | /** 2 | * http://alexgorbatchev.com/SyntaxHighlighter/donate.html 3 | * 4 | * @version 5 | * 3.0.83 (July 02 2010) 6 | * 7 | * @copyright 8 | * Copyright (C) 2004-2010 Alex Gorbatchev. 9 | * 10 | * @license 11 | * Dual licensed under the MIT and GPL licenses. 12 | */ 13 | .syntaxhighlighter { 14 | background-color: transparent !important; 15 | } 16 | .syntaxhighlighter .line.alt1 { 17 | background-color: transparent !important; 18 | } 19 | .syntaxhighlighter .line.alt2 { 20 | background-color: transparent !important; 21 | } 22 | .syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 { 23 | background-color: #c3defe !important; 24 | } 25 | .syntaxhighlighter .line.highlighted.number { 26 | color: white !important; 27 | } 28 | .syntaxhighlighter table caption { 29 | color: black !important; 30 | } 31 | .syntaxhighlighter .gutter { 32 | color: #787878 !important; 33 | } 34 | .syntaxhighlighter .gutter .line { 35 | border-right: 3px solid #d4d0c8 !important; 36 | } 37 | .syntaxhighlighter .gutter .line.highlighted { 38 | background-color: #d4d0c8 !important; 39 | color: white !important; 40 | } 41 | .syntaxhighlighter.printing .line .content { 42 | border: none !important; 43 | } 44 | .syntaxhighlighter.collapsed { 45 | overflow: visible !important; 46 | } 47 | .syntaxhighlighter.collapsed .toolbar { 48 | color: #3f5fbf !important; 49 | background: white !important; 50 | border: 1px solid #d4d0c8 !important; 51 | } 52 | .syntaxhighlighter.collapsed .toolbar a { 53 | color: #3f5fbf !important; 54 | } 55 | .syntaxhighlighter.collapsed .toolbar a:hover { 56 | color: #aa7700 !important; 57 | } 58 | .syntaxhighlighter .toolbar { 59 | color: #a0a0a0 !important; 60 | background: #d4d0c8 !important; 61 | border: none !important; 62 | } 63 | .syntaxhighlighter .toolbar a { 64 | color: #a0a0a0 !important; 65 | } 66 | .syntaxhighlighter .toolbar a:hover { 67 | color: red !important; 68 | } 69 | .syntaxhighlighter .plain, .syntaxhighlighter .plain a { 70 | color: black !important; 71 | } 72 | .syntaxhighlighter .comments, .syntaxhighlighter .comments a { 73 | color: #3f5fbf !important; 74 | } 75 | .syntaxhighlighter .string, .syntaxhighlighter .string a { 76 | color: #2a00ff !important; 77 | } 78 | .syntaxhighlighter .keyword { 79 | color: #7f0055 !important; 80 | } 81 | .syntaxhighlighter .preprocessor { 82 | color: #646464 !important; 83 | } 84 | .syntaxhighlighter .variable { 85 | color: #aa7700 !important; 86 | } 87 | .syntaxhighlighter .value { 88 | color: #009900 !important; 89 | } 90 | .syntaxhighlighter .functions { 91 | color: #ff1493 !important; 92 | } 93 | .syntaxhighlighter .constants { 94 | color: #0066cc !important; 95 | } 96 | .syntaxhighlighter .script { 97 | font-weight: bold !important; 98 | color: #7f0055 !important; 99 | background-color: none !important; 100 | } 101 | .syntaxhighlighter .color1, .syntaxhighlighter .color1 a { 102 | color: gray !important; 103 | } 104 | .syntaxhighlighter .color2, .syntaxhighlighter .color2 a { 105 | color: #ff1493 !important; 106 | } 107 | .syntaxhighlighter .color3, .syntaxhighlighter .color3 a { 108 | color: red !important; 109 | } 110 | 111 | .syntaxhighlighter .xml .keyword { 112 | color: #3f7f7f !important; 113 | font-weight: normal !important; 114 | } 115 | .syntaxhighlighter .xml .color1, .syntaxhighlighter .xml .color1 a { 116 | color: #7f007f !important; 117 | } 118 | .syntaxhighlighter .xml .string { 119 | font-style: italic !important; 120 | color: #2a00ff !important; 121 | } 122 | 123 | .clojure.syntaxhighlighter .invalid { 124 | background-color: #FAA !important; 125 | } 126 | 127 | .clojure.syntaxhighlighter .quoted { 128 | font-style: italic !important; 129 | } 130 | 131 | .syntaxhighlighter .clojure.variable, 132 | .syntaxhighlighter .clojure.symbol, 133 | .syntaxhighlighter .clojure.value 134 | { 135 | color: #006060 !important; 136 | } 137 | 138 | .syntaxhighlighter .clojure.string { 139 | color: #55B !important; 140 | } 141 | 142 | .syntaxhighlighter .clojure.functions { 143 | color: black !important; 144 | } 145 | 146 | .syntaxhighlighter .clojure.color1 { 147 | color: #666 !important; 148 | } 149 | 150 | .syntaxhighlighter .clojure.color3 { 151 | color: #900 !important; 152 | } 153 | 154 | .syntaxhighlighter .clojure.constants { 155 | color: #1A734D !important; 156 | } 157 | 158 | --------------------------------------------------------------------------------