├── .gitignore
├── README.md
├── UNLICENSE
├── javadoc-import.el
├── javadoc-lookup.el
├── maven-fetch.el
└── webcache
└── http+++docs.oracle.com+javase+8+docs+api+.v4
/.gitignore:
--------------------------------------------------------------------------------
1 | *.elc
2 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # javadoc-lookup
2 |
3 | This package provides a `javadoc-lookup` function for quickly looking
4 | up Javadoc for any library from within Emacs, optionally integrating
5 | with Maven. A browser is launched to view the documentation.
6 |
7 | `javadoc-lookup` is not bound to any key by default, so you may want
8 | to add this to your initialization file,
9 |
10 | ```el
11 | (global-set-key (kbd "C-h j") 'javadoc-lookup)
12 | ````
13 |
14 | An index for the core Java classes (i.e. java.*) is provided
15 | built-in. Beyond this, you'll want to tell javadoc-lookup what else
16 | you would like to have indexed. There are two ways to do this. You can
17 | point it to the root of a library's documentation on your
18 | filesystem. For example (the first entry here will replace the
19 | built-in index),
20 |
21 | ```el
22 | (javadoc-add-roots "/usr/share/doc/openjdk-8-jdk/api"
23 | "~/src/project/doc")
24 | ```
25 |
26 | Or, more conveniently, you can **fetch and index documentation from
27 | Maven**! This is done by specifying an artifact as a sequence of three
28 | strings/symbols: `[groupId artifactId version]`. For example,
29 |
30 | ```el
31 | (javadoc-add-artifacts [org.lwjgl.lwjg lwjgl "2.8.2"]
32 | [com.nullprogram native-guide "0.2"]
33 | [org.apache.commons commons-math3 "3.0"])
34 | ```
35 |
36 | This feature requires that you have Maven and the command-line unzip
37 | utility installed on your system. The initial fetch is slow but Emacs
38 | will operate from its own cache after that.
39 |
40 | ## Import functions
41 |
42 | Two functions for managing Java imports is provided: `javadoc-add-import`
43 | and `javadoc-sort-imports`. The former integrates with the javadoc-lookup
44 | index to provide completions.
45 |
46 | ## History
47 |
48 | This package obsoletes my previous java-docs package. Use this one
49 | instead.
50 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/javadoc-import.el:
--------------------------------------------------------------------------------
1 | ;;; javadoc-import.el --- quickly add import statements in Java
2 |
3 | ;; This is free and unencumbered software released into the public domain.
4 |
5 | ;;; Commentary:
6 |
7 | ;; Provides the functions `javadoc-add-import' and `javadoc-sort-imports'.
8 |
9 | ;;; Code:
10 |
11 | (require 'javadoc-lookup)
12 |
13 | (defvar jdl/import-regexp "^import "
14 | "Regular expression for finding import statements.")
15 |
16 | (defvar jdl/package-regexp "^package "
17 | "Regular expression for finding package statements.")
18 |
19 | (defun jdl/in-package ()
20 | "Return t if this source has a package statement."
21 | (save-excursion
22 | (goto-char (point-min))
23 | (and (search-forward-regexp jdl/package-regexp nil t) t)))
24 |
25 | (defun jdl/has-import ()
26 | "Return t if this source has at least one import statement."
27 | (save-excursion
28 | (goto-char (point-min))
29 | (and (search-forward-regexp jdl/import-regexp nil t) t)))
30 |
31 | (defun jdl/goto-first-import ()
32 | "Move cursor to the first import statement."
33 | (goto-char (point-min))
34 | (search-forward-regexp jdl/import-regexp)
35 | (move-beginning-of-line nil)
36 | (point))
37 |
38 | (defun jdl/goto-last-import ()
39 | "Move cursor to the first import statement."
40 | (goto-char (point-max))
41 | (search-backward-regexp jdl/import-regexp)
42 | (move-end-of-line nil)
43 | (forward-char)
44 | (point))
45 |
46 | ;;;###autoload
47 | (defun javadoc-sort-imports ()
48 | "Sort the imports in the import section in proper order."
49 | (interactive)
50 | (when (jdl/has-import)
51 | (save-excursion
52 | (sort-lines nil (jdl/goto-first-import) (jdl/goto-last-import)))))
53 |
54 | ;;;###autoload
55 | (define-obsolete-function-alias
56 | 'sort-java-imports 'javadoc-sort-imports "1.1.0")
57 |
58 | ;;;###autoload
59 | (defun javadoc-add-import ()
60 | "Insert an import statement at import section at the top of the file."
61 | (interactive)
62 | (let ((class (jdl/completing-read)))
63 | (save-excursion
64 | (if (jdl/has-import)
65 | (progn
66 | (jdl/goto-first-import)
67 | (insert "import " class ";\n")
68 | (javadoc-sort-imports))
69 | (progn
70 | (goto-char (point-min))
71 | (when (jdl/in-package)
72 | (search-forward-regexp jdl/package-regexp)
73 | (move-end-of-line nil)
74 | (forward-char)
75 | (insert "\n"))
76 | (insert "import " class ";\n"))))))
77 |
78 | ;;;###autoload
79 | (define-obsolete-function-alias
80 | 'add-java-import 'javadoc-add-import "1.1.0")
81 |
82 | (provide 'javadoc-import)
83 |
84 | ;;; javadoc-import.el ends here
85 |
--------------------------------------------------------------------------------
/javadoc-lookup.el:
--------------------------------------------------------------------------------
1 | ;;; javadoc-lookup.el --- Javadoc Emacs integration with Maven
2 |
3 | ;; This is free and unencumbered software released into the public domain.
4 |
5 | ;; Author: Christopher Wellons
6 | ;; URL: https://github.com/skeeto/javadoc-lookup
7 | ;; Version: 1.1.0
8 | ;; Package-Requires: ((cl-lib "0.3"))
9 |
10 | ;;; Commentary:
11 |
12 | ;; This package provides a quick way to look up any Javadoc
13 | ;; documentation from Emacs, using your browser to display the
14 | ;; information. Since the mechanism is already there, java-import.el
15 | ;; provides the completing function `javadoc-add-import' for quickly
16 | ;; adding an import to a source file.
17 |
18 | ;; This mode stores database and index information in
19 | ;; `javadoc-lookup-cache-dir'.
20 |
21 | ;; Indexing:
22 |
23 | ;; Give `javadoc-lookup' your root Java documentation directories. It
24 | ;; will scan and index those directories, exposing them to
25 | ;; `javadoc-lookup'. Multiple directories can be provided at once, for
26 | ;; example,
27 |
28 | ;; (javadoc-add-roots "/usr/share/doc/openjdk-6-jdk/api"
29 | ;; "~/src/project/doc")
30 |
31 | ;; If you haven't loaded the core Java Javadoc, it will load a
32 | ;; pre-made database for you, which indexes the official website.
33 |
34 | ;; More conveniently, you can list Maven artifacts to index,
35 |
36 | ;; (javadoc-add-artifacts [org.lwjgl.lwjgl lwjgl "2.8.2"]
37 | ;; [com.nullprogram native-guide "0.2"]
38 | ;; [org.apache.commons commons-math3 "3.0"])
39 |
40 | ;; Browser configuration:
41 |
42 | ;; To view documentation, the browser is launched with `browse-url'.
43 | ;; This may require setting `browse-url-browser-function' in order to
44 | ;; select the proper browser. For example,
45 |
46 | ;; (setq browse-url-browser-function 'browse-url-firefox)
47 |
48 | ;;; Code:
49 |
50 | (require 'cl-lib)
51 | (require 'ido)
52 |
53 | (defgroup javadoc-lookup ()
54 | "Lookup Java library documentation from Emacs."
55 | :group 'java)
56 |
57 | ;; Customization variables
58 |
59 | (defcustom javadoc-lookup-cache-dir (locate-user-emacs-file "javadoc-cache")
60 | "Filesystem location to store index and cache database.")
61 |
62 | (defcustom javadoc-lookup-completing-read-function #'ido-completing-read
63 | "Function used when performing a minibuffer read.")
64 |
65 | ;; Internal variables
66 |
67 | (defvar jdl/data-root (file-name-directory load-file-name)
68 | "The location of data for javadoc-loookup.")
69 |
70 | (defvar jdl/index (make-hash-table :test 'equal)
71 | "Full index of for documentation lookups.")
72 |
73 | (defvar jdl/cache-version ".v4"
74 | "Cache version, so it won't load old caches.")
75 |
76 | (defvar jdl/loaded ()
77 | "List of already-loaded documentation directories.")
78 |
79 | ;; Indexing Functions
80 |
81 | (defun jdl/dir-truename (dir)
82 | "Return the truename for DIR, which always has a trailing slash."
83 | (expand-file-name (concat dir "/")))
84 |
85 | (defun jdl/clear ()
86 | "Clear all in-memory javadoc-lookup cache and indexes."
87 | (setq jdl/loaded nil)
88 | (setq jdl/index (make-hash-table :test 'equal)))
89 |
90 | (defun jdl/loaded-p (dir)
91 | "Return t if DIR has already been loaded."
92 | (member dir jdl/loaded))
93 |
94 | (defun jdl/cache-name (dir)
95 | "Get the cache file name for DIR."
96 | (concat (replace-regexp-in-string "[/:]" "+" dir) jdl/cache-version))
97 |
98 | (defun jdl/load-cache (cache-file)
99 | "Load a cache from disk."
100 | (let ((require-final-newline nil))
101 | (with-current-buffer (find-file-noselect cache-file)
102 | (goto-char (point-min))
103 | (jdl/add-hash (read (current-buffer)))
104 | (kill-buffer))))
105 |
106 | (defun jdl/save-cache (cache-file hash)
107 | "Save a cache to the disk."
108 | (unless (file-exists-p javadoc-lookup-cache-dir)
109 | (make-directory javadoc-lookup-cache-dir t))
110 | (with-temp-file cache-file
111 | (let ((print-circle t)
112 | (print-level nil)
113 | (print-length nil))
114 | (prin1 hash (current-buffer)))))
115 |
116 | (defun jdl/add (dir)
117 | "Index DIR, using the cache if available."
118 | (let ((cache-file (expand-file-name (jdl/cache-name dir)
119 | javadoc-lookup-cache-dir)))
120 | (if (file-exists-p cache-file)
121 | (jdl/load-cache cache-file)
122 | (let ((hash (make-hash-table :test 'equal)))
123 | (jdl/index dir hash)
124 | (jdl/save-cache cache-file hash)
125 | (jdl/add-hash hash))))
126 | (add-to-list 'jdl/loaded dir))
127 |
128 | (defun jdl/add-hash (hash)
129 | "Combine HASH into the main index hash."
130 | (maphash (lambda (key val) (puthash key val jdl/index)) hash))
131 |
132 | (cl-defun jdl/index (dir hash &optional (root (list dir "file://")))
133 | "Index the documentation in DIR into HASH, based on ROOT."
134 | (let* ((list (directory-files dir t "^[^.]"))
135 | (files (cl-remove-if 'file-directory-p list))
136 | (dirs (cl-remove-if-not 'file-directory-p list)))
137 | (dolist (file files)
138 | (jdl/add-file file hash root))
139 | (dolist (dir dirs)
140 | (when (not (string-equal "class-use" (file-name-nondirectory dir)))
141 | (jdl/index dir hash root)))))
142 |
143 | (defun jdl/add-file (fullfile hash root)
144 | "Add a file to the index if it looks like a class."
145 | (let* ((file (file-name-nondirectory fullfile))
146 | (ext (file-name-extension fullfile))
147 | (class (file-name-sans-extension file))
148 | (rel (substring fullfile (length (cl-first root))))
149 | (fullclass (cl-substitute ?. ?/ (file-name-sans-extension rel)))
150 | (case-fold-search nil))
151 | (when (and (string-equal ext "html")
152 | (string-match "^[A-Z].+" class))
153 | (puthash fullclass (cons rel root) hash))))
154 |
155 | (defun javadoc-add-roots (&rest directories)
156 | "Index and load all documentation under DIRECTORIES."
157 | (cl-loop for directory in directories
158 | for truename = (jdl/dir-truename directory)
159 | unless (jdl/loaded-p truename)
160 | do (jdl/add truename)))
161 |
162 | (defun jdl/web (&rest urls)
163 | "Load pre-cached web indexes for URLS."
164 | (dolist (url (cl-remove-if 'jdl/loaded-p urls))
165 | (let* ((rel-cache-file (concat "webcache/" (jdl/cache-name url)))
166 | (cache-file (expand-file-name rel-cache-file jdl/data-root)))
167 | (if (file-exists-p cache-file)
168 | (jdl/load-cache cache-file)
169 | (error "No cache for %s" url)))))
170 |
171 | ;; Lookup functions
172 |
173 | (defun jdl/core-indexed-p ()
174 | "Return true if the JRE Javadoc has been indexed. The class
175 | java.net.URL is used for this test, since it's simple and should
176 | always be there."
177 | (gethash "java.net.URL" jdl/index))
178 |
179 | (defun jdl/get-class-list ()
180 | (cl-loop for class being the hash-keys of jdl/index
181 | collect class into classes
182 | finally (return (cl-sort classes #'< :key #'length))))
183 |
184 | (defun jdl/completing-read ()
185 | "Query the user for a class name."
186 | (unless (jdl/core-indexed-p)
187 | (ignore-errors ; Provide *something* useful, if needed
188 | (jdl/web "http://docs.oracle.com/javase/8/docs/api/")))
189 | (let ((default (thing-at-point 'symbol))
190 | (classes (jdl/get-class-list)))
191 | (funcall javadoc-lookup-completing-read-function "Class: "
192 | classes nil nil nil nil
193 | (and default (cl-find default classes :test #'string-match)))))
194 |
195 | ;;;###autoload
196 | (defun javadoc-lookup (name)
197 | "Lookup based on class name."
198 | (interactive (list (jdl/completing-read)))
199 | (let ((file (apply #'concat (reverse (gethash name jdl/index)))))
200 | (when file (browse-url file))))
201 |
202 | (provide 'javadoc-lookup)
203 |
204 | ;;; javadoc-lookup.el ends here
205 |
--------------------------------------------------------------------------------
/maven-fetch.el:
--------------------------------------------------------------------------------
1 | ;;; maven-fetch.el --- Fetch Javadoc artifacts from the Maven repository
2 |
3 | ;; This is free and unencumbered software released into the public domain.
4 |
5 | ;;; Commentary:
6 |
7 | ;; This code adds support to javadoc-lookup by automatically fetching
8 | ;; and indexing documentation artifacts from the Maven repository. It
9 | ;; requires Maven and the command-line unzip utility installed on your
10 | ;; system. If these are not in your $PATH, the variables
11 | ;; `maven-program-name' and `unzip-program-name' will need to be set.
12 |
13 | ;; An artifact is specified by a sequence (list or vector) of three
14 | ;; strings: [groupId artifactId version]. For example,
15 |
16 | ;; ["org.apache.commons" "commons-math3" "3.0"]
17 |
18 | ;; In your Emacs initialization file, call `javadoc-add-artifact' with
19 | ;; your desired artifacts. They are only downloaded, unzipped, and
20 | ;; indexed -- a slow process -- the very first time. Each startup
21 | ;; after that, Emacs will work entirely from a cache (fast).
22 |
23 | ;;; Code:
24 |
25 | (require 'cl-lib)
26 | (require 'javadoc-lookup)
27 |
28 | (defcustom maven-program-name "mvn"
29 | "Path to the Maven executable."
30 | :group 'external)
31 |
32 | (defcustom unzip-program-name "unzip"
33 | "Path to the unzip executable."
34 | :group 'external)
35 |
36 | (defvar maven-fetch-command
37 | "org.apache.maven.plugins:maven-dependency-plugin:2.6:get"
38 | "Long command name for the Maven dependency fetch plugin.")
39 |
40 | (defun maven-fetch-artifact-jar (artifact)
41 | "Return the cache filename for ARTIFACT."
42 | (let ((file (format "%s-%s-javadoc.jar" (elt artifact 1) (elt artifact 2))))
43 | (expand-file-name file (jdl/dir-truename javadoc-lookup-cache-dir))))
44 |
45 | (defun maven-fetch-unpacked-path (artifact)
46 | "Return the unpacked directory name for ARTIFACT."
47 | (expand-file-name (format "%s/%s" (elt artifact 0) (elt artifact 1))
48 | (jdl/dir-truename javadoc-lookup-cache-dir)))
49 |
50 | (cl-defun maven-fetch (artifact)
51 | "Use maven to fetch ARTIFACT into the cache directory,
52 | returning true on success."
53 | (let ((jarfile (maven-fetch-artifact-jar artifact)))
54 | (if (file-exists-p jarfile)
55 | (format "Artifact %s already downloaded" artifact)
56 | (let ((artifact-arg "-Dartifact=%s:%s:%s:javadoc"))
57 | (message "Maven is fetching %s ..." artifact)
58 | (zerop
59 | (call-process maven-program-name nil nil nil
60 | maven-fetch-command
61 | (format "-Ddest=%s" jarfile)
62 | (apply #'format artifact-arg
63 | (cl-coerce artifact 'list))))))))
64 |
65 | (defun maven-fetch-unpack (artifact)
66 | "Unpack an artifact in the javadoc-lookup cache directory,
67 | returning the destination directory. Throws an error on any failure."
68 | (let* ((jarfile (maven-fetch-artifact-jar artifact))
69 | (destdir (maven-fetch-unpacked-path artifact)))
70 | (if (not (file-exists-p jarfile))
71 | (error "Could not find artifact jar file: %s." jarfile)
72 | (if (file-exists-p destdir)
73 | destdir
74 | (message "Unpacking %s ..." (file-name-nondirectory jarfile))
75 | (mkdir destdir t)
76 | (if (call-process unzip-program-name nil nil nil jarfile "-d" destdir)
77 | destdir
78 | (delete-directory destdir t)
79 | (error "Failed to unpack %s" jarfile))))))
80 |
81 | ;;;###autoload
82 | (defun javadoc-add-artifacts (&rest artifacts)
83 | "Add Maven repository artifacts to the javadoc-lookup index.
84 | An artifact is specified by a sequence of three strings:
85 | [groupId artifactId version]."
86 | (dolist (artifact artifacts)
87 | (if (maven-fetch artifact)
88 | (javadoc-add-roots (maven-fetch-unpack artifact))
89 | (error "Failed to fetch %s" artifact))))
90 |
91 | (provide 'maven-fetch)
92 |
93 | ;;; maven-fetch.el ends here
94 |
--------------------------------------------------------------------------------