reddit / emacs

Find file in project sub directory?

joshleeb 路 2022-03-28 09:06
Hey r/emacs, long time Vim user here trying to make the switch to Emacs and get it to stick (this time). And one of the recommendations I've seen when it comes to successfully switching is to figure out your emacs workflow and patterns rather than trying to shove Vim into Emacs (evil-mode aside). One of the core parts of my Vim workflow was fuzzy finding a file (any file, anywhere) in a project. And I see that there's a way to get similar functionality with projectile or project.el. The problem I've found is on large projects it's too slow, and breaks my focus. But this got me thinking. I very rarely need to jump between many far flung regions of the project I'm working on. And actually, having to search through all files in the project (as quick as it may be) gets annoying in my Vim workflow where there are many files with the same or similar names. So instead, what I'm imagining would work well for me is to fuzzy search for all files in a sub directory of a project. I.e: in executing a custom `project-find-file` I would first get the option to find a subdir in the project, and then it would operate as regular `project-find-file` from that subdir. Being new to emacs/elisp are there any pointers for how to do this, I would imagine ideally with project.el? Or alternatively, how do you deal with navigating to files quickly (without breaking your focus/flow) in large projects with emacs? Thanks in advance! 馃檹
AndreaSomePostfix 路 2022-03-28 11:19
Mmm maybe you just need to wrap\` (project-find-file-in (thing-at-point 'filename) dirs pr)\`
AndreaSomePostfix 路 2022-03-28 11:19
So the one you are using is this: `(defun project-find-file ()` `"Visit a file (with completion) in the current project.` `The filename at point (determined by \`thing-at-point'), if any,` `is available as part of \"future history\"."` `(interactive)` `(let* ((pr (project-current t))` `(dirs (list (project-root pr))))` `(project-find-file-in (thing-at-point 'filename) dirs pr)))`
AndreaSomePostfix 路 2022-03-28 11:21
while you want something like (defun project-find-file-in-dir (dir) "Visit a file (with completion) in the current project. The filename at point (determined by \`thing-at-point'), if any, is available as part of \\"future history\\"." (interactive "D") (let\* ((pr (project-current t)) (dirs (list dir))) (project-find-file-in (thing-at-point 'filename) dirs pr)))
AndreaSomePostfix 路 2022-03-28 11:24
I just introduced (interactive "D") which asks you for a directory and passes it to project-find-file-in. The writers of project.el are smart people and made the library pretty malleable with project-find-file-in, they just didn't expose it
AndreaSomePostfix 路 2022-03-28 11:24
and if you want help learning elisp, check out the Emacs Buddy initiative https://github.com/ag91/emacs-buddy
by_wicker 路 2022-03-28 15:13
Is your repo huge because it's a monorepo with multiple sub-projects in? If so, it's easy to make `projectile` see it as separate projects by just dropping an empty `.projectile` file where you want a project root. There are other ways to skin this cat too. For `project.el` you would have to rolling your own option for this I think. Something I intend to get to and then I could abandon `projectile` for the build-in `project`.
[deleted] 路 2022-03-29 01:20
[deleted]
joshleeb 路 2022-03-29 01:21
Thanks so much, super helpful! For future reference this is where I landed with a function to try out in my workflow. (defun choose-directory (dir) (interactive "D") dir) (defun project-find-file-in-dir () (interactive) (let* ((pr (project-current t)) (default-directory (project-root pr)) (dir (call-interactively 'choose-directory)) (dirs (list dir))) (project-find-file-in (thing-at-point 'filename) dirs pr)))
redguardtoo 路 2022-03-29 13:11
https://github.com/redguardtoo/find-file-in-project#find-file-in-current-directory