elpa-find-file function
While researching internals of agent-shell I needed to quickly visit Elisp files by name. Here's the helper, which takes the file name and finds it within installed packages.
Examples:
- (elpa-find-file "agent-shell.el")
- (elpa-find-file "avy.el")
(defun elpa-find-file (pattern)
"Open first file matching PATTERN in the elpa directory.
Error if multiple versions of the same package match."
(interactive "sFile: ")
(let* ((elpa-dir (expand-file-name "elpa" user-emacs-directory))
(files (thread-first
"rg --files %s | grep -F \"%s\" | grep -v '\\.elc$'"
(format (shell-quote-argument elpa-dir) pattern)
shell-command-to-string
split-string))
(pkgs (mapcar (lambda (f)
(let ((dir (cadr (split-string f "/elpa/"))))
(replace-regexp-in-string
"-[0-9].*?/.*\\'" "" dir)))
files))
(dups (seq-filter (lambda (p)
(> (cl-count p pkgs :test #'string=) 1))
(seq-uniq pkgs))))
(when dups
(user-error "Multiple versions found for: %s — clean up %s"
(string-join dups ", ") elpa-dir))
(unless files
(user-error "file %s not found" pattern))
(find-file (cl-first files))))
Support to jumping to a :line:column
Okay, almost immediately I wanted something like this - (elpa-find-file "agent-shell.el:4616"), which is essentially what visit-source.el does. But, it turned out better not integrate visit-source, but implement parsing of line directly in the function.
So, version 2:
(defun elpa-find-file (pattern)
"Open file matching PATTERN in the elpa directory.
PATTERN may include a trailing :LINE or :LINE:COL.
Error if multiple versions of the same package match."
(interactive "sFile: ")
(let* ((parts (split-string pattern ":"))
(name (car parts))
(line (and (nth 1 parts) (string-to-number (nth 1 parts))))
(col (and (nth 2 parts) (string-to-number (nth 2 parts))))
(elpa-dir (expand-file-name "elpa" user-emacs-directory))
(files (thread-first
"rg --files %s | grep -F \"%s\" | grep -v '\\.elc$'"
(format (shell-quote-argument elpa-dir) name)
shell-command-to-string
split-string))
(pkgs (mapcar (lambda (f)
(let ((dir (cadr (split-string f "/elpa/"))))
(replace-regexp-in-string
"-[0-9].*?/.*\\'" "" dir)))
files))
(dups (seq-filter (lambda (p)
(> (cl-count p pkgs :test #'string=) 1))
(seq-uniq pkgs))))
(when dups
(user-error "Multiple versions found for: %s — clean up %s"
(string-join dups ", ") elpa-dir))
(unless files
(user-error "file %s not found" name))
(find-file (cl-first files))
(when line
(goto-char (point-min))
(forward-line (1- line))
(when col (forward-char (1- col))))))