If you work on large repos at large companies using Vim or Emacs, my experience has been that most solutions seem to break down under the performance strain except for getting FZF in the mix. I've tried stock Telescope+neovim, Emacs+helm/ivy, etc.
I’ve been able to get decent performance from helm in large repos. I think the main thing is to get rg to walk the list of files instead of using the native elisp implementation.
Never tried other solutions, but fzf + vim + ripgrep handle everything I've worked with without any real performance issues even on 500K-1M line repos. Of course they're no longer instantaneous at those line counts, but still in the order of seconds.
At that point, I’d be project-scoping to individual submodules rather than the whole monolith. For something like projectile, that would mean dropping a .projectile in the submodule root so my “rip grip in project” functions are scoped to the submodule, then using VC to mark the root where I need to expensively search the whole project.
Could you explain more about this setup? I'm not familiar with "projectile". Is this https://github.com/bbatsov/projectile the same thing you're referring to?
Sounds interesting. What I've done recently is open my vim in the folder that contains all the organization's repos (the ones I've cloned) and just run ripgrep inside vim to find examples or references to whatever I've seeking. Seems performant enough even without doing anything except letting ripgrep ignore git-ignored stuff (default behavior of ripgrep).
Sure - projectile is one of the packages that convinced me to migrate from vim to emacs. It curates a notion of "project" and maintains a list of projects you visit. My workflow is based around a lot of using projectile-find-file, which prompts you for a known project, then dumps you into an completion interface to open a specific file.
Projectile works OOTB with .git directories, so if you visit a git-controlled dir it's added to your projects. You can similarly specify other directories as projects by putting a .projectile file in them, and the contents of the .projectile file act as an ignore list.
So the workflow is work/myMonolith is the git controlled root, while I have work/myMonolith/frontend/.projectile and work/myMonolith/backend/.projectile. So I can use the project-scoped find file, grep etc. to inherently narrow the search space to that module. When I'd want to globally search, I'd use projectile-find-file (or grep, or whatever) on the myMonolith root.
I tend to not like this extra step of managing submodules, but to each their own. Often enough I'm looking at many packages at once. I guess you have to globally gitignore the projectile file too to avoid committing them everywhere?
I considered projectile but then found that the built in project-find-file is enough for my puny webdev projects - they all have a .git by default and once in the dir, looking for files works it seems without any setup or config files. Does projectile have something I might like to have?
I don't know if there's a way to indicate a project with the built-in project.el without a VC root. The other feature i use regularly that I don't think exists in project.el is projectile-toggle-between-implementation-and-test, which does exactly what it sounds like. You can configure it by build tool and give it path regexes to substitute to specify how to find the corresponding Spec for a file.
I actually use a mix of both. Project.el being built in means it properly leverages the built-in completion stuff, which has a level of awareness for the types of things I search and gives appropriate icons and context information (see all-the-icons-completion[1] for details). I fibbed a little bit about my workflow - to switch projects and find a file I use this:
(defun project-find-file-from-projectile-project ()
(interactive)
(project-switch-project (completing-read "From which project?" projectile-known-projects)))