summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cider-eldoc.el67
-rw-r--r--doc/configuration.md44
-rw-r--r--test/cider-eldoc-tests.el66
3 files changed, 156 insertions, 21 deletions
diff --git a/cider-eldoc.el b/cider-eldoc.el
index 26399d23..f0737216 100644
--- a/cider-eldoc.el
+++ b/cider-eldoc.el
@@ -138,16 +138,73 @@ is non-nil. Else format it as a variable."
;; in case ns-or-class is nil
propertized-method-name))
+(defun cider-eldoc-format-sym-doc (var ns docstring)
+ "Return the formatted eldoc string for VAR and DOCSTRING.
+
+Consider the value of `eldoc-echo-area-use-multiline-p' while formatting.
+If the entire line cannot fit in the echo area, the var name may be
+truncated or eliminated entirely from the output to make room for the
+description.
+
+Try to truncate the var with various strategies, so that the var and
+the docstring can be displayed in the minibuffer without resizing the window.
+We start with `cider-abbreviate-ns' and `cider-last-ns-segment'.
+Next, if the var is in current namespace, we remove NS from the eldoc string.
+Otherwise, only the docstring is returned."
+ (let* ((ea-multi eldoc-echo-area-use-multiline-p)
+ ;; Subtract 1 from window width since emacs will not write
+ ;; any chars to the last column, or in later versions, will
+ ;; cause a wraparound and resize of the echo area.
+ (ea-width (1- (window-width (minibuffer-window))))
+ (strip (- (+ (length var) (length docstring)) ea-width))
+ (newline (string-match-p "\n" docstring))
+ ;; Truncated var can be ea-var long
+ ;; Subtract 2 to account for the : and / added when including
+ ;; the namespace prefixed form in eldoc string
+ (ea-var (- (- ea-width (length docstring)) 2)))
+ (cond
+ ((or (eq ea-multi t)
+ (and (<= strip 0) (null newline))
+ (and ea-multi (or (> (length docstring) ea-width) newline)))
+ (format "%s: %s" var docstring))
+
+ ;; Now we have to truncate either the docstring or the var
+ (newline (cider-eldoc-format-sym-doc var ns (substring docstring 0 newline)))
+
+ ;; Only return the truncated docstring
+ ((> (length docstring) ea-width)
+ (substring docstring 0 ea-width))
+
+ ;; Try to truncate the var with cider-abbreviate-ns
+ ((<= (length (cider-abbreviate-ns var)) ea-var)
+ (format "%s: %s" (cider-abbreviate-ns var) docstring))
+
+ ;; Try to truncate var with cider-last-ns-segment
+ ((<= (length (cider-last-ns-segment var)) ea-var)
+ (format "%s: %s" (cider-last-ns-segment var) docstring))
+
+ ;; If the var is in current namespace, we try to truncate the var by
+ ;; skipping the namespace from the returned eldoc string
+ ((and (string-equal ns (cider-current-ns))
+ (<= (- (length var) (length ns)) ea-var))
+ (format "%s: %s"
+ (replace-regexp-in-string (format "%s/" ns) "" var)
+ docstring))
+
+ ;; We couldn't fit the var and docstring in the available space,
+ ;; so we just display the docstring
+ (t docstring))))
+
(defun cider-eldoc-format-variable (thing pos eldoc-info)
"Return the formatted eldoc string for a variable.
THING is the variable name. POS will always be 0 here.
ELDOC-INFO is a p-list containing the eldoc information."
- (let ((ns (lax-plist-get eldoc-info "ns"))
- (symbol (lax-plist-get eldoc-info "symbol"))
- (docstring (lax-plist-get eldoc-info "docstring")))
+ (let* ((ns (lax-plist-get eldoc-info "ns"))
+ (symbol (lax-plist-get eldoc-info "symbol"))
+ (docstring (lax-plist-get eldoc-info "docstring"))
+ (formatted-var (cider-eldoc-format-thing ns symbol thing 'var)))
(when docstring
- (format "%s: %s" (cider-eldoc-format-thing ns symbol thing 'var)
- docstring))))
+ (cider-eldoc-format-sym-doc formatted-var ns docstring))))
(defun cider-eldoc-format-function (thing pos eldoc-info)
"Return the formatted eldoc string for a function.
diff --git a/doc/configuration.md b/doc/configuration.md
index 2fd6722b..15cb0b05 100644
--- a/doc/configuration.md
+++ b/doc/configuration.md
@@ -4,22 +4,6 @@ experience.
## Basic configuration
-* Enable `eldoc` in Clojure buffers:
-
-```el
-(add-hook 'cider-mode-hook #'eldoc-mode)
-```
-
-![Eldoc](images/eldoc.png)
-
-CIDER also would show the eldoc for the symbol at point. So in (map inc ...)
-when the cursor is over inc its eldoc would be displayed. You can turn off this
-behaviour by:
-
-```el
-(setq cider-eldoc-display-for-symbol-at-point nil)
-```
-
* Suppress auto-enabling of `cider-mode` in `clojure-mode` buffers, when starting
CIDER:
@@ -140,6 +124,34 @@ More details can be found [here](https://github.com/clojure-emacs/cider/issues/9
(setq cider-filter-regexps '(".*nrepl"))
```
+## Configuring eldoc
+
+* Enable `eldoc` in Clojure buffers:
+
+```el
+(add-hook 'cider-mode-hook #'eldoc-mode)
+```
+
+![Eldoc](images/eldoc.png)
+
+* CIDER also would show the eldoc for the symbol at point. So in (map inc ...)
+when the cursor is over inc its eldoc would be displayed. You can turn off this
+behaviour by:
+
+```el
+(setq cider-eldoc-display-for-symbol-at-point nil)
+```
+
+* CIDER respects the value of `eldoc-echo-area-use-multiline-p` when
+displaying documentation in the minibuffer. You can customize this variable to change
+its behaviour.
+
+| eldoc-echo-area-use-multiline-p | Behaviour |
+| ------------- | ------------- |
+| `t` | Never attempt to truncate messages. Complete symbol name and function arglist or variable documentation will be displayed even if echo area must be resized to fit.|
+| `nil` | Messages are always truncated to fit in a single line of display in the echo area. |
+| `truncate-sym-name-if-fit` or anything non-nil | Symbol name may be truncated if it will enable the function arglist or documentation string to fit on a single line. Otherwise, behavior is just like `t` case. |
+
## Overlays
When you evaluate code in Clojure files, the result is displayed in the buffer
diff --git a/test/cider-eldoc-tests.el b/test/cider-eldoc-tests.el
index dfc5cc50..06c418d4 100644
--- a/test/cider-eldoc-tests.el
+++ b/test/cider-eldoc-tests.el
@@ -234,3 +234,69 @@
(search-forward ".length")
(expect (cider-eldoc-info-in-current-sexp) :to-equal
'("eldoc-info" (("java.lang.String") ".length" (("this"))) "thing" "java.lang.String/.length" "pos" 0)))))))
+
+(describe "cider-eldoc-format-sym-doc"
+ :var (eldoc-echo-area-use-multiline-p)
+ (before-all
+ (spy-on 'window-width :and-return-value 177))
+
+ (it "returns the formated eldoc string"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "Simple docstring.")
+ :to-equal "kubaru.core/plane: Simple docstring."))
+
+
+ (describe "specifications for eldoc-echo-area-use-multiline-p"
+ (describe "when its value is t"
+ (before-each
+ (setq eldoc-echo-area-use-multiline-p t))
+ (it "does not truncate anything"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ :to-equal "kubaru.core/plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "Line 1.\nLine 2.\nLine 3.")
+ :to-equal "kubaru.core/plane: Line 1.\nLine 2.\nLine 3.")))
+
+
+ (describe "when its value is truncate-sym-name-if-fit"
+ (before-each
+ (setq eldoc-echo-area-use-multiline-p 'truncate-sym-name-if-fit))
+ (it "doesn't truncate anything if docstring doesn't fit"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ :to-equal "kubaru.core/plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+ (it "truncates the symbol name with cider-abbreviate-ns"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ :to-equal "k.core/plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+ (it "truncates the symbol name with cider-last-ns-segment"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ :to-equal "core/plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+ (it "leaves out the namespace if the var is in current namespace"
+ (spy-on 'cider-current-ns :and-return-value "kubaru.core")
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ :to-equal "plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+ ;; this case would be different when it is nil
+ (it "returns as is if truncating the symbol doesn't make it fit"
+ ;; notice that the T is not deleted
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaT")
+ :to-equal "kubaru.core/plane: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaT"))
+
+ (describe "when the docstring spans multiple lines"
+ (it "returns it as is"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "Line 1.\nLine 2.\nLine 3.")
+ :to-equal "kubaru.core/plane: Line 1.\nLine 2.\nLine 3."))))
+
+
+ (describe "when its value is nil"
+ (before-each
+ (setq eldoc-echo-area-use-multiline-p nil))
+ (it "leaves out the symbol name and truncates the docstring"
+ ;; notice the missing T from the result
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaT")
+ :to-equal "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
+
+ (describe "when the docstring spans multiple lines"
+ (it "returns tries to display the var with the first line"
+ (expect (cider-eldoc-format-sym-doc "kubaru.core/plane" "kubaru.core" "Line 1.\nLine 2.\nLine 3.")
+ :to-equal "kubaru.core/plane: Line 1."))))))