diff --git a/racer.el b/racer.el index ab2c23a..00a9480 100644 --- a/racer.el +++ b/racer.el @@ -348,10 +348,18 @@ split it into its constituent parts." :signature (nth 6 match-parts) :docstring (if (> (length docstring) 0) docstring nil))))) +(defun racer--order-descriptions (descriptions) + (sort descriptions + (lambda (a b) + (let ((a (or (plist-get a :docstring) "")) + (b (or (plist-get b :docstring) ""))) + (> (length a) (length b)))))) + (defun racer--describe-at-point (name) - "Get a description of the symbol at point matching NAME. -If there are multiple possibilities with this NAME, prompt -the user to choose." + "Get a descriptions of the symbols matching symbol at point and +NAME. If there are multiple possibilities with this NAME, prompt +the user to choose. Return a list of all possibilities that +start with the user's selection." (let* ((output-lines (save-excursion ;; Move to the end of the current symbol, to ;; increase racer accuracy. @@ -362,14 +370,20 @@ the user to choose." output-lines)) (relevant-matches (--filter (equal (plist-get it :name) name) all-matches))) - (if (> (length relevant-matches) 1) - ;; We might have multiple matches with the same name but - ;; different types. E.g. Vec::from. - (let ((signature - (completing-read "Multiple matches: " - (--map (plist-get it :signature) relevant-matches)))) - (--first (equal (plist-get it :signature) signature) relevant-matches)) - (-first-item relevant-matches)))) + (racer--order-descriptions + (if (> (length relevant-matches) 1) + ;; We might have multiple matches with the same name but + ;; different types. E.g. Vec::from. + (let ((signature + (completing-read "Multiple matches: " + (--map (plist-get it :signature) relevant-matches)))) + (-filter + (lambda (x) + (let ((sig (plist-get x :signature))) + (equal (substring sig 0 (min (length sig) (length signature))) + signature))) + relevant-matches)) + relevant-matches)))) (defun racer--help-buf (contents) "Create a *Racer Help* buffer with CONTENTS." @@ -576,29 +590,39 @@ For example, 'EnumKind' -> 'an enum kind'." "Return a *Racer Help* buffer for the function or type at point. If there are multiple candidates at point, use NAME to find the correct value." - (let ((description (racer--describe-at-point name))) - (when description - (let* ((name (plist-get description :name)) - (raw-docstring (plist-get description :docstring)) - (docstring (if raw-docstring - (racer--propertize-docstring raw-docstring) - "Not documented.")) - (kind (plist-get description :kind))) - (racer--help-buf - (format - "%s is %s defined in %s.\n\n%s%s" - name - (racer--kind-description kind) - (racer--src-button - (plist-get description :path) - (plist-get description :line) - (plist-get description :column)) - (if (equal kind "Module") - ;; No point showing the 'signature' of modules, which is - ;; just their full path. - "" - (format " %s\n\n" (racer--syntax-highlight (plist-get description :signature)))) - docstring)))))) + (let ((descriptions (racer--describe-at-point name))) + (when descriptions + (racer--help-buf + (let ((output "") + (first-iteration t)) + (dolist (description descriptions output) + (unless first-iteration + (setf output + (concat output (format "\n---------------------------------------------------------------\n")))) + (setf output + (concat + output + (let* ((name (plist-get description :name)) + (raw-docstring (plist-get description :docstring)) + (docstring (if raw-docstring + (racer--propertize-docstring raw-docstring) + "Not documented.")) + (kind (plist-get description :kind))) + (setf first-iteration nil) + (format + "%s is %s defined in %s.\n\n%s%s" + name + (racer--kind-description kind) + (racer--src-button + (plist-get description :path) + (plist-get description :line) + (plist-get description :column)) + (if (equal kind "Module") + ;; No point showing the 'signature' of modules, which is + ;; just their full path. + "" + (format " %s\n\n" (racer--syntax-highlight (plist-get description :signature)))) + docstring)))))))))) (defun racer-describe () "Show a *Racer Help* buffer for the function or type at point." diff --git a/test/racer-test.el b/test/racer-test.el index b7ce944..6d92454 100644 --- a/test/racer-test.el +++ b/test/racer-test.el @@ -187,9 +187,9 @@ baz."))) "PREFIX 36,37,n" "MATCH new;new();294;11;/home/user/src/rustc-1.10.0/src/libstd/../libcollections/vec.rs;Function;pub fn new() -> Vec;\"Constructs a new, empty `Vec`.\"" "END"))))) - (should - (equal (plist-get (racer--describe-at-point "new") :name) - "new")))) + (dolist (desc (racer--describe-at-point "new")) + (should + (equal (plist-get desc :name) "new"))))) (ert-deftest racer--describe-at-point-nil-docstring () "If there's no docstring, racer--describe-at-point should use nil." @@ -201,8 +201,9 @@ baz."))) "PREFIX 36,37,n" "MATCH new;new();294;11;/home/user/src/rustc-1.10.0/src/libstd/../libcollections/vec.rs;Function;pub fn new() -> Vec;\"\"" "END"))))) - (should - (null (plist-get (racer--describe-at-point "new") :docstring))))) + (dolist (desc (racer--describe-at-point "new")) + (should + (null (plist-get desc :docstring)))))) (ert-deftest racer--describe-at-point-shortest () "If there are multiple matches, we want the shortest. @@ -218,9 +219,9 @@ Since we've moved point to the end of symbol, the other functions just happen to "MATCH new;new();294;11;/home/user/src/rustc-1.10.0/src/libstd/../libcollections/vec.rs;Function;pub fn new() -> Vec;\"\"" "MATCH new_foo;new_foo();294;11;/home/user/src/rustc-1.10.0/src/libstd/../libcollections/vec.rs;Function;pub fn new() -> Vec;\"\"" "END"))))) - (should - (equal (plist-get (racer--describe-at-point "new") :name) - "new")))) + (dolist (desc (racer--describe-at-point "new")) + (should + (equal (plist-get desc :name) "new"))))) (ert-deftest racer--syntax-highlight () "Ensure we highlight code blocks and snippets correctly."