-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
javadoc.clj
102 lines (93 loc) · 4.3 KB
/
javadoc.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
; Copyright (c) Rich Hickey. All rights reserved.
; The use and distribution terms for this software are covered by the
; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
; which can be found in the file epl-v10.html at the root of this distribution.
; By using this software in any fashion, you are agreeing to be bound by
; the terms of this license.
; You must not remove this notice, or any other, from this software.
(ns
^{:author "Christophe Grand, Stuart Sierra",
:doc "A repl helper to quickly open javadocs."}
clojure.java.javadoc
(:use [clojure.java.browse :only (browse-url)] )
(:import
(java.io File)))
(def ^:dynamic *feeling-lucky-url* "http://www.google.com/search?btnI=I%27m%20Feeling%20Lucky&q=allinurl:")
(def ^:dynamic *feeling-lucky* true)
(def ^:dynamic *local-javadocs* (ref (list)))
(def ^:dynamic *core-java-api*
(case (System/getProperty "java.specification.version")
"1.8" "http://docs.oracle.com/javase/8/docs/api/"
"9" "http://docs.oracle.com/javase/9/docs/api/"
"10" "http://docs.oracle.com/javase/10/docs/api/"
"11" "https://docs.oracle.com/en/java/javase/11/docs/api/%s/"
"12" "https://docs.oracle.com/en/java/javase/12/docs/api/%s/"
"13" "https://docs.oracle.com/en/java/javase/13/docs/api/%s/"
"14" "https://docs.oracle.com/en/java/javase/14/docs/api/%s/"
"15" "https://docs.oracle.com/en/java/javase/15/docs/api/%s/"
"http://docs.oracle.com/javase/8/docs/api/"))
(def ^:dynamic *remote-javadocs*
(ref (sorted-map
"com.google.common." "http://google.github.io/guava/releases/23.0/api/docs/"
"java." *core-java-api*
"javax." *core-java-api*
"org.ietf.jgss." *core-java-api*
"org.omg." *core-java-api*
"org.w3c.dom." *core-java-api*
"org.xml.sax." *core-java-api*
"org.apache.commons.codec." "http://commons.apache.org/proper/commons-codec/apidocs/"
"org.apache.commons.io." "http://commons.apache.org/proper/commons-io/javadocs/api-release/"
"org.apache.commons.lang." "http://commons.apache.org/proper/commons-lang/javadocs/api-2.6/"
"org.apache.commons.lang3." "http://commons.apache.org/proper/commons-lang/javadocs/api-release/")))
(defn add-local-javadoc
"Adds to the list of local Javadoc paths."
{:added "1.2"}
[path]
(dosync (commute *local-javadocs* conj path)))
(defn add-remote-javadoc
"Adds to the list of remote Javadoc URLs. package-prefix is the
beginning of the package name that has docs at this URL."
{:added "1.2"}
[package-prefix url]
(dosync (commute *remote-javadocs* assoc package-prefix url)))
(defn- fill-in-module-name [^String url ^String classname]
;; The getModule method was introduced in JDK 9, and did not exist
;; in earlier JDK versions. Avoid calling it unless its result is
;; needed.
(if (.contains url "%s")
(let [klass (Class/forName classname)
module-name (.getName (.getModule klass))]
(format url module-name))
url))
(defn- javadoc-url
"Searches for a URL for the given class name. Tries
*local-javadocs* first, then *remote-javadocs*. Returns a string."
{:tag String,
:added "1.2"}
[^String classname]
(let [file-path (.replace classname \. File/separatorChar)
url-path (.replace classname \. \/)]
(if-let [file ^File (first
(filter #(.exists ^File %)
(map #(File. (str %) (str file-path ".html"))
@*local-javadocs*)))]
(-> file .toURI str)
;; If no local file, try remote URLs:
(or (some (fn [[prefix url]]
(when (.startsWith classname prefix)
(str (fill-in-module-name url classname)
url-path ".html")))
@*remote-javadocs*)
;; if *feeling-lucky* try a web search
(when *feeling-lucky* (str *feeling-lucky-url* url-path ".html"))))))
(defn javadoc
"Opens a browser window displaying the javadoc for the argument.
Tries *local-javadocs* first, then *remote-javadocs*."
{:added "1.2"}
[class-or-object]
(let [^Class c (if (instance? Class class-or-object)
class-or-object
(class class-or-object))]
(if-let [url (javadoc-url (.getName c))]
(browse-url url)
(println "Could not find Javadoc for" c))))