Code Monkey home page Code Monkey logo

cmp-path's Introduction

cmp-path's People

Contributors

amarakon avatar daangoossens22 avatar dmitmel avatar eonpatapon avatar hrsh7th avatar joseflitos avatar py2048 avatar registergen avatar schrc3b6 avatar squat avatar tzachar avatar weizheheng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmp-path's Issues

Enabling cmp-path hides snippets that start with a slash

Using luasnip, snippets that start with a / or . character don't show up in the completion menu when the path source is enabled in the nvim-cmp config.

nvim-cmp config:

cmp.setup {
  snippet = {
    expand = function(args)
      require'luasnip'.lsp_expand(args.body)
    end,
  },
  mapping = {
    ['<Tab>'] = cmp.mapping.select_next_item(),
    ['<S-Tab>'] = cmp.mapping.select_prev_item(),
    ['<CR>'] = cmp.mapping.confirm({
      behavior = cmp.ConfirmBehavior.Replace,
      select = false,
    })
  },
  preselect = cmp.PreselectMode.None,
  confirmation = { get_commit_characters = function(_) return {} end },
  sources = {
    { name = 'luasnip' },
    { name = 'nvim_lsp' },
    { name = 'buffer' },
    { name = 'path' },
  },
}

luasnip config:

require('luasnip.loaders.from_snipmate').lazy_load({
  paths = "~/.config/nvim/snippets"
})

Example snippet definition:

snippet ///
	/// <summary>
	/// ${0}
	/// </summary>

Expected Behavior

Typing /// should show the defined snippet in the completion menu, however instead it only shows path completions for files at the root file system:

image

If I disable the { name = 'path' } source from the nvim-cmp config then it works as expected:

image

Is there some way to configure it so that both of these things can work together that I'm missing?

`/` on Windows only finds "Documents and Settings" in root dir.

"Documents and Settings" is an alias for the c:/Users/ and is available for compatibility with legacy applications. cmp-path resolves "Documents and Settings" to c:/Users/ dir.

The problem is that no other items in the root directory are accessible, and paths containing "Documents and Settings" are not actually resolvable.

Completion for path not starting with dot or slash or tilde

It seems that the plugin only matches paths starting with . or / or ~.
I'd like to have completion for any relative path, even if it starts with a letter or number.

For example:

  • ./foo/bar.txt - completion works
  • /foo/bar.txt - completion works
  • ~/foo/bar.txt - completion works
  • foo/bar.txt - completion does not work!

[Feature request] syntax highlighting in file preview

And I also viewed the code and came up with a naive idea to implement this.

Since the &ft of preview window is always markdown, so we can't change &ft (am I right?). But the preview content is actually a markdown code block, so we can make use of that.

Create a new buffer which is named after the file name, check the &ft of that buffer, and delete that buffer. The &ft is what we want.

Note: for some unknown reason, treesitter highlight is not available, but the regex-based highlight is loaded.

A better solution is greatly appreciated.

Overriding import statementes suggestions from a language server (`tsserver`)?

Hey! I was having some issues with cmp-path where it "overrides" import statements when trying to import from a directory.

Example:

Here I'm trying to import a file inside of modules/, and for that I type ./ in order to get the suggestions:

image

With cmp-path I expect to get suggestions from the lsp (tsserver) on top of the ones from cmp-path, because that's how I have it configured, but instead the suggestions from the lsp don't appear, and the ones from cmp-path do.

Is this bug or is it intended for cmp-path to "override" lsp suggestions? Or perhaps there is an issue with my setup?

cmp-path relative file

I can't get file path completions when working with relative paths unless I explicitly prefix the path with ./. ctrl+xctrx+f Omnicompletion brings up the right path

Regarding the regex NAME_REGEX

Why it's

'\\%([^/\\\\:\\*?<>\'"`\\|]\\)'

in the implementation?

Isn't that the * doesn't have special meaning in character class in vimscript so we don't need to escape it? The same question for the | before the close bracket ]. Thanks for your reading.

Complete paths relative to current file

It's often useful to be able to complete paths relative to the current file, not just relative to the working directory. For example, given this working directory:

.
├── lib
└── public
    ├── css
    │   └── screen.css
    ├── img
    │   ├── image-1.png
    │   ├── image-2.png
    │   └── image-3.png
    ├── index.html
    └── js
        ├── carousel.js
        └── login.js

It would be very useful to be able to complete paths like img/image-2.png when working on the index.html file. This works as expected in vscode.

I think that when cmp-path is suggesting relative paths, it should include paths relative to the current file. Or, at the very least, it should be an option to enable this.

Bugs in completion with `Insert` behaviour

Hi there!

I've faced issue, possibly related to my (probably wrong) workflow, but I don't know how to fix it properly:

I've "path" source enabled in "global" sources (I mean, not for just cmdline).
Also I have mappings that uses behavior = cmp.SelectBehavior.Insert for <Tab>, behavior = cmp.SelectBehavior.Select for <Up>/<Down>, and behavior = cmp.ConfirmBehavior.Replace, select = false for <CR>.

Meaning "if I'm okay with first suggested variant, I'll just press Tab, and won't bother to navigate anything and pressing Enter, and if it is not - I'll navigate to the appropriate variant and will press Enter on it to replace completion with proper one".

