hrsh7th / nvim-cmp

A completion plugin for neovim coded in Lua.
MIT License
8.13k stars 403 forks source link

Simple markdown support #1699

Open FormalSnake opened 1 year ago

FormalSnake commented 1 year ago

FAQ

Announcement

Minimal reproducible full config

not relevant but

local cmp = require "cmp"

require("luasnip.loaders.from_vscode").lazy_load()

local formatting_style = {
    -- default fields order i.e completion word + item.kind + item.kind icons
    fields = { "abbr", "kind", "menu" },
    format = require('tailwindcss-colorizer-cmp').formatter,
}

local function border(hl_name)
    return {
        { "╭", hl_name },
        { "─", hl_name },
        { "╮", hl_name },
        { "│", hl_name },
        { "╯", hl_name },
        { "─", hl_name },
        { "╰", hl_name },
        { "│", hl_name },
    }
end

local icons = {
    Text = "󰉿",
    Variable = "󰜢",
    Snippet = "",
    Function = "󰊕",
    Keyword = "󰌋",
    Field = "",
    Property = "",
    Enum = "",
}
local options = {
    completion = {
        completeopt = "menu,menuone",
    },

    window = {
        completion = {
            side_padding = 0,
            winhighlight = "Normal:CmpPmenu,CursorLine:PmenuSel,Search:PmenuSel",
            scrollbar = true,
            border = border "CmpDocBorder",
        },
        documentation = {
            border = border "CmpDocBorder",
            winhighlight = "Normal:CmpDoc",
        },
    },
    snippet = {
        expand = function(args)
            require("luasnip").lsp_expand(args.body)
        end,
    },

    -- formatting = formatting_style,
    formatting = {
        format = function(_, vim_item)
            vim_item.kind = icons[vim_item.kind] .. " " .. vim_item.kind or vim_item.kind
            return vim_item
        end,
    },
    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.Insert,
            select = true,
        },
        ["<Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_next_item()
            elseif require("luasnip").expand_or_jumpable() then
                vim.fn.feedkeys(
                    vim.api.nvim_replace_termcodes("<Plug>luasnip-expand-or-jump", true, true, true),
                    "")
            else
                fallback()
            end
        end, {
            "i",
            "s",
        }),
        ["<S-Tab>"] = cmp.mapping(function(fallback)
            if cmp.visible() then
                cmp.select_prev_item()
            elseif require("luasnip").jumpable(-1) then
                vim.fn.feedkeys(
                    vim.api.nvim_replace_termcodes("<Plug>luasnip-jump-prev", true, true, true), "")
            else
                fallback()
            end
        end, {
            "i",
            "s",
        }),
    },

    sources = {
        { name = "nvim_lsp" },
        { name = "luasnip" },
        { name = "buffer" },
        { name = "nvim_lua" },
        { name = "path" },
    },
    {
        { name = 'buffer' },
    },
}
require("cmp").setup(options)

Description

Markdown is not displayed correctly image

Steps to reproduce

just use the plugin

Expected behavior

instead of seeing the markdown it should be formatted

Actual behavior

it is not

Additional context

No response

FormalSnake commented 1 year ago

i know this is not a bug but its the only issue template

MariaSolOs commented 1 year ago

@FormalSnake this will be possible once https://github.com/neovim/neovim/pull/25073 goes in.

FormalSnake commented 1 year ago

Nice! What a coincidence lol

nsoufian commented 1 year ago

The https://github.com/neovim/neovim/pull/25073 is merged into master, can we expect that nvim-cmp docs will be the same as neovim core hover soon?

@MariaSolOs Thank you for https://github.com/neovim/neovim/pull/25073

FormalSnake commented 1 year ago

This is great!

MariaSolOs commented 1 year ago

Alright here's the thing: I had initially envisioned https://github.com/neovim/neovim/pull/25073 to include the public API for the new LSP markdown methods, but because that will involve a larger refactor tracked by https://github.com/neovim/neovim/issues/25272, this will happen in the future. In the meantime, here's a workaround I have in my dotfiles that's inspired by what Noice does.

DISCLAIMER: You shouldn't patch plugins like this or use private (prefixed by _) methods in Neovim. This will very likely cause your configuration to break and you won't be able to blame anyone about it except for yourself, so use at your own risk.

Still here? Okay here's the code.

--- HACK: Override `vim.lsp.util.stylize_markdown` to use Treesitter.
---@param bufnr integer
---@param contents string[]
---@param opts table
---@return string[]
---@diagnostic disable-next-line: duplicate-set-field
vim.lsp.util.stylize_markdown = function(bufnr, contents, opts)
    contents = vim.lsp.util._normalize_markdown(contents, {
        width = vim.lsp.util._make_floating_popup_size(contents, opts),
    })
    vim.bo[bufnr].filetype = 'markdown'
    vim.treesitter.start(bufnr)
    vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents)

    return contents
end

I have extra enhancements in my (publicly available) configuration, but I'll leave that as an exercise for the reader to figure out/find.

FormalSnake commented 1 year ago

I tried it and it looks great, but how do I scroll in the docs without mouse 😅

hedyhli commented 1 year ago

Mappings in the minimal config from your issue description has bindings to scroll docs:

        ["<C-d>"] = cmp.mapping.scroll_docs(-4),
        ["<C-f>"] = cmp.mapping.scroll_docs(4),
carschandler commented 8 months ago

This is particularly important for documentations that make frequent use of &nbsp; since that can make docs pretty tough to read when they don't get rendered.

GordianDziwis commented 4 weeks ago

Alright here's the thing: I had initially envisioned neovim/neovim#25073 to include the public API for the new LSP markdown methods, but because that will involve a larger refactor tracked by neovim/neovim#25272, this will happen in the future. In the meantime, here's a workaround I have in my dotfiles that's inspired by what Noice does.

DISCLAIMER: You shouldn't patch plugins like this or use private (prefixed by _) methods in Neovim. This will very likely cause your configuration to break and you won't be able to blame anyone about it except for yourself, so use at your own risk.

Still here? Okay here's the code.

--- HACK: Override `vim.lsp.util.stylize_markdown` to use Treesitter.
---@param bufnr integer
---@param contents string[]
---@param opts table
---@return string[]
---@diagnostic disable-next-line: duplicate-set-field
vim.lsp.util.stylize_markdown = function(bufnr, contents, opts)
    contents = vim.lsp.util._normalize_markdown(contents, {
        width = vim.lsp.util._make_floating_popup_size(contents, opts),
    })
    vim.bo[bufnr].filetype = 'markdown'
    vim.treesitter.start(bufnr)
    vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, contents)

    return contents
end

I have extra enhancements in my (publicly available) configuration, but I'll leave that as an exercise for the reader to figure out/find.

A less hacky workaround. Change vim.lsp.util.stylize_markdown to a local function:

local stylize_markdown = function(bufnr, contents, opts)
    contents = vim.lsp.util._normalize_markdown(contents, {
        width = vim.lsp.util._make_floating_popup_size(contents, opts),
    })
...

And call it here:

https://github.com/hrsh7th/nvim-cmp/blob/29fb4854573355792df9e156cb779f0d31308796/lua/cmp/view/docs_view.lua#L64