From 4bd08103d254cdd695388e750a199d77ad35aeff Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sat, 1 Mar 2014 08:42:05 +0200 Subject: [PATCH 01/11] Make cider-doc-handler work synchronously, and rename it --- cider-interaction.el | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/cider-interaction.el b/cider-interaction.el index 406a9db4a..8cbac1206 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -1225,20 +1225,23 @@ if there is no symbol at point, or if QUERY is non-nil." (ido-mode (cider-ido-read-var nrepl-buffer-ns callback)) (t (funcall callback (read-from-minibuffer prompt symbol-name)))))) -(defun cider-doc-handler (symbol) - "Create a handler to lookup documentation for SYMBOL." - (let ((form (format "(clojure.repl/doc %s)" symbol)) - (doc-buffer (cider-popup-buffer cider-doc-buffer t))) - (cider-tooling-eval form - (cider-popup-eval-out-handler doc-buffer) - nrepl-buffer-ns))) +(defun cider-doc-for (symbol) + "Look up documentation for SYMBOL using inlined Clojure code." + (let* ((form (format "(clojure.repl/doc %s)" symbol)) + (doc-buffer (cider-popup-buffer cider-doc-buffer t)) + (response + (cider-tooling-eval-sync form nrepl-buffer-ns)) + (str + (or (plist-get response :stdout) + (plist-get response :stderr)))) + (cider-emit-into-popup-buffer doc-buffer str))) (defun cider-doc (query) "Open a window with the docstring for the given QUERY. Defaults to the symbol at point. With prefix arg or no symbol under point, prompts for a var." (interactive "P") - (cider-read-symbol-name "Symbol: " 'cider-doc-handler query)) + (cider-read-symbol-name "Symbol: " 'cider-doc-for query)) (defun cider-src-handler (symbol) "Create a handler to lookup source for SYMBOL." From e33f072e65fa6d0c2c3bcbb1b73475c9f8148c5c Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 05:57:34 +0200 Subject: [PATCH 02/11] Extract `cider-doc-buffer-for' And use it in `cider-complete-at-point'. --- cider-interaction.el | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/cider-interaction.el b/cider-interaction.el index 8cbac1206..0038fe32f 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -622,8 +622,8 @@ otherwise dispatch to internal completion function." (when (and sap (not (in-string-p))) (let ((bounds (bounds-of-thing-at-point 'symbol))) (list (car bounds) (cdr bounds) - (completion-table-dynamic #'cider-dispatch-complete-symbol)))))) - + (completion-table-dynamic #'cider-dispatch-complete-symbol) + :company-doc-buffer #'cider-doc-buffer-for))))) ;;; JavaDoc Browsing ;;; Assumes local-paths are accessible in the VM. @@ -1225,23 +1225,30 @@ if there is no symbol at point, or if QUERY is non-nil." (ido-mode (cider-ido-read-var nrepl-buffer-ns callback)) (t (funcall callback (read-from-minibuffer prompt symbol-name)))))) -(defun cider-doc-for (symbol) - "Look up documentation for SYMBOL using inlined Clojure code." +(defun cider-doc-buffer-for (symbol) + "Return buffer with documentation for SYMBOL." (let* ((form (format "(clojure.repl/doc %s)" symbol)) - (doc-buffer (cider-popup-buffer cider-doc-buffer t)) + (doc-buffer (cider-make-popup-buffer cider-doc-buffer)) (response (cider-tooling-eval-sync form nrepl-buffer-ns)) (str (or (plist-get response :stdout) (plist-get response :stderr)))) - (cider-emit-into-popup-buffer doc-buffer str))) + (cider-emit-into-popup-buffer doc-buffer str) + doc-buffer)) + +(defun cider-doc-lookup (symbol) + "Look up documentation for SYMBOL." + (with-current-buffer (cider-doc-buffer-for symbol) + (setq buffer-read-only t) + (cider-popup-buffer-display (current-buffer) t))) (defun cider-doc (query) "Open a window with the docstring for the given QUERY. Defaults to the symbol at point. With prefix arg or no symbol under point, prompts for a var." (interactive "P") - (cider-read-symbol-name "Symbol: " 'cider-doc-for query)) + (cider-read-symbol-name "Symbol: " 'cider-doc-lookup query)) (defun cider-src-handler (symbol) "Create a handler to lookup source for SYMBOL." From bc5e9f4b27f98be46752dbf886f11496460acce2 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 07:55:03 +0200 Subject: [PATCH 03/11] Make cider--jump-to-def-eval-fn work synchronously --- cider-interaction.el | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/cider-interaction.el b/cider-interaction.el index 0038fe32f..244b49c0f 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -492,15 +492,15 @@ Uses `find-file'." (kill-buffer opened-buffer))))) (t (error "Unknown resource path %s" resource)))) -(defun cider-jump-to-def-for (location buffer) - "Jump to LOCATION's definition in the source code, relative to BUFFER. -BUFFER is used to determine a tramp prefix, which is added to as a prefix -to the LOCATION." +(defun cider-jump-to-def-for (location) + "Jump to LOCATION's definition in the source code. +The current buffer is used to determine a tramp prefix, which is +added as a prefix to the LOCATION." ;; ugh; elisp destructuring doesn't work for vectors (let* ((resource (aref location 0)) (path (aref location 1)) (line (aref location 2)) - (tpath (if path (cider--client-tramp-filename path buffer)))) + (tpath (if path (cider--client-tramp-filename path)))) (cond (tpath (find-file tpath)) ((and path (file-exists-p path)) (find-file path)) @@ -508,18 +508,17 @@ to the LOCATION." (goto-char (point-min)) (forward-line (1- line)))) -(defun cider-jump-to-def-handler (buffer) - "Create a handler for jump-to-def in BUFFER." - ;; TODO: got to be a simpler way to do this - (nrepl-make-response-handler buffer - (lambda (buffer value) - (with-current-buffer buffer - (ring-insert find-tag-marker-ring (point-marker))) - (cider-jump-to-def-for - (car (read-from-string value)) buffer)) - (lambda (_buffer out) (message out)) - (lambda (_buffer err) (message err)) - nil)) +(defun cider--jump-to-def-eval-fn-1 (response) + "Handle the synchronous response." + (let ((value (plist-get response :value)) + (out (plist-get response :stdout)) + (err (plist-get response :stderr))) + (cond + (value + (ring-insert find-tag-marker-ring (point-marker)) + (cider-jump-to-def-for (car (read-from-string value)))) + (out (message out)) + (err (message err))))) (defun cider--jump-to-def-eval-fn (var) "Jump to VAR def by evaluating inlined Clojure code." @@ -558,9 +557,7 @@ to the LOCATION." :line) (clojure.core/meta (clojure.core/ns-resolve ns-symbol ns-var)))))" (cider-current-ns) var))) - (cider-tooling-eval form - (cider-jump-to-def-handler (current-buffer)) - (cider-current-ns)))) + (cider--jump-to-def-eval-fn-1 (cider-tooling-eval-sync form (cider-current-ns))))) (defun cider--jump-to-def-op-fn (var) "Jump to VAR def by using the nREPL info op." @@ -574,7 +571,7 @@ to the LOCATION." (file (cadr (assoc "file" val-alist))) (line (cadr (assoc "line" val-alist)))) (ring-insert find-tag-marker-ring (point-marker)) - (cider-jump-to-def-for (vector file file line) (current-buffer)))) + (cider-jump-to-def-for (vector file file line)))) (defun cider-jump-to-def (var) "Jump to the definition of the VAR at point." From 550f1cf2f39f7b86c27a93f08aea0a64cfa5d485 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 08:01:17 +0200 Subject: [PATCH 04/11] Move find-tag-marker-ring insertion to cider-jump-to-def-for --- cider-interaction.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cider-interaction.el b/cider-interaction.el index 244b49c0f..905d70ed5 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -496,6 +496,7 @@ Uses `find-file'." "Jump to LOCATION's definition in the source code. The current buffer is used to determine a tramp prefix, which is added as a prefix to the LOCATION." + (ring-insert find-tag-marker-ring (point-marker)) ;; ugh; elisp destructuring doesn't work for vectors (let* ((resource (aref location 0)) (path (aref location 1)) @@ -515,7 +516,6 @@ added as a prefix to the LOCATION." (err (plist-get response :stderr))) (cond (value - (ring-insert find-tag-marker-ring (point-marker)) (cider-jump-to-def-for (car (read-from-string value)))) (out (message out)) (err (message err))))) From 72bf24b5f65a364448d57b64f74ad5dbf28909ed Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 08:11:20 +0200 Subject: [PATCH 05/11] cider--jump-to-def-eval-fn-1: signal errors --- cider-interaction.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cider-interaction.el b/cider-interaction.el index 905d70ed5..4851d26f0 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -517,8 +517,8 @@ added as a prefix to the LOCATION." (cond (value (cider-jump-to-def-for (car (read-from-string value)))) - (out (message out)) - (err (message err))))) + (out (error out)) + (err (error err))))) (defun cider--jump-to-def-eval-fn (var) "Jump to VAR def by evaluating inlined Clojure code." From 6cb9efbf1da6fc407b0f2f50be5b87fbca903c07 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 08:26:12 +0200 Subject: [PATCH 06/11] Define cider-company-location It's a hack, but a simple one. --- cider-interaction.el | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/cider-interaction.el b/cider-interaction.el index 4851d26f0..12d24bc43 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -620,7 +620,16 @@ otherwise dispatch to internal completion function." (let ((bounds (bounds-of-thing-at-point 'symbol))) (list (car bounds) (cdr bounds) (completion-table-dynamic #'cider-dispatch-complete-symbol) - :company-doc-buffer #'cider-doc-buffer-for))))) + :company-doc-buffer #'cider-doc-buffer-for + :company-location #'cider-company-location))))) + +(defun cider-company-location (var) + "Open VAR definition in a buffer and return its location." + (save-excursion + (save-window-excursion + (let ((find-tag-marker-ring (make-ring 1))) + (cider-jump-to-def var) + (cons (current-buffer) (point)))))) ;;; JavaDoc Browsing ;;; Assumes local-paths are accessible in the VM. From 466d5501a2d90e8a5e3006aa3bb6189b4598e325 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 08:55:00 +0200 Subject: [PATCH 07/11] Define cider-company-docsig --- cider-eldoc.el | 24 +++++++++++++++--------- cider-interaction.el | 11 ++++++++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/cider-eldoc.el b/cider-eldoc.el index c2ac712ca..3c42d26a8 100644 --- a/cider-eldoc.el +++ b/cider-eldoc.el @@ -90,21 +90,27 @@ POS is the index of current argument." nil (list (cider-symbol-at-point) argument-index))))) +(defun cider-eldoc-arglist (thing) + "Return the arglist for THING." + (let* ((form (format "(try + (:arglists + (clojure.core/meta + (clojure.core/resolve + (clojure.core/read-string \"%s\")))) + (catch Throwable t nil))" thing)) + (value (when thing + (cider-get-raw-value (cider-tooling-eval-sync form nrepl-buffer-ns))))) + (unless (string= value "nil") + value))) + (defun cider-eldoc () "Backend function for eldoc to show argument list in the echo area." (when (cider-connected-p) (let* ((info (cider-eldoc-info-in-current-sexp)) (thing (car info)) (pos (cadr info)) - (form (format "(try - (:arglists - (clojure.core/meta - (clojure.core/resolve - (clojure.core/read-string \"%s\")))) - (catch Throwable t nil))" thing)) - (value (when thing - (cider-get-raw-value (cider-tooling-eval-sync form nrepl-buffer-ns))))) - (unless (string= value "nil") + (value (cider-eldoc-arglist thing))) + (when value (format "%s: %s" (cider-eldoc-format-thing thing) (cider-eldoc-format-arglist value pos)))))) diff --git a/cider-interaction.el b/cider-interaction.el index 12d24bc43..327e7834a 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -621,7 +621,8 @@ otherwise dispatch to internal completion function." (list (car bounds) (cdr bounds) (completion-table-dynamic #'cider-dispatch-complete-symbol) :company-doc-buffer #'cider-doc-buffer-for - :company-location #'cider-company-location))))) + :company-location #'cider-company-location + :company-docsig #'cider-company-docsig))))) (defun cider-company-location (var) "Open VAR definition in a buffer and return its location." @@ -631,6 +632,14 @@ otherwise dispatch to internal completion function." (cider-jump-to-def var) (cons (current-buffer) (point)))))) +(defun cider-company-docsig (thing) + "Return signature for THING." + (let ((arglist (cider-eldoc-arglist thing))) + (when arglist + (format "%s: %s" + (cider-eldoc-format-thing thing) + arglist)))) + ;;; JavaDoc Browsing ;;; Assumes local-paths are accessible in the VM. (defvar cider-javadoc-local-paths nil From ef008f66a963bd68d22debb971198a9491d97575 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 09:06:58 +0200 Subject: [PATCH 08/11] Mention company-mode and company-cider --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 8838eb9e6..ae174c803 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,14 @@ enable `paredit` in the REPL buffer as well: Where nREPL provides it, pop-up documentation for completed symbols will be displayed. +* [company-cider](https://github.com/clojure-emacs/company-cider) + provides completion back-end with similar functionality for + [company-mode](http://company-mode.github.io/). + +* As long as `company-mode` has the `company-capf` back-end enabled, + it will retrieve completion information from + `cider-complete-at-point`, requiring no additional setup. + ## Basic Usage The only requirement to use CIDER is to have a nREPL server to From 4e68adca458d24e32b8e96c8de8397d858327e38 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 21:57:20 +0200 Subject: [PATCH 09/11] Upcase the argument name --- cider-interaction.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cider-interaction.el b/cider-interaction.el index 327e7834a..5ece1e7a5 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -510,7 +510,7 @@ added as a prefix to the LOCATION." (forward-line (1- line)))) (defun cider--jump-to-def-eval-fn-1 (response) - "Handle the synchronous response." + "Handle the synchronous RESPONSE." (let ((value (plist-get response :value)) (out (plist-get response :stdout)) (err (plist-get response :stderr))) From 8939d8a53155435692d7d9910a368be77ec0126c Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 22:31:21 +0200 Subject: [PATCH 10/11] Add Changelog entry --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f49ca05ca..1d91535b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ### New features +* [#490](https://github.com/clojure-emacs/cider/pull/490) Dedicated + support for `company-mode` in `cider-complete-at-point`. * [#460](https://github.com/clojure-emacs/cider/issues/460) Support for cider-nrepl's complete middleware for CLJ/CLJS autocomplete. * [#465](https://github.com/clojure-emacs/cider/issues/465) Support for From fcad847f3c9a003da70f80b97b8b2759c8714a10 Mon Sep 17 00:00:00 2001 From: Dmitry Gutov Date: Sun, 2 Mar 2014 23:01:26 +0200 Subject: [PATCH 11/11] cider-company-location: check explicitly for namespace error message --- cider-interaction.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cider-interaction.el b/cider-interaction.el index 5ece1e7a5..a70ad815e 100644 --- a/cider-interaction.el +++ b/cider-interaction.el @@ -630,7 +630,8 @@ otherwise dispatch to internal completion function." (save-window-excursion (let ((find-tag-marker-ring (make-ring 1))) (cider-jump-to-def var) - (cons (current-buffer) (point)))))) + (unless (string-match-p "Namespace not found" (current-message)) + (cons (current-buffer) (point))))))) (defun cider-company-docsig (thing) "Return signature for THING."