Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question. How to include dynamic args to live_grep #167

Closed
LoydAndrew opened this issue Oct 5, 2021 · 22 comments
Closed

Question. How to include dynamic args to live_grep #167

LoydAndrew opened this issue Oct 5, 2021 · 22 comments
Labels
feature request New feature question Further information is requested

Comments

@LoydAndrew
Copy link

I want to include dynamic args for live_grep, for example in vim-clap plugin in grep provider input you can specify actions *.ts and it will translate query to rg -g "*.ts" "actions". Or in emacs world there is an ivy-plugin where in rg you can specify actions -- -t ts and achieve the same behaviour. Can we have something like this?

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 5, 2021

You can modify rg_opts or even send an entire new command to live_grep, one of these options should work for your use case:

:lua require'fzf-lua'.live_grep({ rg_opts = “…” })

Another example:

:lua require'fzf-lua'.live_grep({ cmd =rg …” })

You can even provide raw_cmd instead which will be sent without any processing or escaping to fzf directly (so you have to shell escape it yourself).

@ibhagwan ibhagwan added the question Further information is requested label Oct 5, 2021
@LoydAndrew
Copy link
Author

Okay, but lua require'fzf-lua'.live_grep({ rg_opts = “-g '*.ts'” }) is a prefiltering command. I want to be able to use it dynamycally in input like this
Rg> actions -q "*.ts"<
or something like Rg> actions | *.tx<

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 5, 2021

I see, I think you might need a custom script for that, see this discussion about using the glob feature #31

@LoydAndrew
Copy link
Author

Yeah, I guess that's the only way for now, thanks.

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 6, 2021

3b24fe4

