vim-esearch
vim-esearch copied to clipboard
Filtering search results by path
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.
Thanks for the detailed report.
Debugging hint: you can see the executed command using :echo b:esearch.request.command
.
- 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
-
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'}}}
-
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 ing: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).
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?
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.
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.
Yes.
- 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 - 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 - plain CLI
rg asdfasdf --glob '!b.txt' --glob '!c.txt'
works in a sandbox - plain CLI
rg asdfasdf --glob '!b.txt' --glob '!c.txt'
works in a git repo - esearch with
!(b.txt|c.txt)
works in a sandbox - 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.
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.
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.
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!
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.
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:
- 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 ofa.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.
- 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. - 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 theb: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. - 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.
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
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.
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?
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/*>
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?
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.
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.
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.
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?
@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 bothb.txt
andc.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.
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.
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?
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
$ 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
$ 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
$ 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
$ 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
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
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.
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.