From 0a2bcf928c868db5cf41041bd707d3f395504130 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Thu, 20 Jun 2024 17:08:26 -0400 Subject: [PATCH] feat(lookup): +lookup/file: search file tree for relative paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- modules/tools/lookup/autoload/lookup.el | 32 +++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/modules/tools/lookup/autoload/lookup.el b/modules/tools/lookup/autoload/lookup.el index befd335fd..ac4ff3e65 100644 --- a/modules/tools/lookup/autoload/lookup.el +++ b/modules/tools/lookup/autoload/lookup.el @@ -263,29 +263,41 @@ current buffer." (< pt end)))))))) (defun +lookup-ffap-backend-fn (identifier) - "Tries to locate the file 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)." - (let ((guess + "Tries to locate the file or URL at point (or in active selection). + +See `ffap-alist' for ways to tweak how files are resolved. Falls back to +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) ((doom-region-active-p) (buffer-substring-no-properties (doom-region-beginning) (doom-region-end))) - ((if (require 'ffap) (ffap-guesser))) + ((if (require 'ffap) (ffap-guesser))) ; Powerful! See `ffap-alist' ((thing-at-point 'filename t))))) (cond ((and (stringp guess) (or (file-exists-p guess) (ffap-url-p guess))) (find-file-at-point guess)) - ((and (modulep! :completion ivy) - (doom-project-p)) + ;; Walk the file tree up to the project's root for relative paths. + ((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))) - ((and (modulep! :completion vertico) - (doom-project-p)) + ((and (modulep! :completion vertico) (doom-project-p)) (+vertico/consult-fd-or-find (doom-project-root) guess)) ((find-file-at-point (ffap-prompter guess)))) - t)) + (not (eq initial-buffer (current-buffer))))) (defun +lookup-bug-reference-backend-fn (_identifier) "Searches for a bug reference in user/repo#123 or #123 format and opens it in