diff options
-rw-r--r-- | cider-eldoc.el | 67 | ||||
-rw-r--r-- | doc/configuration.md | 44 | ||||
-rw-r--r-- | test/cider-eldoc-tests.el | 66 |
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.")))))) |