hrsh7th / cmp-cmdline

nvim-cmp source for vim's cmdline
MIT License
550 stars 42 forks source link

:! (colon exclamation mark) in command line hangs #24

Closed manuelmuehlig closed 1 year ago

manuelmuehlig commented 2 years ago

Hi,

here is how to reproduce the issue:

  1. Open any file
  2. Type :!

I have cmp-cmdline added with:

cmp.setup.cmdline(':', {
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline' }
  })
})

Results: nvim-cmp hangs and can only be stopped with Ctrl-C. Error message below.

E5500: autocmd has thrown an exception: Vim(lua):E5108: Error executing lua Keyboard interrupt^@stack traceback:^@^I[C]: in function 'getcompletion'^@^I.../share/nvim/pl
ugged/cmp-cmdline/lua/cmp_cmdline/init.lua:13: in function 'exec'^@^I.../share/nvim/plugged/cmp-cmdline/lua/cmp_cmdline/init.lua:68: in function 'complete'^@^I...el/.loc
al/share/nvim/plugged/nvim-cmp/lua/cmp/source.lua:290: in function 'complete'^@^I...nuel/.local/share/nvim/plugged/nvim-cmp/lua/cmp/core.lua:250: in function 'complete'^
@^I...nuel/.local/share/nvim/plugged/nvim-cmp/lua/cmp/core.lua:163: in function 'autoindent'^@^I...nuel/.local/share/nvim/plugged/nvim-cmp/lua/cmp/core.lua:155: in funct
ion 'on_change'^@^I...nuel/.local/share/nvim/plugged/nvim-cmp/lua/cmp/init.lua:301: in function 'callback'^@^I...al/share/nvim/plugged/nvim-cmp/lua/cmp/utils/autocmd.lua
:31: in function 'emit'^@^I[string ":lua"]:1: in main chunk

Expected result: Not hanging, being able to type a system command

RnYi commented 2 years ago
  cmp.setup.cmdline(':', {
    sources = cmp.config.sources({
      { name = 'path' }
    }, {
      { name = 'cmdline', keyword_pattern=[=[[^[:blank:]\!]*]=]}
    })
  })

I find this keyword_pattern can give a help

k-times-c commented 2 years ago

@RnYi -- thanks for the help. Can you point to the documentation on how I could improve on this regex to include the following cases that hang?

w ! python '<,'>w ! python read! ls '<,'>r! ls

fredizzimo commented 2 years ago

It does not seem to completely hang, but it takes a long time to fill. And when it does it fills all the possible commands that you can run. So it's probably blocking searching the whole path for executables. This should probably at least be asynchronous, and also not trigger completion unless you have typed at least 1 character.

But even then it's slow, since my normal zsh shell completion is basically instant for a one char completion. But that's not a problem of this plugin, trying to complete without the plugin by pressing tab is just as slow, so there's something that Neovim does badly here.

steveclarke commented 2 years ago

Are you using WSL? I notice in my WSL that my Windows path is mixed in with my WSL/Ubuntu path. I think the completion is enumerating my entire Windows path, including hundreds of .dll files.

rxw1 commented 2 years ago

Are you using WSL? I notice in my WSL that my Windows path is mixed in with my WSL/Ubuntu path. I think the completion is enumerating my entire Windows path, including hundreds of .dll files.

Your hint helped me to figure this out. Thank you.

I had the same problem while using WSL. Per default WSL appends the Windows path (%PATH or $Env:Path) to your the path of your shell. This behavior can be configured in /etc/wsl.conf:

# Set whether WSL supports interop process like launching Windows apps and
# adding path variables. Setting these to false will block the launch of
# Windows processes and block adding $PATH environment variables.
[interop]
#enabled = false
appendWindowsPath = false

After setting appendWindowsPath to false and restarting WSL the issue is resolved and there is no noticeable lag in completing shell commands via neovim's command line anymore.

Hope that helps.

steveclarke commented 2 years ago

Thanks for that info @rwilhelm ! I'll give that a try. I have a feeling I'll have to manually add some Windows paths back in so my win32yank.exe, code, etc. still work.

bva99 commented 2 years ago

I'm using Powershell in Windows and : searches are okay, but :! searches take forever.

Is there a way to differentiate between : and :!? I would like to add keyword_length=3 only if :! is used, but let keyword_length=1 (the default) for :<something that does not start with !>.

I'm trying to do something like this:

-- exclusively for :, without !, uses the default keyword_length
cmp.setup.cmdline(':', {
  mapping = cmp.mapping.preset.cmdline(),
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline', keyword_pattern=<something that excludes :! ?> }
  })
})
--- for :!, sets keyword_length to 3
cmp.setup.cmdline(':!', {
  mapping = cmp.mapping.preset.cmdline(),
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline', keyword_pattern=<something that allows for :!>, keyword_length=3 }
  })
})

But I don't know how to program this. For now, I just set keyword_pattern=[=[[^[:blank:]\!]*]=], keyword_length=3 using the default : configuration.

sys9kdr commented 2 years ago

I have a same issue on WSL2. It fixed by @bva99 's idea. Thank you!

habibbhutto commented 1 year ago

@bva99's idea is a good workaround. However, it does lag a bit and causes the CPU spike while going through the paths in WSL. Increasing the keyword_length to 4 improves it significantly.

Additional tricks

Someone might find the following tricks useful.

This allows skipping cmdline completion for a given !command.

Let's say we want to run !docker ps -a.

1 Prefix !docker ps -a with some text and then remove it. Step 1 type it as :n|!docker ps -a Step 2 remove n and | :!docker ps -a Step 3 hit the return key

2 Use the terminal to run commands Use :new|term instead of :! You can run :new|term docker ps -a instead of !docker ps -a When you are done, you can close the terminal window with the usual keymap ZQ or ZZ.

changye-chen commented 1 year ago

@rwilhelm 's method solved my problem

hrsh7th commented 1 year ago

Fixed. You can modify ignore_cmds option.

nick-esqueda commented 1 year ago

@hrsh7th Hi! Is there currently any way to use wildcards or some sort of regex in the strings provided to the ignore_cmds property?

I'd like to ignore commands such as "read !cat file.txt", because currently everything hangs once ! is typed, as everyone else explained. Something like this:

        option = {
            ignore_cmds = { 'Man', '!', '*!*' }
        }

Is this currently possible?

trev-dev commented 1 year ago

Are you using WSL? I notice in my WSL that my Windows path is mixed in with my WSL/Ubuntu path. I think the completion is enumerating my entire Windows path, including hundreds of .dll files.

Your hint helped me to figure this out. Thank you.

I had the same problem while using WSL. Per default WSL appends the Windows path (%PATH or $Env:Path) to your the path of your shell. This behavior can be configured in /etc/wsl.conf:

# Set whether WSL supports interop process like launching Windows apps and
# adding path variables. Setting these to false will block the launch of
# Windows processes and block adding $PATH environment variables.
[interop]
#enabled = false
appendWindowsPath = false

After setting appendWindowsPath to false and restarting WSL the issue is resolved and there is no noticeable lag in completing shell commands via neovim's command line anymore.

Hope that helps.

This works but it kinda breaks WSL clipboard interop