eugen0329 / vim-esearch

Perform search in files easily
352 stars 12 forks source link

Filtering search results by path #174

Open ristillu opened 3 years ago

ristillu commented 3 years ago

I work on a large project. Sometimes my result set is large (e.g. 100 files). By default it feels like esearch is picking up my .gitignore, which I want it to do. When I get a result set sometimes I would then like to filter it down further by dynamically setting my exclude path. So I do <c-o> p and set some path. I can exclude a single file. When I do that search then seems to ignore my .gitignore, which is probably expected behavior. That is, my 100 files goes up to several hundred files when the path filter override is applied.

I can't get it exclude multiples however, even though you have examples implying that that should work. To demonstrate, if I have:

$ ls
a.txt b.txt c.txt
$ cat a.txt
asdfasdf
$ cat b.txt
asdfasdf
$ cat c.txt
asdfasdf
$ rg asdfasdf
c.txt
1: asdfasdf

b.txt
1: asdfasdf

a.txt
1: asdfasdf
$ rg asdfasdf -g '!b.txt' -g '!c.txt'
a.txt
1:asdfasdf

That last command is what I would like to achieve in esearch. So I open a file, do

<leader>ff
<c-o>
p
'!b.txt !c.txt'

or many other combinations of commands (brackets for grouping and alternation etc), essentially let g:esearch.paths = '!b.txt !c.txt' and I get various errors or not what I want. Mostly the errors are along the lines of No such file or directory (os error 2)

On top of this, as I mentioned earlier even if I can get an explicit multiple path override to work I sort of need to continue to honor my .gitignore or else I will get many directories and artifacts that I don't care about included in my esearch result set. So I guess what I'm leading to is it would be fantastic if it's not too much work to extend esearch to allow filtering of the result files in addition to the ignore files. That would increase the utility of esearch immensely for me.

Potentially I could write my own function and mappings to override the adapters options? But if you have something up your sleeve that was part of esearch rather than my custom .vimrc that would be awesome.

I have set shell=/usr/bin/bash\ -O\ globstar\ -O\ extglob I have echo esearch#has#lua returning 1 I'm using ripgrep 12.1.1, vim 8.2-2549 I have a colleague using a recent neovim and rg who is trying to find a solution to the same problem in parallel so it's not vim specific.

eugen0329 commented 3 years ago

Thanks for the detailed report.

Debugging hint: you can see the executed command using :echo b:esearch.request.command.

  1. If you use extglob, all the extglobbing features that your bash build supports are available. You can use this post as a cheatsheet. Here are some examples:

    # Exclude doc/ directory and Makefile file from the results
    !(doc|Makefile)
    # Include vimscript files from autoload/ directory excluding subdirectories
    # and all lua files from lua/ directory including files in subdirectories
    autoload/*.vim lua/**/*.lua

    You can learn how extglob syntax works by running:

    bash -O globstar -O extglob # enter bash shell
    echo !(doc|Makefile)        # output matched files and directories
  2. Gitignore has almost nothing to do with the plugin as it's maintained by the search util you use. You can pass raw options directly to the search util using let g:esearch = {'adapters': {'rg': {'options': '--sort path --no-ignore-vcs'}}}

  3. About custom mappings. Yes, you a highly encouraged to create your own mappings. That's the point of the api. You can pass a dict to esearch#init using the config names as in g:esearch to override it. Examples:

    " Search in modified files only
    nnoremap <leader>fm :call esearch#init({'paths': '`git ls-files --modified`'})<cr>
    " Search in git history
    nnoremap <leader>fl :call esearch#init({'paths': esearch#xargs#git_log()})<cr>
    " Search excluding b.txt and c.txt files
    nnoremap <leader>fe :call esearch#init({'paths': '!(b.txt|c.txt)'})<cr>
    " Search in libs
    nnoremap <leader>fv :call esearch#init({'paths': '**/node_modules'})<cr>

    The rule of how b:esearch in a results window is composed is the following: b:esearch = {...default_conf, ...g:esearch, ...esearch_init_kwargs} (default configurations have the lowest prio and esearch#init arguments have the highest).

eugen0329 commented 3 years ago

Another problem is that paths option seems to override dot-ignore files. We can get around it by implementing another menu entry to set --glob GLOB option.

Since you can specify multiple glob patterns, my proposal is to try to go with the input kind similar to the one that is used with git-grep adapter. <c-p> appends another pattern, <bs> within the empty input drops the last pattern and <enter> submits the request. The idea is similar to select2 tags input.

E.g. type :call esearch#init({'adapter': 'git'})<enter>pattter<c-p>exclude-pattern<CR> to search using git grep -e 'pattern' --and --not -e 'exclude-pattern' command.

What do you think about this design?

ristillu commented 3 years ago

Thanks for the quick feedback eugen0329. Let me play with it a bit tomorrow or the next day and think about it.

Just one more data point - with the information you gave just now I tried something different. Earlier today I was working in a git/project/ structure and just now I tried in a clean sandbox/ structure and got different behaviour with the a.txt b.txt c.txt structure. So there is definitely some conflict happening with my git/project/.gitignore.

In both locations with the exact same command sequence:

gvim a.txt
<leader>ff
<c-o>
p
!(b.txt|c.txt)<CR>
<esc>

That works in sandbox/ and doesn't work in git/project/. In the former it does exactly what I was requesting and exactly what you were probably scratching your head about. In the latter the filtering doesn't work plus I get an extra file from some other artifact that was clearly excluded by my git/project/.gitignore before I modify the path.

In both circumstances the output of :echo b:esearch.request.command is the same: rg --fixed-strings --ignore-case --no-heading --color=never --line-number --with-filename --follow -e 'asdfasdf' -- !(b.txt|c.txt) I guess in the sandbox one it's just operating locally but in the git one it's traversing the whole project tree's parents until it reaches .git and then navigating the tree. I'm not sure why it returns all of a.txt b.txt c.txt plus another file though - i.e. why it's not honoring the exclude pattern.

Thanks for the info and as I say let me play with it some more over the next day or few and see what I learn.

eugen0329 commented 3 years ago

Does rg --glob '!b.txt' --glob '!c.txt' asdfasdf work as you expect?

UX hint: most of menu entries work with control btn pressed as well, e.g. both <c-o>p and <c-o><c-p> open the input.

ristillu commented 3 years ago

Yes.

  1. plain CLI rg --fixed-strings --ignore-case --no-heading --color=never --line-number --with-filename --follow -e 'asdfasdf' -- !(b.txt|c.txt) works in a sandbox
  2. plain CLI rg --fixed-strings --ignore-case --no-heading --color=never --line-number --with-filename --follow -e 'asdfasdf' -- !(b.txt|c.txt) works in a git repo
  3. plain CLI rg asdfasdf --glob '!b.txt' --glob '!c.txt' works in a sandbox
  4. plain CLI rg asdfasdf --glob '!b.txt' --glob '!c.txt' works in a git repo
  5. esearch with !(b.txt|c.txt) works in a sandbox
  6. esearch with !(b.txt|c.txt) doesn't work in a git repo

I will try tomorrow (getting late here) to disable some other plugs in case they are interfering. I'm looking at vim debug logs now, which I'm sure you know can be quite verbose and I'm not great at deciphering them quickly.

ristillu commented 3 years ago

I disabled all plugs except eugen0329/vim-esearch and mileszs/ack.vim. It didn't help and at level 9 verbosity the vim log isn't informative. It notes my esearch path change but nothing diagnostic pointing towards anything special about directory navigation or being inside a git repo or anything.

eugen0329 commented 3 years ago

I'm not sure that we can unite extglobs and ignore files, as they seem to rely on search util internals.

Please, switch to development branch and try <c-o>g input using the controls I described above. It can be a bit unstable, as it's just a POC, but it already works for rg, ag and pt for most test cases I've come up with. Your feedback and any suggestions are highly appreciated.

ristillu commented 3 years ago

Before I do so, here's another interesting thing - I can reproduce it in your repo.

$ git clone https://github.com/eugen0329/vim-esearch
$ cd vim-esearch
$ mkdir -p sandbox
$ cd sandbox
$ cp ~/sandbox/* .
$ ls
a.txt b.txt c.txt
$ gvim a.txt
<leader>ff
asdfasdf
<c-o><c-p>
!(b.txt|c.txt)<CR>
<esc>

and I get all three files listed. Whereas the same strategy works as I would hope in the ~/sandbox directory i.e. it filters out b.txt and c.txt and only a.txt is listed. In the git repo it also doesn't work if I try to add a single exclusion to the filter with !(b.txt).

So you should be able to reproduce the behavior I'm seeing. I'm on a fairly vanilla Linux red hat-ish system.

I'll switch to dev branch now and try your suggestions. Thanks!

ristillu commented 3 years ago

Unfortunately the development branch and the glob filtering doesn't quite work. If I specify a single file to exclude, like !b.txt, that works. So that is an improvement over the master branch behavior of using the path filter and the .gitignore confusing things (i.e. a single exclude also didn't work, as per my previous comment).

If I want multiples though I can't figure it out. I tried:

!b.txt !c.txt
'!b.txt !c.txt'
!b.txt --glob !c.txt

etc. The last one was me trying to trick your code and it actually looked like it might work, since the <c-o> menu said:

> g      [!/] filter paths (--glob !b.txt --glob !c.txt)

but the actual command that :echo b:esearch.request.command showed was executed was unfortunately: rg --fixed-strings --ignore-case --no-heading --color=never --line-number --with-filename --follow --glob '!b.txt --glob !c.txt' -e 'asdfasdf' -- That is, it dragged the second glob inside single quotes.

I pushed the vim logs to debug level 99 and one thing that may be worth noting - tpope's fugitive is being used to find the git repo path.

Anyway I gave up on that and used your API and came up with a solution. I will refine it but it looks like this:

function! RG(...)
    let globber_options = b:esearch.adapters['rg'].options
    for glob in a:000
        let globber_options = globber_options . ' -g ' . glob
    endfor
    let b:esearch.adapters['rg'].options = globber_options
    call b:esearch.reload()
endfunction

and I can do:

$ gvim a.txt
<leader>ff
asdfasdf<CR>
:call RG('!b.txt','!c.txt')

within your vim-esearch repo and it works exactly as I want. I need to define a mapping and polish it a bit. It's clearly very brittle and dependent on me using rg etc and I'm clearly not a vimscripter but hey, it works.

I tried this with :%s/asdfasdf/xxxxxxxx/g commands on the resulting result set and it only applied to the files I had not filtered out (e.g. only a.txt) so it was all good

I'm still on your development branch but my function is no doubt fine with master too so I might revert.

ristillu commented 3 years ago

Refined solution (for now) looks like:

function! s:FilterEsearch(...)
    if exists("b:esearch")
    " See ~/git/vim-esearch/autoload/esearch/adapter/rg.vim
    " where the g:esearch.adapters.rg.options are originally set.
    " Using this function with no arguments to reset the options
    " will break if somewhere we try to set g:esearch.adapters.rg.options
    " and expect it to be honored.
    let l:default_options = '--follow'
    let l:filter = ''
    if a:0 == 0
        let l:filter = b:esearch.adapters.rg.options
        let b:esearch.adapters.rg.options = l:default_options
    else
        for l:glob in a:000
            let b:esearch.adapters.rg.options .= ' -g ' . l:glob
        endfor
        let l:filter = b:esearch.adapters.rg.options
    endif
    echo l:filter
    call b:esearch.reload()
    endif
endfunction

:command! -nargs=* Fil call s:FilterEsearch(<f-args>)

So you can call :Fil !b.txt and it will filter out one file. You can call it again with :Fil !c.txt and it will filter out both b.txt and c.txt. You can call it from scratch with :Fil !b.txt !c.txt and it will filter out both in one go. You can call it with no arguments and it will echo the arguments it has cached and set the rg options back to defaults. Each time it refreshes the esearch display after applying the filter state.

Four points:

  1. Maybe I will split out resetting/clearing into a separate function (maybe even echoing as well) in order to not destroy a valuable filter list. At the moment calling with no args means you see the previous args but you then destroy them. Perhaps I'll end up with:
    • Filter
    • ShowFilter
    • ClearFilter or something analogous. With my contrived example of a.txt b.txt c.txt with single line text it's working fine but if I want to pass complicated or many glob options to rg I won't want to accidentally blow them away.
  2. I don't know vimscript so I would prefer a less brittle way of resetting the stuff from g:esearch.adapters.rg.options. For me for now it's fine that it always just resets to --follows but if I ever (or if your plugin ever) wanted to set the global options to something else my filter would break that. At the moment I don't care much about that but I'm not designing an API here.
  3. Any set filter(s) remains in play after executing. So it could be confusing if you apply a filter, do some operations, forget to clear the filter, exit the current esearch and ten minutes later do another esearch and miss several files. I will think about how to overcome this. Probably hook into the initial <leader>ff workflow to reset the b:esearch.adapters.rg.options to default so that within a current esearch your cascading filters are applied but a fresh esearch has no filters applied.
  4. Obviously it's specific to rg. The concept probably extrapolates but casual readers will need to tailor to their search engine if they're not using rg.
eugen0329 commented 3 years ago

There was a minor rendering bug that could mislead you with that input. The principle of how it works is borrowed from select2 tags input. Please, pull and try it again.

Controls are: key what does
<c-p> push another glob pattern (or cycle through glob kinds if the pattern is empty).
<bs>, <c-w> pop the current glob pattern (if the glob string is empty, the same as select2 works).
<enter> submit the input and return to the menu.

The motivation is to prevent users from dealing with shell escaping where it's possible. So instead of inputting a string with --iglob a\ b --iglob c\\\\\n the plugin escapes globs automatically.

Your steps to input what you need:

<c-o><c-g>       # or <c-o>g to enter the input with globs
b.txt<c-p>c.txt  # your input should look like rg … --glob 'b.txt' --iglob 'c.txt
<enter>          # submit the globs
q                # leave the menu
asdasd<enter>    # submit the search pattern
ristillu commented 3 years ago

OK that works but I would prefer not to have to enter the search pattern twice and I'd prefer to reload the view after entering the globs.

ristillu commented 3 years ago

I.e. I'd like to:

<leader>ff
asdfasdf
<c-o><c-g>
!b.txt<c-p>!c.txt<cr>

(esearch list automatically applies the glob options and reloads my view)

q

(menu disappears and I'm left with the filtered, reloaded view)

I'm also ok with the view reload happening after the q. Is there any possibility of implementing that?

eugen0329 commented 3 years ago

Before I do so, here's another interesting thing - I can reproduce it in your repo

If you try to search within a repository and cd into a directory, the root is resolved to the repository root. You should use sandbox/!(b.txt|c.txt) or consider to tweak :h g:esearch.root_markers to prevent working directory enforcing.

:call RG('!b.txt','!c.txt')

It already supports recognizing globs from strings, so you should just try nmap <leader>fg <cmd>call esearch#init({'globs': '--glob a --iglob b'})<cr>. It'll be parsed, validated and you'll be notified if the input is incorrect.

I would prefer a less brittle way of resetting the stuff from

Options resetting and memoizing is done using :h g:esearch.remember. By default, almost any option is remembered, but you can configure it manually, e.g. by using nmap <leader>fg <cmd>call esearch#init({'remember': ['last_pattern', 'globs'], 'globs': '--glob a --iglob b'})<cr>.

So it could be confusing if you apply a filter, do some operations, forget to clear the filter

All the configurations that affect the results set are listed in the statusline. If you try call esearch#init({'paths': '/etc docs/ specs/', 'cwd': '/tmp/vim-esearch', 'filetypes': 'lua sh', 'globs': '--glob autoload/* --iglob plugin/*'}), you will see the following in the statusline: In <.lua> <.sh> 📂 /tmp/vim-esearch/{ docs/, specs/ } 📂 /etc <glob autoload/*> <glob plugin/*>

eugen0329 commented 3 years ago

I'm also ok with the view reload happening after the q. Is there any possibility of implementing that?

Do you mean reloading the results window when <enter> is pressed on globs submitting and you get to the menu, but before leaving it?

ristillu commented 3 years ago

Yes! That would be awesome. I guess it would require in the background an async invocation of the full rg command (with globs) again. So there might be a 100ms delay or whatever, but you'd see the effect of what you've done.

That plus not having to enter asdfasdf to get into an esearch context and again on exiting the menu would be great.

The repo root stuff is not a problem since we have a working solution now in both the hacky vimscript I threw together and your solution.

Thanks for the tips on history, I'll investigate.

eugen0329 commented 3 years ago

So there might be a 100ms delay or whatever, but you'd see the effect of what you've done.

I added a forced execution on leaving an input. Please, update the plugin.

The repo root stuff is not a problem since we have a working solution now in both the hacky vimscript I threw together and your solution.

I am not satisfied with the design of UI code at the moment, so I'm going to change the architecture of it to be able to create easily create custom menu entries and inputs or drop unwanted defaults.

Thanks for the tips on history, I'll investigate.

Note that unlike regular history where you can traverse back and forth, this is just recording the values in g:esearch when the search is submitted. Although, I think it's enough at the moment and no overcomplicating is required here.

ristillu commented 3 years ago

From within ~/sandbox/ it works OK except I have to either q or <esc> out of the menu and it leaves me in a rg >>> state. But it is dynamically refreshing.

From within ~/git/vim-esearch/sandbox/ it is back to the previous problem - the filter is incrementally applied and the view is refreshed however it is dragging in all the .gitignore stuff. After I apply the first filter (!b.txt) I get 1467 line matches in 26 files. After <c-p>!c.txt I get 33249 lines in 196 files. And it also leaves me in a rg >>> limbo state as per outside the repo.

eugen0329 commented 3 years ago

From within ~/git/sandbox/ it works OK except I have to either q or out of the menu and it leaves me in a rg >>> state. But it is dynamically refreshing.

Does updates happen when press j/k? The problem is that we can get only the first portion of the data since getchar() call is blocking. But I'll try to investigate how we can get around it.

After I apply the first filter (!b.txt) I get 1467 line matches in 26 files. After !c.txt I get 33249 lines in 196 files

Can you provide the command it builds please?

infinite-ops commented 3 years ago

@ristillu wrote:

Refined solution (for now) looks like:

function! s:FilterEsearch(...)
    if exists("b:esearch")
    " See ~/git/vim-esearch/autoload/esearch/adapter/rg.vim
    " where the g:esearch.adapters.rg.options are originally set.
    " Using this function with no arguments to reset the options
    " will break if somewhere we try to set g:esearch.adapters.rg.options
    " and expect it to be honored.
    let l:default_options = '--follow'
    let l:filter = ''
    if a:0 == 0
        let l:filter = b:esearch.adapters.rg.options
        let b:esearch.adapters.rg.options = l:default_options
    else
        for l:glob in a:000
            let b:esearch.adapters.rg.options .= ' -g ' . l:glob
        endfor
        let l:filter = b:esearch.adapters.rg.options
    endif
    echo l:filter
    call b:esearch.reload()
    endif
endfunction

:command! -nargs=* Fil call s:FilterEsearch(<f-args>)

So you can call :Fil !b.txt and it will filter out one file. You can call it again with :Fil !c.txt and it will filter out both b.txt and c.txt. You can call it from scratch with :Fil !b.txt !c.txt and it will filter out both in one go. You can call it with no arguments and it will echo the arguments it has cached and set the rg options back to defaults. Each time it refreshes the esearch display after applying the filter state.

This works well for me and is just what I was missing with esearch. The ability to remove one or more files from the results from within the results.

ristillu commented 3 years ago

eugen the command it runs is e.g.: rg --fixed-strings --ignore-case --no-heading --color=never --line-number --with-filename --follow --glob '!b.txt' --iglob '!c.txt' -e 'asdfasdf' -- but it must be doing something very different (as you mentioned before) when run in a git repo vs run in a sandbox. I don't know rg, I only installed it yesterday.

You can reproduce yourself (if you have a linux box) with:

$ git clone https://github.com/eugen0329/vim-esearch
$ cd vim-esearch
$ mkdir -p sandbox
$ cd sandbox
$ pwd
~/git/vim-esearch/sandbox
$ cat <<EOF > a.txt
> asdfasdf
> EOF
$ cp a.txt b.txt
$ cp a.txt c.txt
$ gvim a.txt

with Plug 'eugen0329/vim-esearch', { 'branch': 'development' } or whatever plugin manager you use. And then that's exactly the contents I have and am playing with right now, not my project's git repo but yours.

And then I'm following various instructions from this thread to try out your and my experiments.

eugen0329 commented 3 years ago

From within ~/sandbox/ it works OK except I have to either q or out of the menu and it leaves me in a rg >>> state. But it is dynamically refreshing.

It was a bug. Please, update the plugin and try it again.

You can reproduce yourself (if you have a linux box) with:

Lets clearly defined all the test cases

# Setup
$ git clone https://github.com/eugen0329/vim-esearch /tmp/vim-esearch && cd /tmp/vim-esearch
$ mkdir -p sandbox && cd sandbox
$ echo 'asdfasdf' > {a,b,c}.txt
$ cp -r . /tmp/sandbox

# Case 1 (in the repo, no gitignore)
$ cd /tmp/vim-esearch/sandbox && gvim
:call esearch#init({'globs': '--glob !b.txt --glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
#
# sandbox/a.txt
#    1 asdfasdf

# Case 2 (in the sandbox)
$ cd /tmp/sandbox && gvim
:call esearch#init({'globs': '--glob !b.txt --glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
# 
# a.txt
#    1 asdfasdf

# Case 3 (in the repo, ignore b.txt using gitignore)
$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'globs': '--glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
# 
# sandbox/a.txt
#    1 asdfasdf
$ rm .gitignore

# Case 4 (in the repo, skip gitignore files)
$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'globs': '--glob !c.txt', 'pattern': 'asdfasdf', 'adapters': {'rg': {'options': '--no-ignore-vcs'}}, 'remember': 1})
# Matches in 2 lines, 2 files. Finished.
# 
# sandbox/b.txt
#    1 asdfasdf
# 
# sandbox/a.txt
#    1 asdfasdf
$ rm .gitignore

If it works differently in your repo, then you have something that prevents it from searching. Can you share the output of rg --glob '**/.gitignore' -e '[abc].txt' please?

ristillu commented 3 years ago

It was a bug. Please, update the plugin and try it again.

Updated

$ git clone https://github.com/eugen0329/vim-esearch /tmp/vim-esearch && cd /tmp/vim-esearch
$ mkdir -p sandbox && cd sandbox
$ echo 'asdfasdf' > {a,b,c}.txt
$ cp -r . /tmp/sandbox
Done

```# Case 1 (in the repo, no gitignore)
$ cd /tmp/vim-esearch/sandbox && gvim
:call esearch#init({'globs': '--glob !b.txt --glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
#
# sandbox/a.txt
#    1 asdfasdf
Confirmed

```# Case 2 (in the sandbox)
$ cd /tmp/sandbox && gvim
:call esearch#init({'globs': '--glob !b.txt --glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
# 
# a.txt
#    1 asdfasdf
Confirmed

```# Case 3 (in the repo, ignore b.txt using gitignore)
$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'globs': '--glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
# 
# sandbox/a.txt
#    1 asdfasdf
Confirmed

```# Case 4 (in the repo, skip gitignore files)
$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'globs': '--glob !c.txt', 'pattern': 'asdfasdf', 'adapters': {'rg': {'options': '--no-ignore-vcs'}}, 'remember': 1})
# Matches in 2 lines, 2 files. Finished.
# 
# sandbox/b.txt
#    1 asdfasdf
# 
# sandbox/a.txt
#    1 asdfasdf
Confirmed

