rlm@10: ; Copyright (c) Rich Hickey. All rights reserved. rlm@10: ; The use and distribution terms for this software are covered by the rlm@10: ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) rlm@10: ; which can be found in the file epl-v10.html at the root of this distribution. rlm@10: ; By using this software in any fashion, you are agreeing to be bound by rlm@10: ; the terms of this license. rlm@10: ; You must not remove this notice, or any other, from this software. rlm@10: (ns rlm@10: ^{:author "Christophe Grand, Stuart Sierra", rlm@10: :doc "A repl helper to quickly open javadocs."} rlm@10: clojure.java.javadoc rlm@10: (:use [clojure.java.browse :only (browse-url)] ) rlm@10: (:import rlm@10: (java.io File))) rlm@10: rlm@10: (def *feeling-lucky-url* "http://www.google.com/search?btnI=I%27m%20Feeling%20Lucky&q=allinurl:") rlm@10: (def *feeling-lucky* true) rlm@10: rlm@10: (def *local-javadocs* (ref (list))) rlm@10: rlm@10: (def *core-java-api* rlm@10: (if (= "1.5" (System/getProperty "java.specification.version")) rlm@10: "http://java.sun.com/j2se/1.5.0/docs/api/" rlm@10: "http://java.sun.com/javase/6/docs/api/")) rlm@10: rlm@10: (def *remote-javadocs* rlm@10: (ref (sorted-map rlm@10: "java." *core-java-api* rlm@10: "javax." *core-java-api* rlm@10: "org.ietf.jgss." *core-java-api* rlm@10: "org.omg." *core-java-api* rlm@10: "org.w3c.dom." *core-java-api* rlm@10: "org.xml.sax." *core-java-api* rlm@10: "org.apache.commons.codec." "http://commons.apache.org/codec/api-release/" rlm@10: "org.apache.commons.io." "http://commons.apache.org/io/api-release/" rlm@10: "org.apache.commons.lang." "http://commons.apache.org/lang/api-release/"))) rlm@10: rlm@10: (defn add-local-javadoc rlm@10: "Adds to the list of local Javadoc paths." rlm@10: {:added "1.2"} rlm@10: [path] rlm@10: (dosync (commute *local-javadocs* conj path))) rlm@10: rlm@10: (defn add-remote-javadoc rlm@10: "Adds to the list of remote Javadoc URLs. package-prefix is the rlm@10: beginning of the package name that has docs at this URL." rlm@10: {:added "1.2"} rlm@10: [package-prefix url] rlm@10: (dosync (commute *remote-javadocs* assoc package-prefix url))) rlm@10: rlm@10: (defn- javadoc-url rlm@10: "Searches for a URL for the given class name. Tries rlm@10: *local-javadocs* first, then *remote-javadocs*. Returns a string." rlm@10: {:tag String, rlm@10: :added "1.2"} rlm@10: [^String classname] rlm@10: (let [file-path (.replace classname \. File/separatorChar) rlm@10: url-path (.replace classname \. \/)] rlm@10: (if-let [file ^File (first rlm@10: (filter #(.exists ^File %) rlm@10: (map #(File. (str %) (str file-path ".html")) rlm@10: @*local-javadocs*)))] rlm@10: (-> file .toURI str) rlm@10: ;; If no local file, try remote URLs: rlm@10: (or (some (fn [[prefix url]] rlm@10: (when (.startsWith classname prefix) rlm@10: (str url url-path ".html"))) rlm@10: @*remote-javadocs*) rlm@10: ;; if *feeling-lucky* try a web search rlm@10: (when *feeling-lucky* (str *feeling-lucky-url* url-path ".html")))))) rlm@10: rlm@10: (defn javadoc rlm@10: "Opens a browser window displaying the javadoc for the argument. rlm@10: Tries *local-javadocs* first, then *remote-javadocs*." rlm@10: {:added "1.2"} rlm@10: [class-or-object] rlm@10: (let [^Class c (if (instance? Class class-or-object) rlm@10: class-or-object rlm@10: (class class-or-object))] rlm@10: (if-let [url (javadoc-url (.getName c))] rlm@10: (browse-url url) rlm@10: (println "Could not find Javadoc for" c))))