gyakovlev / fish-fzy

fzy inegration with fish. Search history, navigate directories and more. Blazingly fast.
MIT License
23 stars 6 forks source link

Add a function to locate directories #2

Closed Dietr1ch closed 6 years ago

Dietr1ch commented 6 years ago

It uses cd, locate and find as appropiate.

I'm still missing the binding, but it's not clear to me which one would be best, maybe we should just copy what fisherman/fzf does. What do you think?

gyakovlev commented 6 years ago

hey, it's much cleaner and better with latest commits. let me test some edge cases and I'll merge it a bit later. It's still kinda slow for large directories (like kernel source) but it's fine. I wonder if it's possible to use some fish non-blocking capability. just going to /usr/src/linux and typing find . -type d | fzy is almost instant. but not with this function for some reason. I'll investigate later and see what can be done.

Dietr1ch commented 6 years ago

Hey give fd a try. It's smarter about skipping files and gets a nice speed advantage while retaining relevant results.

I can list "all" files on my home in 0.5s with fd, and 3.5s with find (find ran afterwards and might have some advantage). A 4x difference remains when dropping the output.

gyakovlev commented 6 years ago

I heard a lot of good things about fd, will give it a try sometime. thanks!

I've been trying to optimize the find to be somewhat faster and here is what I came up with.

find * -name ".*" -prune -o -type d -print ^/dev/null I don't care about filtering fist 2 lines, because I'll rely on fzy finding the result. also filtering /proc or anything else is not needed, I do sometimes have to search something in that fs. can you test if on your side?

some points

1) -name is ~100x faster than -path for me. 2) don't call sed or tail, because clean relative path gets printed. just use the line. 4) fzy starts receiving find's output immediately in realtime 4) should be cross-platform and work everywhere.

even If I do cd / and hit ctrl+f it gives me results in a reasonable time (less than 3 second) if I use it in any nested dir I do get results instantly. by the time I type anything fzy will receive rest of the data.

My tests may not reflect true picture, because my storage is ridiculously fast (nvme drives with 3.5 GB/sec read speed) so I need something or someone else to test it before I push.

I also see really good results with /usr/bin/printf "%s\n" $PWD/**/ but it does not start printing until it returns, so cannot use real-time pipe to fzy with it.

fun fact:

if you type any dir name into fzy prompt, even if it's not in the results, fish will cd into that dir on hitting Return, which is great!

ctrl+f is now my favourite keybindng, how did I live before this? it's so fast and convenient.

Dietr1ch commented 6 years ago

I just tried that on my root and noticed that it goes through remote mounts, it needs the -mount flag, it seems to be available on BSD's find too, so it should work on starbucks laptops too. With that flag listing on my root takes 1.6s (a more modest ~550MB/s read sata ssd). This probably needs input from someone with an ancient rotating disk.

Also, it'll probably be much better to skip odd filesystems like proc, sysfs and others mentioned on mount. I noticed that fd does badly /. Probably I'll fill a bug there to check the filesystem first.

gyakovlev commented 6 years ago

tried fd, it's good ) a bit slower than my find line, but insignificantly so. have no problems with it on /.

on the find function: I find it REALLY useful for /sys, as sometimes I need to find that obscure dir in that jungle (something like devices/system/cpu/vulnerabilities or cgroup related). /proc is less useful but still fairly safe to search. especially if you mount /proc with hidepid=2. with hidepid=2 nothing you don't own gets shown in /proc.

another argument against -fstype is that it significantly slows down find. it runs several hundred times slower that way. and even if you go to /sys | /proc to find something, find -fstype will refuse to search completely.

-mount skips mountpoints but not /proc or /sys, some people have a LOT of mounts. on the other hand it makes sense to cd to possible target filesystem before searching in the first place. I use a lot of zfs and btrfs montpoints and it fails in that case.

maybe requiring an additional input from a user is a sane option. like hit enter to confirm search after ctrl+f if PWD is /

I'd really like to make it fast, because typical usage is just CDing withing ~ and slowing it down for some those edge cases makes me sad.

another possible problem like you mentioned is nfs/cifs/something else, slow as a turtle.

will test that new find line for a while, possibly with slow storage. I had a old raspberry pi lying somewhere, I guess one with an external usb mechanical drive is slow enough with target to test.

gyakovlev commented 6 years ago

what do you think of this? pretty simple, works for /proc and /sys, only searches / mountpoint in single edge case, and still fast for regular lookups.

    function __fzy_get_directory_list -d 'Get a list of directories using fd or find'
      if which fd >/dev/null ^/dev/null
        command fd . -t d
      else if test "$PWD" = '/'
        command find / -mount -name ".*" -prune -o -type d -print ^/dev/null
      else
        command find * -name ".*" -prune -o -type d -print ^/dev/null
      end
    end
Dietr1ch commented 6 years ago

Yes, it makes sense to special-case for unusual places to let the default perform well on the common ones, although maybe we want to do that when outside ~/. For the meantime I'd just try one that out to see how it behaves and then decide, worst case scenario we revert that change, but I think that at most it'll have adjustments as the idea seems fine to me.

I asked on fd repo and they told me to use --exclude to avoid network repos. Maybe we want to ignore based on odd filesystems after parsing mount. I'll play with that later next week.