Can you share the output of `rg --glob '**/.gitignore' -e '[abc].txt'` please?

$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore $ rg --glob **/.gitignore -e '[abc].txt' .gitignore 1:b.txt

eugen0329 commented 3 years ago

Your problem seems to be that rg doesn't respect .gitignore when globs are used:

$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'adapter': 'rg', 'globs': '--glob !c.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 2 lines, 2 files. Finished.
# 
# sandbox/b.txt
#    1 asdfasdf
# 
# sandbox/a.txt
#    1 asdfasdf
$ rm .gitignore

My suggestion is to try switching to ag as it looks like overruling .gitignore statements is the feature of rg:

$ cd /tmp/vim-esearch/sandbox && echo 'b.txt' > .gitignore && gvim
:call esearch#init({'adapter': 'ag', 'globs': '--ignore b.txt', 'pattern': 'asdfasdf', 'remember': 1})
# Matches in 1 line, 1 file. Finished.
# 
# sandbox/a.txt
#    1 asdfasdf
ristillu commented 3 years ago

Thanks eugen. I don't have a strong preference for rg vs ag either way so I'll have a think about it and a play with the stuff you implemented with ag vs my hacky vimscript with rg.

eugen0329 commented 3 years ago

Don't forget to pull development branch again. There're some improvements including previewing files matched by the globs you entered and live updates of the search window.

There is also a plan to improve the UX of the globs input to allow not just push and pop patterns, but to make changes at an arbitrary position. Feel free to share you ideas on how to make it better, including in your particular case.