Skip to content

Opencode.nvim completions menu can't be accessed with nvim-cmp #309

Closed

Description

@sei-dwtompkins

Similar to the issue reported by user disrupted in 287, I'm having an issue with the recent LSP completions actually activating. When I hit tab in the input_window, it will insert a literal tab character instead of moving through the completions menu.

Activity

  1. sudo-tee commented on Mar 6, 2026

    @sudo-tee
    Owner

    @sei-dwtompkins What is your cmp config?

    I just tried it and it worked fine for me.

  2. sei-dwtompkins commented on Mar 6, 2026

    @sei-dwtompkins
    ContributorAuthor

    It had been working properly for me before that PR got merged in:

      -- Autocomplete
      {
        "hrsh7th/nvim-cmp",
        event = "InsertEnter",
        -- Sources for nvim-cmp
        dependencies = {
          "nvim-tree/nvim-web-devicons",
          "hrsh7th/cmp-nvim-lsp",
          "hrsh7th/cmp-buffer",
          "hrsh7th/cmp-path",
          "hrsh7th/cmp-nvim-lua",
          "hrsh7th/cmp-cmdline",
          "saadparwaiz1/cmp_luasnip",
          "l00sed/cmp-tidal",
        },
        config = function()
          require("plugins.cmp")
        end,
      },

    plugins/cmp.lua

    local fn = vim.fn
    local cmd = vim.cmd
    
    local luasnip = require('luasnip')
    local cmp = require('cmp')
    
    local function get_snippets_rtp()
      return vim.tbl_map(function(itm)
        return fn.fnamemodify(itm, ":h")
      end, vim.api.nvim_get_runtime_file(
          "package.json", true
      ))
    end
    
    local opts = {
      paths = {
        fn.stdpath('config')..'/snips/',
        get_snippets_rtp()[1],
      },
    }
    
    require('luasnip.loaders.from_vscode').lazy_load(opts)
    
    local border = {
      { "╭", "FloatBorder" },
      { "─", "FloatBorder" },
      { "╮", "FloatBorder" },
      { "│", "FloatBorder" },
      { "╯", "FloatBorder" },
      { "─", "FloatBorder" },
      { "╰", "FloatBorder" },
      { "│", "FloatBorder" },
    }
    
    local hl = "Normal:Normal,FloatBorder:FloatBorder,CursorLine:CursorLine,Search:Search"
    
    local lspkind = require('lspkind')
    
    cmp.setup({
      preselect = cmp.PreselectMode.None,
      snippet = {
        expand = function(args)
          luasnip.lsp_expand(args.body)
        end,
      },
    
      -- Styles
      window = {
        completion = {
          side_padding = 1,
          col_offset = -1,
          border = border,
          winhighlight = hl,
        },
        documentation = {
          side_padding = 1,
          border = border,
          winhighlight = hl,
        }
      },
    
      formatting = {
        format = lspkind.cmp_format({
          mode = 'symbol',
          preset = 'default',
          menu = ({
            nvim_lsp = "[LSP]",
            luasnip = "[LuaSnip]",
            nvim_lua = "[Lua]",
            path = "[Path]",
            buffer = "[Buffer]",
            spell = "[Spell]",
          }),
          symbol_map = {
            ... symbols mapping here ...
          },
          ellipsis_char = '...',
          before = function(entry, vim_item)
            return vim_item
          end
        })
      },
    
      -- Mappings
      mapping = {
        -- open/close autocomplete
        ['<C-Space>'] = function()
          if cmp.visible() then
            cmp.close()
          else
            cmp.complete()
          end
        end,
    
        ['<C-c>'] = cmp.mapping.close(),
    
        -- select completion
        ['<CR>'] = cmp.mapping.confirm({
          behavior = cmp.ConfirmBehavior.Replace,
          select = false,
        }),
    
        ['<Tab>'] = function(fallback)
          if cmp.visible() then
            cmp.select_next_item()
          elseif luasnip.expand_or_jumpable() then
            luasnip.expand_or_jump()
          else
            fallback()
          end
        end,
    
        ['<S-Tab>'] = function(fallback)
          if cmp.visible() then
            cmp.select_prev_item()
          elseif luasnip.jumpable(-1) then
            luasnip.jump(-1)
          else
            fallback()
          end
        end,
    
        -- Scroll documentation
        ['<C-d>'] = cmp.mapping.scroll_docs(-4),
        ['<C-f>'] = cmp.mapping.scroll_docs(4),
      },
    
      -- Complete options from the LSP servers and the snippet engine
      sources = {
        { name = 'nvim_lsp' },
        { name = 'luasnip'  },
        { name = 'tidal' },
        { name = 'tidal_samples' },
        { name = 'nvim_lua' },
        { name = 'path'     },
        { name = 'buffer'   },
        { name = 'spell'    },
      },
    
      performance = {
        fetching_timeout = 2000,
      },
    })
  3. sudo-tee commented on Mar 6, 2026

    @sudo-tee
    Owner

    Thanks for sharing.

    If you remove the Tab from the opencode config does it still interfere?

  4. sei-dwtompkins commented on Mar 6, 2026

    @sei-dwtompkins
    ContributorAuthor

    It still seems to want to put in the literal tab instead of getting into the completions menu.

  5. sei-dwtompkins commented on Mar 7, 2026

    @sei-dwtompkins
    ContributorAuthor

    I managed to get it working, it was a very strange issue... I had the following configured in opencode's keymaps:

    -['<C-i>'] = { 'focus_input', mode = { 'n', 'i' } },
    +['<C-i>'] = { 'focus_input', mode = { 'n' } },

    Apparently <C-i> and Tab are interpreted as the same character. So this was overriding the Tab key behavior. TIL
    https://unix.stackexchange.com/a/563480

    EDIT: It looks like I did grab that from the default config options listed in the README, so idk if you feel like that ought to be updated to something different to prevent people from making this mistake— or just remove the 'i' (insert mode) option?

  6. sudo-tee commented on Mar 7, 2026

    @sudo-tee
    Owner

    Thanks for the info.

    Some terminal effectively use C-i as Tab chars. I remember having issues in the pass.

    I will remove this binding as it can cause confusion.

    By curiosity which terminal are u using?

  7. sei-dwtompkins commented on Mar 9, 2026

    @sei-dwtompkins
    ContributorAuthor

    That was a real rabbit hole, it felt a bit hilarious when that simple change got it working again. These tests were in Ghostty.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions