Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Smart Clojure/ClojureScript code sharing

branch: master

Fetching latest commit…

Octocat-spinner-32-eaf2f5

Cannot retrieve the latest commit at this time

Octocat-spinner-32 src
Octocat-spinner-32 test
Octocat-spinner-32 .gitignore
Octocat-spinner-32 LICENSE
Octocat-spinner-32 README.markdown
Octocat-spinner-32 project.clj
Octocat-spinner-32 scratch.clj
README.markdown
            /$$                
           | $$                
  /$$$$$$$ | $$    /$$   /$$   /$$
 /$$_____/ | $$   |__/  |  $$ /$$/
| $$       | $$    /$$   \  $$$$/ 
| $$       | $$   | $$    >$$  $$ 
|  $$$$$$$ | $$   | $$   /$$/\  $$
 \_______/ |__/   | $$  |__/  \__/
             /$$  | $$          
            |  $$$$$$/  Your code is, like, data, bro.        
             \______/           

Cljx is a Lein plugin that emits Clojure and ClojureScript code from a single metadata-annotated codebase.

To use it, add it to your project.clj:

:plugins [[com.keminglabs/cljx "0.2.0"]]
:cljx {:builds [{:source-paths ["src/cljx"]
                 :output-path ".generated/clj"
                 :rules cljx.rules/clj-rules}

                {:source-paths ["src/cljx"]
                 :output-path ".generated/cljs"
                 :extension "cljs"
                 :include-meta true
                 :rules cljx.rules/cljs-rules}]}

Can be run "once" or "auto", in which case it will watch all source-paths for changes to .cljx files. Defaults to "once".

Add

:hooks [cljx.hooks]

to automatically run cljx before cutting a JAR.

The included clj and cljs rule sets will remove forms marked with platform-specific metadata and rename protocols as appropriate. E.g., the .cljx source containing

^:clj (ns c2.maths
        (:use [c2.macros :only [combine-with]]))
^:cljs (ns c2.maths
         (:use-macros [c2.macros :only [combine-with]]))

(defn ^:clj sin [x] (Math/sin x))
(defn ^:cljs sin [x] (.sin js/Math x))

(reify
  clojure.lang.IFn
  (invoke [_ x] (inc x)))

will, when run through cljx.rules/cljs-rules, yield:

(ns c2.maths
  (:use-macros [c2.macros :only [combine-with]]))

(defn sin [x] (.sin js/Math x))

(reify
  IFn
  (invoke [_ x] (inc x)))

The value associated with :rules should be a symbol naming a var containing the rules to use for that build. cljx.rules/cljs-rules and cljx.rules/clj-rules are provided as a convenience, but you can extend those (or replace them entirely). For example, a namespace on your classpath like this defines some rules:

(ns my.rules
  (:require [kibit.rules.util :refer (compile-rule defrules)]))

(defrules rules
  [(+ ?x 1) (inc ?x)]
  [(- ?x 1) (dec ?x)])

Now you can use those rules in a cljx build like so:

:rules my.rules/rules

The var's namespace will be automatically loaded by cljx (i.e. no need to do so manually via the :injections key in your project.clj).

Forms that are converted into :cljx.core/exclude will be excluded from the output. See Kibit for more info on writing rules, and C2 for a project that uses .cljx heavily.

Clojure is a hosted language

Cljx does not try to hide implementation differences between host platforms. Clojure has ints, floats, longs, &c., ClojureScript has number; Clojure regular expressions act differently than ClojureScript regular expressions, because they are different.

Cljx only tries to unify Clojure/ClojureScript abstractions when it makes sense. E.g., converting clojure.lang.IFn into IFn when generating ClojureScript.

Misc

Emacs users, want syntax highlighting? Add to your emacs config: (add-to-list 'auto-mode-alist '("\\.cljx\\'" . clojure-mode)).

Todo

  • CLJS: Remove docstrings from namespaces.

Thanks

@jonase & @ohpauleez for kibit @swannodette for core.logic

Something went wrong with that request. Please try again.