PageRenderTime 56ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 0ms

/src/net/cgrand/dispatch.clj

https://github.com/cgrand/sandbox
Clojure | 58 lines | 37 code | 11 blank | 10 comment | 0 complexity | 402066d9dae4e1df4e6a40ff6ad42d51 MD5 | raw file
  1. ; Copyright (c) Christophe Grand, 2009. 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
  5. ; distribution.
  6. ; By using this software in any fashion, you are agreeing to be bound by
  7. ; the terms of this license.
  8. ; You must not remove this notice, or any other, from this software.
  9. (ns net.cgrand.dispatch
  10. (:use [clojure.contrib.test-is :as test-is :only [set-test with-test is]]))
  11. (defn add-route [root path handler]
  12. (assoc-in root (concat path [:handler]) handler))
  13. (defn remove-route [root path]
  14. (add-route root path nil))
  15. ;; default root for the mount/unmount macros and dispatch fn
  16. (def *root* (ref {}))
  17. (defn- step-dispatch [roots segment]
  18. (mapcat #(when %1
  19. (map %1 [segment :else])) roots))
  20. (defn dispatch
  21. "Returns the handler for the specified path (segments) or nil."
  22. ([segments] (dispatch @*root* segments))
  23. ([root segments]
  24. (when-let [handler (first
  25. (drop-while nil?
  26. (map :handler
  27. (reduce step-dispatch [root] segments))))]
  28. (handler segments))))
  29. (defn dispatch-url
  30. [#^String location]
  31. (dispatch (map #(java.net.URLDecoder/decode % "UTF-8") (rest (.split location "/")))))
  32. ;; macros
  33. (defmacro mount
  34. "Adds a route (a vector of strings and symbols) to the specified root
  35. (defaults to *root*)."
  36. ([route form] `(mount *root* ~route ~form))
  37. ([root route form]
  38. (let [_ (gensym "_")
  39. args (map #(if (string? %) _ %) route)
  40. segments (map #(if (string? %) % :else) route)
  41. f `(fn [[~@args]] ~form)]
  42. `(commute ~root add-route [~@segments] ~f))))
  43. (defmacro unmount
  44. ([route form] `(unmount *root* ~route ~form))
  45. ([root route form]
  46. (let [segments (map #(if (string? %) % :else) route)]
  47. `(commute ~root remove-route [~@segments]))))