return {
    {
        "hrsh7th/nvim-cmp",
        dependencies = {
            "hrsh7th/cmp-nvim-lsp",
            "hrsh7th/cmp-nvim-lsp-signature-help",
            "hrsh7th/cmp-nvim-lua",
            "hrsh7th/cmp-buffer",
            "hrsh7th/cmp-path",
            "hrsh7th/cmp-omni",
            "micangl/cmp-vimtex",
            "L3MON4D3/LuaSnip",
            "saadparwaiz1/cmp_luasnip",
        },
        opts = function(_, opts)
            opts.sources = opts.sources or {}
            table.insert(opts.sources, {
                name = "lazydev",
                group_index = 0, -- set group index to 0 to skip loading LuaLS completions
            })
        end,
        config = function()
            local cmp = require("cmp")
            local luasnip = require("luasnip")

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

            local kind_icons = {
                Text = "󰊄",
                Method = "m",
                Function = "󰊕",
                Constructor = "",
                Field = "󰽏",
                Variable = "󰫧",
                Class = "󰌗",
                Interface = "",
                Module = "",
                Property = "",
                Unit = "",
                Value = "󰎠",
                Enum = "",
                Keyword = "",
                Snippet = "",
                Color = "󰏘",
                File = "󰈙",
                Reference = "",
                Folder = "󰉋",
                EnumMember = "",
                Constant = "󰇽",
                Struct = "",
                Event = "",
                Operator = "󰆕",
                TypeParameter = "",
            }

            cmp.setup({
                enabled = function()
                    -- disable autocompletion in telescope prompt
                    local buftype = vim.api.nvim_get_option_value("buftype", {})

                    return buftype ~= "prompt"
                end,
                completion = {
                    completeopt = "menu,menuone,noselect",
                },
                window = {
                    documentation = cmp.config.window.bordered(),
                    completion = cmp.config.window.bordered(),
                },
                snippet = {
                    expand = function(args)
                        luasnip.lsp_expand(args.body)
                    end,
                },
                mapping = cmp.mapping.preset.insert({
                    ["<C-l>"] = cmp.mapping.confirm({
                        behavior = cmp.ConfirmBehavior.Replace,
                        select = true,
                    }),
                    ["<Tab>"] = cmp.mapping(function(fallback)
                        if luasnip.locally_jumpable(1) then
                            luasnip.jump(1)
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
                    ["<S-Tab>"] = cmp.mapping(function(fallback)
                        if luasnip.locally_jumpable(-1) then
                            luasnip.jump(-1)
                        else
                            fallback()
                        end
                    end, { "i", "s" }),
                }),
                formatting = {
                    fields = { "kind", "abbr", "menu" },
                    format = function(entry, vim_item)
                        -- kind icons
                        vim_item.kind = string.format("%s", kind_icons[vim_item.kind])
                        vim_item.menu = ({
                            nvim_lsp = "[ ]",
                            nvim_lsp_signature_help = "[󰞋 ]",
                            omni = "[ ]",
                            luasnip = "[ ]",
                            buffer = "[󰮳 ]",
                            path = "[ ]",
                        })[entry.source.name]
                        -- return vim_item
                        return require("nvim-highlight-colors").format(entry, vim_item)
                    end,
                },
                sources = {
                    { name = "nvim_lsp" },
                    { name = "nvim_lua" },
                    { name = "buffer" },
                    { name = "path" },
                    { name = "vimtex" },
                    { name = "nvim_lsp_signature_help" },
                    { name = "luasnip" },
                },
            })

            -- insert `(` after select function or method item
            local cmp_autopairs = require('nvim-autopairs.completion.cmp')
            cmp.event:on(
                'confirm_done',
                cmp_autopairs.on_confirm_done()
            )

            -- use omnifunc in vimwiki to complete paths and tags
            cmp.setup.filetype('vimwiki', {
                sources = cmp.config.sources({
                    { name = "omni" },
                    { name = "luasnip" },
                    { name = "buffer" },
                    { name = "path" },
                    option = {
                        disable_omnifuncs = {},
                    },
                })
            })
        end,
    },
    {
        'mireq/luasnip-snippets',
        dependencies = { 'L3MON4D3/LuaSnip' },
        init = function()
            require('luasnip_snippets.common.snip_utils').setup()
        end

    },
    {
        "L3MON4D3/LuaSnip",
        version = "v2.*",
        dependencies = {
            'nvim-treesitter/nvim-treesitter',
        },
        build = "make install_jsregexp",
        opts = {
            history = false,
            region_check_events = 'InsertEnter',
            delete_check_events = 'InsertLeave',
        },
        init = function()
            local ls = require('luasnip')
            ls.setup({
                -- Required to automatically include base snippets, like "c" snippets for "cpp"
                load_ft_func = require('luasnip_snippets.common.snip_utils').load_ft_func,
                ft_func = require('luasnip_snippets.common.snip_utils').ft_func,
                -- To enable auto expansion
                enable_autosnippets = true,
            })
            require("luasnip.loaders.from_lua").lazy_load({ paths = "./lua/luasnippets" })
        end

    },
}