So, when I type :e fil<Tab>, and select the appropriate result, I'm getting cmdlne completed to :e files/. Next I want to navigate files inside it, and since cmp doesnt do that by typing <Tab> once more, I type / (as I did with deoplete time ago), and then <backspace> it, to somehow make cmp know that previous completion stage is over, and I want to complete further.
Unfortunately, it still shows only files/ as only available completion suggestion, and doesn't look inside...

And it will only work as expected after selecting proper suggeston (files/) with <CR>

So, it looks for me like cmp-path is intended to work with Insert behaviour on <CR>, and not-inserting over navigation 🤷‍♂️

P.S. also I hit another variant of #19 while tested things for that issue:

if I type . after files/, and will try to navigate over results, there would be: files/., files/.., and files/. Selecting first two inserts exactly what said, but choosing last one (files/) inserts files/.files/ 🤷‍♂️

double path comes up?

image
when i tab /, it comes two path hint, have no answer.

Here's my cmp config:

        -----------------------------------------------
        --- most important place for autocompletion ---
        -----------------------------------------------
        local cmp_status_ok, cmp = pcall(require, "cmp")
        if not cmp_status_ok then
          error("Load [cmp] Failed!")
          return
        end
        
        local luasnip_status_ok, luasnip = pcall(require, "luasnip")
        if not luasnip_status_ok then
          error("Load [luasnip] Failed!")
          return
        end
        
        local lspkind_status, lspkind = pcall(require, "lspkind")
        if not lspkind_status then
          error("Load [lspking] Failed!")
          return
        end
        
        -- use existing vs-code style snippets from friendly-snippets
        require("luasnip.loaders.from_vscode").lazy_load()


        -- completeopt, for cmp, else there will have two path completion
        vim.opt.completeopt = { "menu", "menuone", "noselect" }
      
        
        cmp.setup({
          -- cmp_luasnip
          snippet = {
            expand = function(args)
              luasnip.lsp_expand(args.body)
            end,
          },

          mapping = cmp.mapping.preset.insert({
            ["<C-k>"] = cmp.mapping.select_prev_item(), -- previous suggestion
            ["<C-j>"] = cmp.mapping.select_next_item(), -- next suggestion
            ["<C-y>"] = cmp.mapping.scroll_docs(-4),
            ["<C-e>"] = cmp.mapping.scroll_docs(4),
            ["<C-Space>"] = cmp.mapping.complete(),     -- show completion suggestions
            -- ["<C-a>"] = cmp.mapping.abort(),            -- close completion window
            ["<CR>"] = cmp.mapping.confirm({ select = true }),
            ["<Tab>"] = function(fallback)
              if cmp.visible() then
                cmp.select_next_item()
              else
                fallback()
              end
            end,
          }),

          -- sources for autocompletion
          sources = {
            { name = 'nvim_lsp' },
            { name = 'nvim_lua' },
            -- { name = 'vsnip' }, -- For vsnip users.
            { name = 'luasnip' }, -- For luasnip users.
            -- { name = 'ultisnips' }, -- For ultisnips users.
            -- { name = 'snippy' }, -- For snippy users.
            { name = 'buffer' },
            { name = 'path' },
          },
          
          -- configure lspkind for vs-code like icons
          formatting = {
            format = lspkind.cmp_format({
              maxwidth = 50,
              ellipsis_char = "...",
            }),
          },


          -- set window appearence
          window = {
            completion = cmp.config.window.bordered(),
            documentation = cmp.config.window.bordered(),
          },
          experimental = {
            ghost_text = true,
          },
        })
        
        -- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline({ '/', '?' }, {
          mapping = cmp.mapping.preset.cmdline(),
          sources = {
            { name = 'buffer' }
          }
        })

        -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
        cmp.setup.cmdline(':', {
          mapping = cmp.mapping.preset.cmdline(),
          sources = {
            { name = 'path' },
            -- { name = 'cmdline' }
          }
        })

Hidden files/directories are not shown

When I type . in PATH, it is expected to see all the files/dirs (like nvim-compe). However they are not appeared:
Screen Shot 2021-09-11 at 21 25 56

I am not really sure but when I change the line:

local include_hidden = string.sub(params.context.cursor_before_line, offset + 1, offset + 1) == '.'

to:

  local include_hidden = string.sub(params.context.cursor_before_line, offset , offset) == '.'

It fixed the issue and I can see all the hidden files
Screen Shot 2021-09-11 at 21 27 32

E5113: Error while calling lua chunk: vim.lua:63

Hello,

When using Plug 'hrsh7th/cmp-path'from nvim-cmp plugin example config, this error appears on every nvim start:

Error detected while processing /home/user/.local/share/nvim/plugged/cmp-path/after/plugin/cmp_path.lua:
E5113: Error while calling lua chunk: vim.lua:63: /home/user/.local/share/nvim/plugged/cmp-path/lua/cmp_path/init.lua:122: '=' expected near 'continue'
stack traceback:
        [C]: in function 'error'
        vim.lua:63: in function <vim.lua:57>
        [C]: in function 'require'
        ...hare/nvim/plugged/cmp-path/after/plugin/cmp_path.lua:1: in main chunk
cat ~/.config/nvim/init.vim

colorscheme ide_500
set number
set ignorecase
set smartcase
set hlsearch


" Plugins will be downloaded under the specified directory.
call plug#begin(has('nvim') ? stdpath('data') . '/plugged' : '~/.vim/plugged')

