[HN Gopher] Fuzzy Finding with Emacs Instead of Fzf
       ___________________________________________________________________
        
       Fuzzy Finding with Emacs Instead of Fzf
        
       Author : signa11
       Score  : 117 points
       Date   : 2023-12-10 08:47 UTC (14 hours ago)
        
 (HTM) web link (www.masteringemacs.org)
 (TXT) w3m dump (www.masteringemacs.org)
        
       | kungfufrog wrote:
       | Seems way more abstruse than just using fzf
        
         | mickeyp wrote:
         | fzf won't work in shell-mode as it does not handle curses-like
         | apps. Thus, `ezf.el' avoids that problem by using Emacs as the
         | fuzzy searching facility. To say nothing of the fact that this
         | is a fine example to re-use for, similar, needs where you need
         | to receive and send back information in an ordered manner.
         | 
         | (And helm is far more advanced than fzf is, as far as
         | searching)
        
           | Lyngbakr wrote:
           | Alternatively, would _fzf_ work in _vterm_?
        
             | mickeyp wrote:
             | Yes, of course. It'll work in EAT and M-x term too.
        
       | dig1 wrote:
       | Another alternative is fzf.el [1] which wraps fzf.
       | 
       | [1] https://github.com/bling/fzf.el
        
         | signa11 wrote:
         | and another one, from the author of consult/vertico/..., minad,
         | is affe: https://github.com/minad/affe
        
       | tetris11 wrote:
       | I always love reading these guides, and I will eventually give in
       | and buy Mickey's book just as a quick peek into his overflowing
       | mind.... but this article left me wanting for a fizzy completion
       | engine in emacs.
       | 
       | There is the emacs-fzf package, icicles, and various other
       | vertical completion frameworks, but I essentially want something
       | that pretends to be fzf at the Emacs level, without having to
       | spawn background shell scripts
        
         | xenodium wrote:
         | Emacs completion frameworks are handy within our beloved editor
         | but also well beyond. A recent post I wrote:
         | https://xenodium.com/building-your-own-bookmark-launcher
        
         | natrys wrote:
         | Various vertical completion frameworks like vertico are
         | essentially front-end UIs. You can choose underlying filtering
         | and sorting/scoring algorithm by setting `completion-styles`
         | variable. One popular choice here is the orderless package
         | (which probably doesn't give "fuzzy" completion experience as
         | most people call it I guess, orderless-flex does filtering but
         | not heuristic based sorting like fzf does).
         | 
         | There are some options outlined in the readme of fussy[1],
         | which is a wrapper around them. There are some pure elisp ones,
         | and some written in native languages (including fzf itself)
         | interfaced with dynamic module (so FFI rather than subprocess).
         | Does that qualify as Emacs level?
         | 
         | [1] https://github.com/jojojames/fussy
        
           | tetris11 wrote:
           | Yeah, I'm currently using orderless with vertico for my
           | "fuzzy" needs, but I genuinely do find ido completion much
           | faster and more practical 90% of the time.
        
           | flylikeabanana wrote:
           | Orderless is probably the way to go for a "pure emacs"
           | solution - its selling point is that you can feed whatever
           | function you want into the completion framework, so if you
           | feed a fuzzy completer then you get fuzzy matching. It's also
           | part of a relatively new completion stack (that includes
           | vertico, marginalia, and others) that leverages the inbuilt
           | emacs features instead of replacing them.
        
         | hprotagonist wrote:
         | M-x ask and ye shall receive:
         | 
         | https://github.com/jojojames/fussy
        
         | binary132 wrote:
         | I have come to really think that a big problem in the open
         | source world is the non-standardization of interfaces. Text
         | over stdio and communicating processes is just not the
         | greatest; if every program standardized on C ABI library
         | protocols, and offered stdio and socket interfaces to them,
         | then suddenly the landscape of possibilities in software
         | composition would be way broader. Herding daemons and managing
         | docker containers when we have the linker and dynamic libraries
         | just doesn't feel sane or sanitary to me, especially outside of
         | the Linux shell. This is how we end up with 50 different
         | implementations of syntax parsers, fuzzy-finding, API clients,
         | etc.
        
           | gumby wrote:
           | > I have come to really think that a big problem in the open
           | source world is the non-standardization of interfaces. Text
           | over stdio and communicating processes is just not the
           | greatest...
           | 
           | We lost that battle in the late 70s/early 80s. It has nothing
           | to do with the open source world.
        
             | binary132 wrote:
             | Open source has everything to do with interoperability of
             | software.
        
               | gumby wrote:
               | The problem of ad hoc nonstandard text interfaces, in
               | both source-available and priority code far predated the
               | gnu manifesto, much less anything that happened since.
               | 
               | That's all.
        
               | gumby wrote:
               | s/priority/proprietary/
        
           | mickeyp wrote:
           | > C ABI library protocols, and offered stdio and socket
           | interfaces to them, then suddenly the landscape of
           | possibilities in software composition would be way broader
           | 
           | You've just invented a rudimentary and worse version of COM.
           | (There are advantages in not limiting yourself to low-level
           | tooling like ptys/pipes/sockets.)
           | 
           | https://en.wikipedia.org/wiki/Component_Object_Model
        
             | binary132 wrote:
             | What is worse about native C FFI and structs-as-messages
             | socket protocols as compared to the malebolge of Windows
             | APIs?
        
               | fwip wrote:
               | COM, the interface, is not the same as the conglomeration
               | of Windows APIs.
               | 
               | A web-dev example might be that CSS, the language design,
               | is not the same as the ever-growing and inconsistent set
               | of properties that the browser uses to style documents.
        
           | Kamq wrote:
           | > C ABI library protocols, and offered stdio and socket
           | interfaces to them, then suddenly the landscape of
           | possibilities in software composition would be way broader.
           | 
           | I think it would have reduced composition in practice. Part
           | of what you get out of "text as the universal interface" is
           | tools that never heard of each other being able to work
           | together. Because there's only a couple types: string, maybe
           | number depending on the context, list (strings separated by
           | spaces or newlines) and record (single line of a csv/tsv
           | file), things can be kinda coerced into working together.
           | 
           | You could get this with a type system... if you restrict
           | yourself to at the most advanced List<String>, Map<String,
           | String>, but you've lost ~80% of your type system value. As
           | soon as anyone defines a custom struct, only tools that have
           | heard of that type (which, in practice, end up being tools
           | specifically made to work with it) can use it. Just using
           | text with a few conventions is a really high utility point on
           | the pareto curve for basically zero work.
           | 
           | I could see some benefit in getting a system defined Path/URL
           | type, but you'd really need to have a culture of sticking to
           | built in types, and a system that offers types to cover
           | basically every use-case.
        
       | cerved wrote:
       | I prefer vipe + vim
        
       | dbalatero wrote:
       | 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.
        
         | frfl wrote:
         | 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.
        
           | dbalatero wrote:
           | Yeah that's the stack I was running as well. I think we had
           | like 15 million LOC or more and it was useable.
        
             | flylikeabanana wrote:
             | 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.
        
               | frfl wrote:
               | 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).
        
               | flylikeabanana wrote:
               | 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.
        
               | dbalatero wrote:
               | 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?
        
               | flylikeabanana wrote:
               | > I guess you have to globally gitignore the projectile
               | file too to avoid committing them everywhere?
               | 
               | Indeed, in my global git ignore, same with other
               | workflow-specific stuff that nobody else at $WORK uses
        
               | mediumsmart wrote:
               | 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?
        
               | flylikeabanana wrote:
               | 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)))
               | 
               | [1] https://github.com/iyefrat/all-the-icons-completion
        
               | dbalatero wrote:
               | Alternatively if the monorepo has a way to denote when
               | you're in a new package (package.json, etc) you could key
               | off that too?
        
               | PuercoPop wrote:
               | I use project.el instead of projectile but yeah that is
               | exactly what I do. It is only a couple of lines.
               | 
               | https://github.com/PuercoPop/.emacs.d/blob/9d0b99d332d619
               | fe3...
        
         | Kalq wrote:
         | Give consult-rg with ripgrep and emacs a try. It's an excellent
         | combination.
        
         | senkora wrote:
         | I've found this article useful for understanding how to debug
         | performance issues in Emacs: https://www.murilopereira.com/how-
         | to-open-a-file-in-emacs/
        
           | bloopernova wrote:
           | Fantastic read, thank you for sharing!
        
         | fiddlerwoaroof wrote:
         | 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.
        
       | jrm4 wrote:
       | To go big here; I did Emacs for a year or two then gave it up
       | because -- despite being probably the most theoretically powerful
       | -- there's just too much friction.
       | 
       | I don't know if it's been given a name, but this new wave of
       | (usually Rust) shell tools that are great and seem obvious in
       | retrospect (fzf, rg, etc) strongly feel like they're doing
       | exactly right what Emacs has "failed badly" at.
       | 
       | edit: And now that I think about it, the "failure of Emacs" thing
       | feels a lot not going the old "Unix way, do one thing and speak
       | text" ideals?
        
         | Barrin92 wrote:
         | I don't really understand the point being made. Virtually every
         | popular unix-like command line tool integrates with the popular
         | Emacs frontends. It's as trivial as going `consult-ripgrep` or
         | `projectile ripgrep` and so on. There's significantly more
         | friction for me in praying I remember a hundred terminal
         | commands and tools than just having an actual UI.
        
           | jrm4 wrote:
           | I mean the other way around?
           | 
           | Living inside Emacs separates you from lots of "how everyone
           | else does it" over time and is hard to integrate with
           | "everything else" without TONS of work.
           | 
           | To avail yourself of the full power of Emacs, it demands more
           | "difference from everything else?"
        
             | orange-mentor wrote:
             | As a newcomer to Emacs in the past couple of months (my
             | second try), I think I agree with you that it's a lot of
             | work.
             | 
             | But for the Emacs fans who've had success, that work pays
             | them back because they can bend the editor to an extremely
             | bespoke workflow.
             | 
             | I'm unsure if it will work out for me long term but I can
             | sort of see the appeal. No other tool even attempts to be
             | what Emacs has become.
             | 
             | So yeah, it's different from every other approach I've
             | tried. But there's a chance it will work for me. Jury's
             | out, though, and I am only now realizing that I'm going to
             | have to put more effort into hacking my workflow than with
             | other things I've used (Kakoune, Neovim, sublime, etc)
        
             | lycopodiopsida wrote:
             | I've been on both sides: emacs only and fish + cli toolig +
             | neovim and there is certainly no "everyone" on the console
             | side. "Everyone" lives in VSCode. People using console
             | tooling do not invest less time into it compared to emacs
             | folks and each setup is no less individual than an init.el
        
             | dbalatero wrote:
             | I had a real "I wish magit was a TUI program and embeddable
             | in Neovim, Emacs, your tmux sidepane" moment the other day.
        
         | darkstarsys wrote:
         | No argument here, and I've been using emacs since around 1983.
         | It's a hobby and a way of life. But like any way of life, it's
         | for those who like that sort of thing.
        
       ___________________________________________________________________
       (page generated 2023-12-10 23:00 UTC)