feat(lookup): +lookup/file: search file tree for relative paths

Given a relative file path that:

- Doesn't exist, relative to the open file/buffer (default-directory),
- Doesn't exist, relative to the project root,
- Doesn't satisfy any of the other rules in ffap-alist,
- Contains more than one segment (forward slashes),

The +lookup/file command will walk the file tree from default-directory
to the project root to search for the path, so given:

  project
  └── src
      ├── a
      │   └── a.h
      └── b
          └── b.h

This command, run on 'b/b.h' in a/a.h, will open b/b.h (but 'b.h' alone
won't work, which is intended, to reduce false positives).

Close: #7890
Co-authored-by: liuzhishan <liuzhishan@users.noreply.github.com>
This commit is contained in:
Henrik Lissner 2024-06-20 17:08:26 -04:00
parent cffb3838ec
commit 0a2bcf928c
No known key found for this signature in database
GPG key ID: B60957CA074D39A3

View file

@ -263,29 +263,41 @@ current buffer."
(< pt end)))))))) (< pt end))))))))
(defun +lookup-ffap-backend-fn (identifier) (defun +lookup-ffap-backend-fn (identifier)
"Tries to locate the file at point (or in active selection). "Tries to locate the file or URL at point (or in active selection).
Uses find-in-project functionality (provided by ivy, helm, or project),
otherwise falling back to ffap.el (find-file-at-point)." See `ffap-alist' for ways to tweak how files are resolved. Falls back to
(let ((guess whatever find-in-project functionality is available in your active completion
framework (ivy, helm, vertico, etc), otherwise falling back to
`find-file-at-point''s file prompt."
(let ((initial-buffer (current-buffer))
(guess
(cond (identifier) (cond (identifier)
((doom-region-active-p) ((doom-region-active-p)
(buffer-substring-no-properties (buffer-substring-no-properties
(doom-region-beginning) (doom-region-beginning)
(doom-region-end))) (doom-region-end)))
((if (require 'ffap) (ffap-guesser))) ((if (require 'ffap) (ffap-guesser))) ; Powerful! See `ffap-alist'
((thing-at-point 'filename t))))) ((thing-at-point 'filename t)))))
(cond ((and (stringp guess) (cond ((and (stringp guess)
(or (file-exists-p guess) (or (file-exists-p guess)
(ffap-url-p guess))) (ffap-url-p guess)))
(find-file-at-point guess)) (find-file-at-point guess))
((and (modulep! :completion ivy) ;; Walk the file tree up to the project's root for relative paths.
(doom-project-p)) ((and (stringp guess)
;; Only do this with paths that contain segments, to reduce
;; false positives.
(string-match-p "/" guess)
(when-let ((dir (locate-dominating-file default-directory guess)))
(when (file-in-directory-p dir (doom-project-root))
(find-file (doom-path dir guess))
t))))
;; Fallback prompters
((and (modulep! :completion ivy) (doom-project-p))
(counsel-file-jump guess (doom-project-root))) (counsel-file-jump guess (doom-project-root)))
((and (modulep! :completion vertico) ((and (modulep! :completion vertico) (doom-project-p))
(doom-project-p))
(+vertico/consult-fd-or-find (doom-project-root) guess)) (+vertico/consult-fd-or-find (doom-project-root) guess))
((find-file-at-point (ffap-prompter guess)))) ((find-file-at-point (ffap-prompter guess))))
t)) (not (eq initial-buffer (current-buffer)))))
(defun +lookup-bug-reference-backend-fn (_identifier) (defun +lookup-bug-reference-backend-fn (_identifier)
"Searches for a bug reference in user/repo#123 or #123 format and opens it in "Searches for a bug reference in user/repo#123 or #123 format and opens it in