" Declare the list of plugins.
Plug 'neovim/nvim-lspconfig'

Plug 'hrsh7th/cmp-nvim-lsp'
Plug 'hrsh7th/cmp-buffer'
Plug 'hrsh7th/cmp-path'
Plug 'hrsh7th/cmp-cmdline'
Plug 'hrsh7th/nvim-cmp'

" For vsnip users.
Plug 'hrsh7th/cmp-vsnip'
Plug 'hrsh7th/vim-vsnip'

" For luasnip users.
" Plug 'L3MON4D3/LuaSnip'
" Plug 'saadparwaiz1/cmp_luasnip'

" For ultisnips users.
" Plug 'SirVer/ultisnips'
" Plug 'quangnguyen30192/cmp-nvim-ultisnips'

" For snippy users.
" Plug 'dcampos/nvim-snippy'
" Plug 'dcampos/cmp-snippy'


" List ends here. Plugins become visible to Vim after this call.
call plug#end()

set completeopt=menu,menuone,noselect

lua << EOF

--require'lspconfig'.gopls.setup{}

 -- Setup nvim-cmp.
  local cmp = require'cmp'

  cmp.setup({
    snippet = {
      -- REQUIRED - you must specify a snippet engine
      expand = function(args)
        vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
        -- require('luasnip').lsp_expand(args.body) -- For `luasnip` users.
        -- require('snippy').expand_snippet(args.body) -- For `snippy` users.
        -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users.
      end,
    },
    mapping = {
      ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
      ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
      ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
      ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
      ['<C-e>'] = cmp.mapping({
        i = cmp.mapping.abort(),
        c = cmp.mapping.close(),
      }),
      ['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
    },
    sources = cmp.config.sources({
      { name = 'nvim_lsp' },
      { name = 'vsnip' }, -- For vsnip users.
      -- { name = 'luasnip' }, -- For luasnip users.
      -- { name = 'ultisnips' }, -- For ultisnips users.
      -- { name = 'snippy' }, -- For snippy users.
    }, {
      { name = 'buffer' },
    })
  })

  -- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
  cmp.setup.cmdline('/', {
    sources = {
      { name = 'buffer' }
    }
  })

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
  cmp.setup.cmdline(':', {
    sources = cmp.config.sources({
      { name = 'path' }
    }, {
      { name = 'cmdline' }
    })
  })

  -- Setup lspconfig.
  local capabilities = require('cmp_nvim_lsp').update_capabilities(vim.lsp.protocol.make_client_capabilities())
  -- Replace <YOUR_LSP_SERVER> with each lsp server you've enabled.
  require('lspconfig')['gopls'].setup {
    capabilities = capabilities
  }
EOF

Nvim: NVIM v0.6.0
Lua: Lua 5.1.5
Distribution: Gentoo (Linux 5.10.76-gentoo-r1)

Stop working cmp

Hi.
In C++, in insert mode, if I start typing like:

mDeltaTime = (SDL_GetTicks( ) - mLastTime) * (TARGET_FPS / 1000.0F);
                                                         ^-- If I press /

When I type / it shows the pop up menu to choose /bin, /dev, /etc, but I skip it pressing spacebar, finish the line. Then if I press enter, shows again the popup menu

image

If I press enter without choosing something, it shows this error and cmp stops working.

image

paths relative to the working directory

Hi,

I think the relative paths work relative to the parent directory of the file I'm currently editing.
Generally I want paths relative to the project the file belongs to, which I usually setup as my vim working directory.

For me it would be fine if both the parent dir and the cwd are used initially until only a unique match exists.
Or if it is an option to choose either one or the other would also be fine for me.
Or something else you come up with.. (lsp root dir might also be a good candidate)

For now I've made a small edit locally in the plugin source so I get the relative path to my cwd, so no pressure :)

Thank you so much for all this stuff, just starting to migrate nvim with lua based plugins and built in lsp since I have holidays, I'm enjoying myself very much, and I'm amazed by cmp, great work!

Allow triggering without trigger characters

I would like to be able to replace the default <C-x><C-f> with cmp with path source. However this will not trigger because of the currently configured trigger characters.

Basically I would like to do something like:

vim.keymap.set("i", "<c-x><c-f>", function()
  require("cmp").complete({
    config = {
      sources = {
        {
          name = "path",
          keyword_length = 0,
          keyword_pattern = ".*?",
          trigger_characters = {}
        },
      },
    },
  })
end)

However it does not seem to trigger, despite the empty trigger_characters

Completion in the middle of a path does not work

Hi

When triggering completion in the middle of a path, for example placing the cursor after the following: "/tmp/fil", will not suggest "/tmp/file". This is probably due to the trigger characters expecting a '/' or a '.' .

Any way to examine the preceding line to decide if completions should be generated? Maybe support a functional override for trigger characters?

Prevent preview generation of device files but still list them.

One of the recent commits tried to remove the ability to complete device files.
Unfortunately, when completing a link to a device file, or any path not starting with /dev
directly, still has the potential to kill vim. Consider this:

ln -s /dev/stdin dead

Then try completing ./dea<TAB> and nvim is dead as it tries to read from the pty /dev/stdin.
Instead of preventing preview generation based on the path, it would be much better to stat
the file beforehand and return an empty preview in case the file is not a regular file or directory (or a symlink to one of these).
Stat can follow symbolic links, and they should be to prevent the above scenario.

On a related note: I seem to be unable to complete anything with more than two path component. No completion for /dev
is ever shown, but I suppose this is not directly related to this bug.

Windows paths starting with a drive letter are not recognized as such

Paths starting with, for example, C:// etc are not recognized as paths.

c-x c-f works fine though.

Likely just need another pattern around here: https://github.com/hrsh7th/cmp-path/blob/main/lua/cmp_path/init.lua#L54

Note that I have shellslash enabled so I am using forward slashes on windows.

Adding cmp-path breaks completion

Greetings,
I noticed that pressing <Tab> on the Cmdline mode stopped working, even though wildmenu was set to on.
I thought the mappings were the culprit and using :verbose map <Tab> only showed:

s  <Tab>       * <Cmd>call v:lua.cmp.utils.keymap.set_map(11)<CR>
        Last set from Lua

Tried locating where v:lua.cmp.utils.keymap.set_map was being set and it turns out to be in nvim-cmp\lua\cmp\utils\keymap.lua, line 228 here.
Added a print to see what was being set (is there a better way to debug those?) and the outcome was:

mode:i lhs:<Up> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(1)<CR>
mode:c lhs:<Up> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(2)<CR>
mode:i lhs:<C-E> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(3)<CR>
mode:c lhs:<C-E> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(4)<CR>
mode:c lhs:<S-Tab> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(5)<CR>
mode:i lhs:<C-P> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(6)<CR>
mode:c lhs:<C-P> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(7)<CR>
mode:i lhs:<C-N> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(8)<CR>
mode:c lhs:<C-N> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(9)<CR>
mode:i lhs:<CR> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(10)<CR>
mode:s lhs:<Tab> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(11)<CR>
mode:i lhs:<Tab> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(12)<CR>
mode:c lhs:<Tab> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(13)<CR>
mode:i lhs:<C-Space> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(14)<CR>
mode:c lhs:<C-Space> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(15)<CR>
mode:i lhs:<C-F> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(16)<CR>
mode:c lhs:<C-F> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(17)<CR>
mode:i lhs:<Down> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(18)<CR>
mode:c lhs:<Down> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(19)<CR>
mode:i lhs:<C-D> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(20)<CR>
mode:c lhs:<C-D> rhs:<Cmd>call v:lua.cmp.utils.keymap.set_map(21)<CR>

So, <Tab> is being set to something in Cmdline mode, even though :verbose map <Tab> didn't show it. (Why's that?)
I don't really know if the above has any relation with the issue.