In the latest commit I added the option to supply cmd_fn which will callback every time fzf-lua wants to run rg, this happens only at the first call of every live_grep_native or grepXXX commands (which doesn't solve this use case).

BUT live_grep calls this function each time the query changes (to retrieve the next rg command), which means we can solve this use case with live_grep (and live_grep_resume - same code, different params), replicating the vimrg code from @fanliver:

require'fzf-lua'.setup {
  grep = {
    cmd_fn = function(opts, query, _)
      local parts = vim.split(query, ">")
      local iglob = ""
      if #parts > 1 then
        for i=1,#parts-1 do
          iglob = iglob .. (" --iglob %s"):format(vim.fn.shellescape(parts[i]))
        end
      end
      local cmd = ("rg %s %s -- %s"):format(opts.rg_opts, iglob,
        vim.fn.shellescape(require'fzf-lua.utils'.rg_escape(parts[#parts])))
      -- print(cmd)
      return cmd
    end,
  },
}

Note that without further modifications this will mess up your live_grep_native, but you can always remove the cmd_fn from global options and create a mapping that does this specifically for live_grep:

:lua require'fzf-lua'.live_grep({ cmd_fn = function(opts, query, _)
...
end })

@ibhagwan ibhagwan reopened this Oct 6, 2021
@ibhagwan
Copy link
Owner

ibhagwan commented Oct 6, 2021

Btw, this is just a quick proof of concept code, tomorrow I’ll add something a bit more robust with customization under a new provider: live_grep_glob.

@ibhagwan ibhagwan added the enhancement New feature or request label Oct 6, 2021
@ibhagwan
Copy link
Owner

ibhagwan commented Oct 6, 2021

b9c0322 this adds the live_grep_glob provider with 2 new setup options under grep:

  grep = {
    glob_flag           = "--iglob",  -- for case sensitive globs use '--glob'
    glob_separator      = "%s%-%-"    -- query separator pattern (lua): ' --'
  }

The default separator is ' --' (space, dash, dash), glob parsing only starts after it detects the full 3 character pattern (so you can still search for dashes or spaces), can be easily modified, just remember it's a lua string pattern so special characters have to be specified the lua way.

Below is a demo of how it works, I printed the command below the status line so you can see how the command is dynamically modified with each keypress and the corresponding rg command that is sent:
fzf-glob

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 6, 2021

@LoydAndrew, @fanliver I'll leave this issue open for now until you guys let me know if this works fine and covers all use cases (including customization)?

@haphamdev
Copy link

@ibhagwan
Thank you very much for a nice feature.
I have just tested live_grep_glob. It works well even with multiple globs. 💯
However, I had to escape \- for the dash. Is there anyway to avoid escaping for dash character?

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 7, 2021

@ibhagwan
Thank you very much for a nice feature.
I have just tested live_grep_glob. It works well even with multiple globs. 💯
However, I had to escape \- for the dash. Is there anyway to avoid escaping for dash character?

You don’t have to escape dash as a separator (see my screencast, it’s not escaped), but you do have to escape it to search for it literally as it’s a regex special character like + or *, etc.

EDIT: actually if you wanna add dash into the glob I can make sure the glob arguments are escaped, lmk.

@LoydAndrew
Copy link
Author

Works great for me.

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 7, 2021

Works great for me.

Great!

if you wanna add dash into the glob I can make sure the glob arguments are escaped, lmk.

Before I close this, @fanliver can you let me know which character's you'd like escaped inside the glob and what is the use case? what is the exact use case for adding - in the glob? simple inlcude/exclude?

@haphamdev
Copy link

Sometimes, I look for the command line argument in shell script or some text in the code with hyphen in the name.
It's totally OK for me to use regex for search and escape the special characters. So don't worry. :) Thank you for the nice feature.

@ibhagwan
Copy link
Owner

ibhagwan commented Oct 9, 2021

Alright, then I guess we can close this.

@nyngwang
Copy link
Contributor

Could we have something like live_grep_glob_resume?

@ibhagwan
Copy link
Owner

Could we have something like live_grep_glob_resume?

Don't need a special command for that, just change your mapping to:

:lua require'fzf-lua'.live_grep_glob({ continue_last_search = true })
-- live_grep_resume is just a shortcut too:
:lua require'fzf-lua'.live_grep({ continue_last_search = true })

@nyngwang
Copy link
Contributor

nyngwang commented Dec 16, 2021

@ibhagwan Thank you! (and I just notice that this option is not shown on README.md.)

@nyngwang
Copy link
Contributor

@ibhagwan How to use glob without manually adding * between the path keyword I want to search, i.e. I can write ' -- foo' instead of -- *foo*?

@ibhagwan
Copy link
Owner

@ibhagwan How to use glob without manually adding * between the path keyword I want to search, i.e. I can write ' -- foo' instead of -- *foo*?

You’d have to create your own custom implementation, the * is standard wildcard syntax and is controlled by rg, not FzfLua, *foo means match any character before foo.

@nyngwang
Copy link
Contributor

nyngwang commented Dec 17, 2021

@ibhagwan My idea is that this can be done without changing the syntax of rg. But if we can let users type -- foo to mean -- *foo*. This way the -- * will not appear in the middle of typing a glob. In this way, those pre-excluded paths from the config won't be overwritten.

@nyngwang
Copy link
Contributor

nyngwang commented Dec 17, 2021

Then we can further design a syntax (as a quick example) --x ...(equivalent to the current -- ...) to let users add those wildcards intentionally. I think this will be more convenient, since the common case is that we don't know whether a key, say foo, is wrapped or not. Consider a more concrete example with two cases:

  1. No matter foo is wrapped by the other chars or not, this new -- foo(that fzf-lua would add * for us) will find the result since *foo* cases must include foo cases. Since "foo is wrapped by the other chars" is more common, the -- * will rarely appear when users are typing their glob, and thus so those static -- !bar predefined in the config will not be overwritten. Then users won't be confused by "Why these pre-excluded files appear again?" question.
  2. If the rare case that users do know that "OK, I'm sure that the path should look like .../foo/... and both pre-dots-path and post-dots-path do not include f or o". Then in this situation, they can then specifically use --x foo(maybe choose a more elegant symbol) to mean exactly 'foo' and can write something like -- foo* to use the powerful * when they really need it.

Indeed the current files_resume is exactly a good example to represent what I mean. I can have this query:

config !.docker !GitHub !Library tmux plugins

instead of this:

*config* !*.docker* !*GitHub* !*Library* *tmux* *plugins*

You can see that most of the time we need wildcard, so why not wrap the keyword with it for the users?

image

On the contrary, the current one is buggy:

  1. Want to search the only tmux folder:
    image

  2. No way:
    image

  3. Also give you nvim, what?:
    image

  4. Wait, why still match?
    image

@ibhagwan
Copy link
Owner

@ibhagwan My idea is that this can be done without changing the syntax of rg. But if we can let users type -- foo to mean -- foo. This way the -- * will not appear in the middle of typing a glob. In this way, those pre-excluded paths from the config won't be overwritten.

You can see that most of the time we need wildcard, so why not wrap the keyword with it for the users?

I understood what you meant and of course it can be done, anything can be done and you can make the parser do whatever you want and adjust to rg commands in any way you wish by writing your own glob parsing function.

I just personally think it's too much of a narrow use case and also very specific, it requires knowing how the format works and additonal "manual", I prefer to stay with the default syntax, as long as users know the argument passes "as is" into an --iglob they know what to do.

  1. Want to search the only tmux folder

I'm not even sure if this is possible, I think --iglob only supports filenames at the end of the path, or it requires to be written in a different way, I don't have enough experience with it, try man rg to see if this is even possible.

Wait, why still match?

Once the matches stop and the command returns no results I think the last known result is still displayed, use debug=true and use the underlying command in the shell and see what it returns, there really is nothing I can do about what rg returns.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants