diff --git a/README.md b/README.md
index 52383b9..7b5c340 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ You will now have the following key combinations at your disposal:
C-c C-c C-S-a | cargo-process-audit
C-c C-c C-S-r | cargo-process-script
C-c C-c C-w | cargo-process-watch
+ C-c C-c C-S-f | cargo-find-dependency
Before executing the task, Emacs will prompt you to save any modified buffers
associated with the current Cargo project. Setting `compilation-ask-about-save`
diff --git a/cargo-process.el b/cargo-process.el
index 6b8a2db..c9aa610 100644
--- a/cargo-process.el
+++ b/cargo-process.el
@@ -347,6 +347,15 @@ If FILE-NAME is not a TRAMP file, return it unmodified."
(cdr (assoc 'workspace_root metadata-json)))))
workspace-root)))
+(defun cargo-process--get-metadata ()
+ "Return the metadata of the current package as an alist."
+ (when (cargo-process--project-root)
+ (let ((metadata-text
+ (shell-command-to-string
+ (concat (shell-quote-argument cargo-process--custom-path-to-bin)
+ " metadata --format-version 1"))))
+ (cargo-json-read-from-string metadata-text))))
+
(defun manifest-path-argument (name)
(let ((manifest-filename (cargo-process--tramp-file-local-name (cargo-process--project-root "Cargo.toml"))))
(when (and manifest-filename
diff --git a/cargo.el b/cargo.el
index 3ccd1e3..14dc1f8 100644
--- a/cargo.el
+++ b/cargo.el
@@ -88,6 +88,7 @@
(define-key km (kbd "C-S-a") 'cargo-process-audit)
(define-key km (kbd "C-S-r") 'cargo-process-script)
(define-key km (kbd "C-w") 'cargo-process-watch)
+ (define-key km (kbd "C-S-f") 'cargo-find-dependency)
km)
"Keymap for Cargo mode commands after prefix.")
(fset 'cargo-minor-mode-command-map cargo-minor-mode-command-map)
@@ -100,6 +101,33 @@
(defvar cargo-minor-mode nil)
+(defun cargo-find-dependency (crate &optional metadata)
+ "Find CRATE's Cargo.toml.
+If METADATA is non-nil, use that instead of fetching it with cargo."
+ (interactive (let* ((metadata
+ (cargo-process--get-metadata))
+ (crates
+ (mapcar (lambda (pkg) (alist-get 'name pkg))
+ (append (alist-get 'packages metadata) nil))))
+ (list
+ (completing-read
+ "Dependency: " crates nil t nil nil (symbol-at-point))
+ metadata)))
+ (let ((filenames
+ (cl-loop for pkg in (append (alist-get 'packages metadata) nil)
+ when (equal crate (alist-get 'name pkg))
+ collect (alist-get 'manifest_path pkg)))
+ ;; Directly `find-file' if there's just a single match.
+ (xref-show-xrefs-function xref-show-definitions-function))
+ (if filenames
+ (xref-show-xrefs (mapcar (lambda (filename)
+ (xref-make crate
+ (xref-make-file-location
+ filename 1 0)))
+ filenames)
+ nil)
+ (message "Can't find: %s" crate))))
+
;;;###autoload
(define-minor-mode cargo-minor-mode
"Cargo minor mode. Used to hold keybindings for cargo-mode.