So I went for the minimum config and found out that, when adding nvim-cmp with cmp-path, the issue would happen.
<Tab> is set in config-cmp.lua but it seems it's not respecting that config.

Also, opening Neovim without doing anything, since it lazy loads the plugin because of event being set(? I suppose, new at packer), if I enter the Cmdline mode, autocompletion works. After going into Insert mode and triggering it an event, autocomplete breaks.
Disabling cmp-path makes Cmdline autocomplete work back again.

  • Vim type (vim/gvim/neovim): Neovim
  • Vim version: v0.7.0-dev+1201-g5760cf87b
  • OS: Windows

Thanks a lot!

init.lua:

require"plugins"

plugins.lua:

local fn = vim.fn
local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim'

if fn.empty(fn.glob(install_path)) > 0 then
    packer_boostrap = fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path})
end

vim.cmd [[
augroup packer_user_config
autocmd!
autocmd BufWritePost */nvim/lua/plugins.lua source <afile> | PackerSync
augroup end
]]

local status_ok, packer = pcall(require, "packer")
if not status_ok then
    return
end

packer.init {
    display = {
        open_fn = function()
            return require('packer.util').float { border = "rounded" }
        end,
    },
}

return packer.startup(function(use)
    use { "wbthomason/packer.nvim" }
    use { "hrsh7th/nvim-cmp", config = "require('config-cmp')", event = {'BufRead', 'BufNewFile', 'InsertEnter'}}
    use { "hrsh7th/cmp-path", after = "nvim-cmp" }

    if packer_boostrap then
        require('packer').sync()
    end
end)

config-cmp.lua:

local cmp = require'cmp'
local luasnip = require"luasnip"

local cmp_kinds = {
    Text = '  ',
    Method = '  ',
    Function = '  ',
    Constructor = '  ',
    Field = '  ',
    Variable = '  ',
    Class = '  ',
    Interface = '  ',
    Module = '  ',
    Property = '  ',
    Unit = '  ',
    Value = '  ',
    Enum = '  ',
    Keyword = '  ',
    Snippet = '  ',
    Color = '  ',
    File = '  ',
    Reference = '  ',
    Folder = '  ',
    EnumMember = '  ',
    Constant = '  ',
    Struct = '  ',
    Event = '  ',
    Operator = '  ',
    TypeParameter = '  ',
}

local has_words_before = function()
    local line, col = unpack(vim.api.nvim_win_get_cursor(0))
    return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end

cmp.setup({
    mapping = {
        ['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
        ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
        ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
        ['<C-y>'] = cmp.config.disable, -- If you want to remove the default `<C-y>` mapping, You can specify `cmp.config.disable` value.
        ['<C-e>'] = cmp.mapping({
            i = cmp.mapping.abort(),
            c = cmp.mapping.close(),
        }),
        ['<CR>'] = cmp.mapping.confirm({
            behavior = cmp.ConfirmBehavior.Insert,
            select = false
        }),
        ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            elseif has_words_before() then
                cmp.complete()
            else
                fallback()
            end
        end, { "i", "s" }),
    },
    sources = cmp.config.sources({
        { name = 'luasnip' }, -- For luasnip users.
    },
    {
        { name = 'buffer' },
        }),
    formatting = {
        fields = {"kind", "abbr", "menu"},
        format = function(entry, vim_item)
            vim_item.kind = string.format('%s %s', cmp_kinds[vim_item.kind] or "", vim_item.kind)
            vim_item.menu = ({
                nvim_lsp = "[LSP]",
                nvim_lua = "[Lua]",
                luasnip = "[LuaSnip]",
                buffer = "[Buffer]",
            })[entry.source.name]
            return vim_item
        end,
    },
    experimental = {
        ghost_text = true,
    },
})

-- Set configuration for specific filetype.
cmp.setup.filetype('gitcommit', {
    sources = cmp.config.sources({
    { name = 'cmp_git' }, -- You can specify the `cmp_git` source if you were installed it.
    }, {
        { name = 'buffer' },
        })
})

-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline('/', {
    sources = {
    { name = 'buffer' }
    }
})

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
    sources = cmp.config.sources({
    { name = 'path' }
    }, {
        { name = 'cmdline' }
        })
})

neovim will block/freeze when retrieving lots of candidates

hey, everyone

this is about the only problem I've encountered with this plugin. I take my hat off and congratulate the maintainers on some real robust code you have here.

So I have a single directory with about 1500 files and the whole neovim will freeze and not accept any inputs until all candidates have been fetched. It takes a few seconds to regain control of neovim.

My advice is replacing the while true block that does fs_scandir_next() and instead execute it in a separate thread using something like luv's thread pool work scheduling, probable with some sort of short-circuiting feature.

I can do a PR for this if the maintainers accept that this is within the scope of this package/plugin

Neovim crashes in WSL2 when typing path `/tmp/`

I'm not sure if anything can or should be done here on cmp's end but I've had some trouble where typing /tmp/ will trigger cmp and cause neovim to freeze for up to a few minutes before either unfreezing or completely crashing crashing without indicating an error, such as a segfault.

Testing against a native linux machine did not have the same problem.

I have native_menu = false and attempted to set max_item_count = 10 for sources.path thinking this would fix the issue but there was no noticeable change.

I tried a clean neovim instance with wildmenu enabled and cmp disabled to see if it would also crash;
it was still noticeably slow and hung for ~30sec but didn't result in a crash.

Is there a possible workaround like disabling completion for the tmp directory in both insert and command mode?

lua/plugins/cmp.lua
-- nvim-cmp setup
local cmp = require('cmp')
local luasnip = require('luasnip')

local kinds = require('lsp.icons').completion_kinds

-- Detect whitespace before cursor position.
local check_backspace = function()
  local col = vim.fn.col('.') - 1
  return col == 0 or vim.fn.getline('.'):sub(col, col):match('%s')
end

cmp.setup({
  -- enabled = function()
  --   buftype = vim.api.nvim_buf_get_option(0, 'buftype')
  --   if buftype == 'prompt' then
  --     return false
  --   end
  --   return true
  -- end,
  snippet = {
    expand = function(args)
      luasnip.lsp_expand(args.body) -- For `luasnip` users.
    end,
  },
  experimental = {
    native_menu = false,
    ghost_text = true,
  },
  window = {
    completion = {
      max_width = 80,
      border = 'single',
      completeopt = 'menu,menuone,noselect',
      keyword_pattern = [[\%(-\?\d\+\%(\.\d\+\)\?\|\h\w*\%(-\w*\)*\)]],
      keyword_length = 2,
      winhighlight = table.concat({
        'NormalFloat:NormalFloat',
        'FloatBorder:FloatBorder',
      }, ','),
    },
    documentation = {
      border = 'single',
      winhighlight = table.concat({
        'NormalFloat:NormalFloat',
        'FloatBorder:FloatBorder',
      }, ','),
    },
  },
  view = {
    entries = {
      name = 'custom',
      -- selection_order = 'near_cursor'
    },
  },
  sorting = {
    comparators = {
      cmp.config.compare.offset,
      cmp.config.compare.exact,
      cmp.config.compare.score,

      -- copied from cmp-under, but I don't think I need the plugin for this.
      function(entry1, entry2)
        local _, entry1_under = entry1.completion_item.label:find('^_+')
        local _, entry2_under = entry2.completion_item.label:find('^_+')
        entry1_under = entry1_under or 0
        entry2_under = entry2_under or 0
        if entry1_under > entry2_under then
          return false
        elseif entry1_under < entry2_under then
          return true
        end
      end,

      cmp.config.compare.kind,
      cmp.config.compare.sort_text,
      cmp.config.compare.length,
      cmp.config.compare.order,
    },
  },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'luasnip' },
    -- { name = 'nvim_lua' },
    -- { name = 'treesitter' },
    { name = 'path', max_item_count = 10 },
    {
      name = 'buffer',
      keyword_length = 3,
      option = {
        get_bufnrs = function()
          return vim.api.nvim_list_bufs()
        end,
      },
    },
  },
  formatting = {
    format = function(entry, vim_item)
      vim_item.dup = { buffer = 1, path = 1, nvim_lsp = 0 }
      vim_item.kind = string.format('%s %s', kinds[vim_item.kind], vim_item.kind)
      vim_item.max_width = 80
      vim_item.menu = ({
        buffer = '[Buffer]',
        cmp_tabnine = '[Tabnine]',
        crates = '[Crates]',
        latex_symbols = '[Latex]',
        luasnip = '[Luasnip]',
        nvim_lsp = '[LSP]',
        nvim_lua = '[Lua]',
        path = '[Path]',
        spell = '[Spell]',
        ultisnips = '[Ultisnips]',
        vsnip = '[VSnip]',
        zsh = '[Shell]',
      })[entry.source.name]
      return vim_item
    end,
  },
  mapping = cmp.mapping.preset.insert({
    ['<CR>'] = cmp.mapping.confirm({ select = false }),
    ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
    ['<C-p>'] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 'c' }),
    ['<C-n>'] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 'c' }),
    ['<C-d>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
    ['<C-f>'] = cmp.mapping.scroll_docs(4),
    ['<C-u>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
    ['<C-e>'] = cmp.mapping({
      i = cmp.mapping.abort(),
      c = cmp.mapping.close(),
    }),

    ['<Down>'] = cmp.mapping({
      n = cmp.mapping.select_next_item(),
      c = cmp.mapping.select_next_item(),
      i = cmp.config.disable,
    }),

    ['<Up>'] = cmp.mapping({
      n = cmp.mapping.select_prev_item(),
      c = cmp.mapping.select_prev_item(),
      i = cmp.config.disable,
    }),

    ['<Tab>'] = cmp.mapping(function(fallback)
      if cmp.visible() and not check_backspace() then
        cmp.confirm({ select = true })
      elseif luasnip.expand_or_jumpable() then
        luasnip.expand_or_jump()
      else
        fallback()
      end
    end, { 'i', 's' }),

    ['<S-CR>'] = cmp.mapping(function(fallback)
      if luasnip.jumpable(-1) then
        luasnip.jump(-1)
      else
        fallback()
      end
    end, { 'i', 's' }),
  }),
})

Support for fnamemodified paths (specifically %:h)

It would be great if e.g. :e %:h/foo suggested completions for the expanded %:h (i.e. the parent directory of the current file name). Right now I either get no completion suggestions when paths include %, or I get incorrectly expanded paths (where the %:h is still present after confirming the completion). A minimal init is:

vim.cmd [[set runtimepath=$VIMRUNTIME]]
vim.cmd [[set packpath=/tmp/nvim/site]]

local package_root = '/tmp/nvim/site/pack'
local install_path = package_root .. '/packer/start/packer.nvim'

local function load_plugins()
  require('packer').startup {
    {
      'hrsh7th/nvim-cmp',
      'hrsh7th/cmp-path',
      'hrsh7th/cmp-cmdline,
      'wbthomason/packer.nvim',
    },
    config = {
      package_root = package_root,
      compile_path = install_path .. '/plugin/packer_compiled.lua',
    },
  }
end

if vim.fn.isdirectory(install_path) == 0 then
  vim.fn.system { 'git', 'clone', 'https://github.com/wbthomason/packer.nvim', install_path }
  load_plugins()
  require('packer').sync()
else
  load_plugins()
  require('packer').sync()
end

local cmp = require'cmp'

cmp.setup({
  mapping = {
    ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
    ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
    ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
    ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
    ['<C-e>'] = cmp.mapping({
      i = cmp.mapping.abort(),
      c = cmp.mapping.close(),
    }),
    ['<CR>'] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items.
  },
  sources = cmp.config.sources({
    { name = 'nvim_lsp' },
    { name = 'path' },
    { name = 'vsnip' }, -- For vsnip users.
  }, {
    { name = 'buffer' },
  })
})

-- Use buffer source for `/` (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline('/', {
  sources = {
    { name = 'buffer' }
  }
})

-- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore).
cmp.setup.cmdline(':', {
  sources = cmp.config.sources({
    { name = 'path' }
  }, {
    { name = 'cmdline' }
  })
})

Which seems to exhibit the first behavior (no completion suggestions). My full config exhibits the latter, I have to bisect why, but neither seems to support the expansion. Let me know if this makes sense for cmp-path! (And thanks for making cmp)

Relative or cwd paths

Feature request: complete paths from the current working directory or relative paths (./file, ../file, ...).

