Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support company-mode #490

Merged
merged 11 commits into from
Mar 2, 2014
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
24 changes: 15 additions & 9 deletions cider-eldoc.el
Original file line number Diff line number Diff line change
Expand Up @@ -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))))))
Expand Down
86 changes: 56 additions & 30 deletions cider-interaction.el
Original file line number Diff line number Diff line change
Expand Up @@ -492,34 +492,33 @@ 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."
(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))
(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))
(t (cider-find-resource resource)))
(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
(cider-jump-to-def-for (car (read-from-string value))))
(out (error out))
(err (error err)))))

(defun cider--jump-to-def-eval-fn (var)
"Jump to VAR def by evaluating inlined Clojure code."
Expand Down Expand Up @@ -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."
Expand All @@ -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."
Expand Down Expand Up @@ -622,8 +619,27 @@ 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
: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."
(save-excursion
(save-window-excursion
(let ((find-tag-marker-ring (make-ring 1)))
(cider-jump-to-def var)
(unless (string-match-p "Namespace not found" (current-message))
(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.
Expand Down Expand Up @@ -1225,20 +1241,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-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-buffer-for (symbol)
"Return buffer with documentation for SYMBOL."
(let* ((form (format "(clojure.repl/doc %s)" symbol))
(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)
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-handler query))
(cider-read-symbol-name "Symbol: " 'cider-doc-lookup query))

(defun cider-src-handler (symbol)
"Create a handler to lookup source for SYMBOL."
Expand Down