These completions should only occur if the cursor is at the start of a string character (typically " or ') or if in a shell script (.sh, .zsh, #!/bin/bash).

Path aliases

VSCode's Path Autocomplete has a feature called path-autocomplete.pathMappings which allows you to define aliases for paths:

"path-autocomplete.pathMappings": {
    "/test": "${folder}/src/Actions/test", // alias for /test
    "/": "${folder}/src", // the absolute root folder is now /src,
    "$root": ${folder}/src // the relative root folder is now /src
    // or multiple folders for one mapping
    "$root": ["${folder}/p1/src", "${folder}/p2/src"] // the root is now relative to both p1/src and p2/src
}

For example, you can define your root path (/) to point to your public directory and other useful things.
It would be nice if we can have a get_aliases function to support this.

Paths containing colons break autocomplete

Whenver a path has a colon, cmp-path stops working.

For example, given a log file in ./my/path/2022-08-22T10:00/log.txt, autocomplete will suggest every part of the path except log.txt,

INPUT                        SUGGESTION
./|                          -> my/
./my/|                       -> path/
./my/path/|                  -> 2022-08-22T10:00/
./my/path/2022-08-22T10:00/| -> (no suggestions from cmp-path)

Incorrect completion trigger for closing C++ block comments

Hi All!
The completion window is shown once I close a comment block in a cpp file.

/* A block comment
 * is here
 */ 
  ^ bump

A quick and dirty solution helped me:

 -- Ignore CPP closing block comments
    accept = accept and not prefix:match('\\*/$')

But I suppose that there might be some issues without proper testing.
Thank you!

Remove trailing slash in the completion menu

Directories show with a trailing slash in the completion menu. Personally, I do not want to see the trailing slash because it already shows the description "Folder" and it has a folder icon. Therefore, I think there should be an option to not show the trailing slash in the menu. This option should not make a functional difference, it is only for apperances.

Not Triggering within quotes

Hey! I recently started using this, and for some reason I've been unable to trigger path completion from within quotes (both single and double).

Is this intended behavior? If so, is there a way to enable path completion from within quotes?

how to ignore the root of the system

hi,

is it possible not to display the root of the system? for example: /sys ...

when I type / I automatically get the root.

in the doc there is the option "get_cwd" but I don't know how to do it.

the best would be to be able to display the current directory.

I have the same configuration as here: https://github.com/sar/cmp.nvim#setup

with the exception that I added this:

cmp.setup({
...
  sources = cmp.config.sources({
    ...
    { name = "path" },
    ...
  )}
...
})

thanks

Windows path with space

for example, there's project under c:\workspace\project 1\src.

When I typing 'tabnew c:\workspace\project ', it won't sugguest 'c:\workspace\project 1', but files under cwd.

When I typing 'tabnew c:\workspace\project\ ', trying to escape the space character, it suggests
image

If I type double '\', 'tabnew c:\workspace\project\ ', trying to escape the space character, it suggests nothing.
image

this may related to previous issue I mentioned: #31

If I start with nvim -u NONE, type 'tabnew c:/me/ccw/ccw\ ', here use unix path delimiter, and use '' as space escaper, and press type, it will promots:
image

Not suggesting path when creating second path on the same line

Lets say I have a line:

/usr/bin/java -jar /usr/local/bin/file.jar

The first path will be completed, but the path to the second file I have to know, since it won't give me any suggestion on the same line.
Is there anything that could be done about this?

Path on LaTeX (i.e. \lstinputlisting)

Hi,

when I use LaTeX, there is a command called \lstinputlisting that receives as a parameter the path to a script to embed in a document (i.e. lstinputlisting{path/to/your/script}).
There are also other commands like this, for example \includegraphics for images.

It would be nice if cmp-path could suggest paths inside that command :D

Nvim 100% CPU after tab from closing parentheses, caused by Path source

So this is going to sound like a wierd one. I spent 2 hours last night working out what was causing Nvim to appear to crash after I jumped to the end of a bracket and entered insert mode with A and hit tab - tab is the key i use to show the menu, but I have also
tested this with ctrl+p and saw the same issue.

If I have a set empty set of brackets like so:

      test_method()
      test_hash = {}
      test_array = []

It seems to give me the menu I would expect:

image

If I add a string, key => value or method arguments inside the brackets like so:

      test_method(:one, :two)
      test_hash = {one: 1}
      test_array = ["hello", "world"]

It reacts extremely slowly, lagging between key presses.

If I use A to get to the end of the line and enter insert mode when the last character is ), }, like below:

      test_hash = {one: 1}

The cursor stays in insert mode but it seems to ramp up the CPU to 100% and needs to be closed with htop:

image

I've also tried it on a bash script that I wrote, using A and tab from the closing bracket causes the 100% issue:

response=$(curl --write-out '%{http_code}' --silent --output /dev/null $url)

By commenting out the { name = "path" }, line the issue stops completely and behaves as expected.

My CMP Config is below incase that sheds any light on the issue.

vim.o.completeopt = 'menuone,noselect'
vim.opt.shortmess:append "c"

local has_words_before = function()
  local line, col = unpack(vim.api.nvim_win_get_cursor(0))
  return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
end

local cmp = require "cmp"
local lspkind = require('lspkind')

cmp.setup {
  mapping = {
    ["<C-p>"] = cmp.mapping.select_prev_item(),
    ["<C-n>"] = cmp.mapping.select_next_item(),
    ["<C-d>"] = cmp.mapping.scroll_docs(-4),
    ["<C-f>"] = cmp.mapping.scroll_docs(4),
    ["<C-Space>"] = cmp.mapping.complete(),
    ["<C-e>"] = cmp.mapping.close(),
    ["<CR>"] = cmp.mapping.confirm {
      behavior = cmp.ConfirmBehavior.Replace,
      select = true,
    },
    ["<Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_next_item()
      elseif has_words_before() then
        cmp.complete()
      else
        fallback()
      end
    end, { "i", "s" }),
    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if cmp.visible() then
        cmp.select_prev_item()
      else
        fallback()
      end
    end, { "i", "s" }),
  },
  sources = {
    { name = "nvim_lua" },
    { name = "nvim_lsp" },
    { name = "path" }, -- This seems to cause nvim to infinate loop and use 100% cpu
    { name = "buffer", keyword_length = 5 },
  },
  formatting = {
    format = lspkind.cmp_format({
      with_text = false,
      maxwidth = 50,
      menu = {
        buffer = "[buf]",
        nvim_lsp = "[LSP]",
        nvim_lua = "[api]",
        path = "[path]",
        luasnip = "[snip]",
      },
    }),
  },
  experimental = {
    native_menu = false,
    ghost_text = false,
  }
}

vim.cmd([[
  augroup NvimCmp
  au!
  au FileType TelescopePrompt lua require('cmp').setup.buffer { enabled = false }
  augroup END
]])

Use wildignore when completing files

Here's a patch to use wildignore when completing files. (This way log files / other outputs wont clutter the completion menu).

diff --git a/lua/cmp_path/init.lua b/lua/cmp_path/init.lua
index 4e63d27..62f1e5e 100644
--- a/lua/cmp_path/init.lua
+++ b/lua/cmp_path/init.lua
@@ -121,11 +121,26 @@ source._candidates = function(_, dirname, include_hidden, option, callback)
 
   local items = {}
 
+  -- 2023-12-12 gi1242: Partially convert glob patters to lua patterns
+  local wildignore = {}
+  for k, v in pairs( vim.opt.wildignore:get() ) do
+    wildignore[k] = v:gsub( '\\.', '\\.' ):gsub( '*', '.*' )
+  end
+  vim.print(wildignore)
+
+
   local function create_item(name, fs_type)
     if not (include_hidden or string.sub(name, 1, 1) ~= '.') then
       return
     end
 
+    -- 2023-12-12 gi1242: Ignore paths matching wildignore
+    for k, v in pairs( wildignore ) do
+      if name:find(v) then
+	return
+      end
+    end
+
     local path = dirname .. '/' .. name
     local stat = vim.loop.fs_stat(path)
     local lstat = nil

Trailing slashes in cmdline?

I have noticed that quite frequently I will get trailing slashes appended to the completions.


Steps to reproduce:

  1. Type the name of a directory and press tab

Notice there is a slash appended to the result

image

  1. Type a slash to get cmp-path to read from the next directory

But wait, now it's trying to complete from the root directory?

image

  1. Press backspace to remove the slash

Wait, now there are two of every file

image


This doesn't happen in the buffer, only in the cmdline. I have noticed that it works properly sometimes, but it is rare and I don't know what causes it to work properly. Although, I'm pretty sure it has to do with the trailing slash because in the cmdline, a slash is appended, and in the buffer, a slash is not appended.

Is this a known bug or is there a way to solve this?

Allow for generic excludes of file extensions

"Vanilla (neo)vim" has the option wildignore to allow ignoring some file patterns. This list is neither respected nor is there any other way to enable ignoring specific file patterns.

some files missing in completion candidate list

I'm trying to type the file path /boot/grub/grub.config, after typing /boot/grub/, the auto completion candidate list pops up, but the gurb.cfg isn't one of them.

The /boot/grub directory contains the following items:

fonts/  locale/  themes/  x86_64-efi/  grub.cfg  grubenv

Only the first four directories are included in the the auto completion candidate list, grub.cfg and grub.env are missing.

And here's my config:

cmp.setup {
  -- snippet = {
  --   expand = function(args)
  --     -- You must install `vim-vsnip` if you use the following as-is.
  --     vim.fn['vsnip#anonymous'](args.body)
  --   end
  -- },

  -- You must set mapping if you want.
  mapping = {
    ["<Tab>"] = cmp.mapping(function(fallback)
      if vim.fn.pumvisible() == 1 then
        vim.fn.feedkeys(t("<C-n>"), "n")
      -- elseif vim.fn['vsnip#available']() == 1 then
      --   vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>(vsnip-expand-or-jump)', true, true, true), '')
      elseif check_back_space() then
        vim.fn.feedkeys(t("<Tab>"), "n")
      else
        fallback()
      end
    end, {
      "i",
      "s",
    }),
    ["<S-Tab>"] = cmp.mapping(function(fallback)
      if vim.fn.pumvisible() == 1 then
        vim.fn.feedkeys(t("<C-p>"), "n")
      -- elseif vim.fn['vsnip#available']() == 1 then
      --   vim.fn.feedkeys(vim.api.nvim_replace_termcodes('<Plug>(vsnip-expand-or-jump)', true, true, true), '')
      else
        fallback()
      end
    end, {
      "i",
      "s",
    }),
  },

  -- You should specify your *installed* sources.
  sources = {
    { name = 'nvim_lsp' },
    { name = 'buffer' },
    { name = 'path' },
  },
  formatting = {
    format = function(entry, vim_item)
      vim_item.menu = ({
        nvim_lsp = "[LSP]",
        buffer = "[BFR]",
        path = "[PTH]",
      })[entry.source.name]
      return vim_item
    end,
  },
}

-- you need setup cmp first put this after cmp.setup()
-- ref: https://github.com/windwp/nvim-autopairs#override-default-values
require("nvim-autopairs.completion.cmp").setup({
  map_cr = true, --  map <CR> on insert mode
  map_complete = true, -- it will auto insert `(` after select function or method item
})

Latest commit (56a0fe5c4) breaks path completion after second `/`

Hi - first, great plugin!

I noticed today that completion would start to break after the second /. The first / opens completion for paths. If I select the first path and then type the next / it shows me only snippets that match / like if/else. Reverting to d83839ae resolves this issue and the source works as before.

Thanks

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.