DEV Community

hardyweb
hardyweb

Posted on • Edited on

Neovim 0.12 autocomplete and native plugin manager for laravel and go

create init.lua file inside .config/nvim , but before that, please back up all configuration files and folders first.

-- =========================================
--  NeoVim 0.12+ Native Pack + LSP Config
-- =========================================

-- Bootstrap plugins (native pack)
vim.pack.add({
    { src = "https://github.com/williamboman/mason.nvim.git" },
    { src = "https://github.com/neovim/nvim-lspconfig.git" },
    { src = "https://github.com/nvim-treesitter/nvim-treesitter.git", build = ":TSUpdate" },
    { src = "https://github.com/hrsh7th/nvim-cmp.git" },
    { src = "https://github.com/hrsh7th/cmp-nvim-lsp.git" },
    { src = "https://github.com/hrsh7th/cmp-buffer.git" },
    { src = "https://github.com/L3MON4D3/LuaSnip.git" },
    { src = "https://github.com/saghen/blink.cmp.git" },
    { src = "https://github.com/echasnovski/mini.pairs.git" },
    { src = "https://github.com/echasnovski/mini.icons.git" },
    { src = "https://github.com/nvim-lualine/lualine.nvim.git" },
    { src = "https://github.com/ibhagwan/fzf-lua.git" },
    { src = "https://github.com/nvim-tree/nvim-web-devicons.git" },
    { src = "https://github.com/folke/tokyonight.nvim.git" },
    { src = "https://github.com/akinsho/toggleterm.nvim.git" },
})

-- =========================================
--  Mason setup
-- =========================================
require("mason").setup()

-- =========================================
--  LSP (New Native API)
-- =========================================
local lsp = vim.lsp

local servers = { "lua_ls", "html", "intelephense", "ts_ls", "gopls", "pyright" }

for _, server in ipairs(servers) do
    lsp.config(server, {
        capabilities = require("cmp_nvim_lsp").default_capabilities(),
        settings = {},
    })
    lsp.enable(server)
end

-- =========================================
--  Autocompletion (nvim-cmp + blink)
-- =========================================
local cmp = require("cmp")
cmp.setup({
    mapping = cmp.mapping.preset.insert({
        ["<CR>"] = cmp.mapping.confirm({ select = true }),
        ["<Tab>"] = cmp.mapping.select_next_item(),
        ["<S-Tab>"] = cmp.mapping.select_prev_item(),
    }),
    sources = {
        { name = "nvim_lsp" },
        { name = "buffer" },
    },
    experimental = { ghost_text = true },
})

pcall(require, "blink.cmp")

-- =========================================
--  Treesitter (Syntax Highlight)
-- =========================================
require("nvim-treesitter.configs").setup({
    ensure_installed = { "lua", "php", "blade", "html", "javascript", "json", "go" },
    highlight = { enable = true },
})

-- =========================================
--  UI & Aesthetic
-- =========================================
vim.cmd.colorscheme("tokyonight")

require("lualine").setup({
    options = { theme = "tokyonight" },
})

require("mini.pairs").setup()
require("mini.icons").setup()
require("nvim-web-devicons").setup()

require("toggleterm").setup({
    size = 15,
    open_mapping = [[<c-\>]], -- Default: Ctrl + \
    shade_terminals = true,
    shading_factor = 2,
    direction = "float", -- or 'horizontal' / 'vertical' / 'tab'
    float_opts = {
        border = "curved",
        winblend = 0,
    },
})

-- Helper: Toggle lazygit (if installed)
local Terminal = require("toggleterm.terminal").Terminal
local lazygit = Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" })
function _lazygit_toggle()
    lazygit:toggle()
end

-- Keymaps for ToggleTerm

-- =========================================
--  Display Settings
-- =========================================
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.cursorline = true
vim.opt.signcolumn = "yes"
vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.sidescrolloff = 8

-- Dynamic relative numbers (like LazyVim)
vim.api.nvim_create_autocmd("InsertEnter", {
    callback = function()
        vim.opt.relativenumber = false
    end,
})
vim.api.nvim_create_autocmd("InsertLeave", {
    callback = function()
        vim.opt.relativenumber = true
    end,
})

-- =========================================
--  Clipboard Integration (WSL)
-- =========================================
-- Yank to Windows clipboard (requires `clip.exe` in WSL)
if vim.fn.has("wsl") == 1 then
    vim.api.nvim_create_autocmd("TextYankPost", {
        callback = function()
            vim.fn.system("clip.exe", vim.fn.getreg('"'))
        end,
    })
    vim.opt.clipboard = "unnamedplus"
end

-- =========================================
--  Diagnostics / Auto Lint + Format
-- =========================================
vim.diagnostic.config({
    virtual_text = { prefix = "ΓùÅ" },
    signs = true,
    underline = true,
    update_in_insert = false,
    severity_sort = true,
})

local lsp_format_group = vim.api.nvim_create_augroup("LspAutoFormat", { clear = true })
vim.api.nvim_create_autocmd("BufWritePre", {
    group = lsp_format_group,
    callback = function(event)
        local client = vim.lsp.get_clients({ bufnr = event.buf })[1]
        if client and client.supports_method("textDocument/formatting") then
            vim.lsp.buf.format({ async = false })
        end
    end,
})

-- =========================================
--  Keymaps
-- =========================================
vim.g.mapleader = " "
vim.g.maplocalleader = " "
local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }

-- LazyVim-style FZF bindings
keymap("n", "<leader>ff", function()
    require("fzf-lua").files()
end, { desc = "Find files", unpack(opts) })
keymap("n", "<leader>fg", function()
    require("fzf-lua").live_grep()
end, { desc = "Live grep", unpack(opts) })
keymap("n", "<leader>fb", function()
    require("fzf-lua").buffers()
end, { desc = "Find buffers", unpack(opts) })
keymap("n", "<leader>fh", function()

require("fzf-lua").help_tags()
end, { desc = "Find help", unpack(opts) })

-- Format & Diagnostics
keymap("n", "<leader>lf", function()
    vim.lsp.buf.format({ async = true })
end, { desc = "Format file", unpack(opts) })
keymap("n", "<leader>ld", vim.diagnostic.open_float, { desc = "Show diagnostics", unpack(opts) })
keymap("n", "<leader>ln", vim.diagnostic.goto_next, { desc = "Next diagnostic", unpack(opts) })
keymap("n", "<leader>lp", vim.diagnostic.goto_prev, { desc = "Prev diagnostic", unpack(opts) })

-- Quick actions
keymap("n", "<leader>w", "<cmd>w<CR>", { desc = "Save file", unpack(opts) })
keymap("n", "<leader>q", "<cmd>q<CR>", { desc = "Quit Neovim", unpack(opts) })

vim.keymap.set("n", "<leader>ft", "<cmd>ToggleTerm<CR>", { desc = "Toggle terminal" })
vim.keymap.set("n", "<leader>fu", "<cmd>lua _lazygit_toggle()<CR>", { desc = "Toggle Lazygit (if available)" })
vim.keymap.set("t", "<Esc>", [[<C-\><C-n>]], { desc = "Exit terminal mode" })

keymap("n", "<leader>bb", "<cmd>bnext<CR>", { desc = "Next buffer", unpack(opts) })
keymap("n", "<leader>bp", "<cmd>bprevious<CR>", { desc = "Previous buffer", unpack(opts) })
keymap("n", "<leader>bd", "<cmd>bd<CR>", { desc = "Delete current buffer", unpack(opts) })


Enter fullscreen mode Exit fullscreen mode
-- =========================================
--  NeoVim 0.12+ Native LSP (no cmp)
-- =========================================

-- Basic editor settings
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.tabstop = 2
vim.opt.softtabstop = 2
vim.cmd("set completeopt+=noselect")

-- =========================================
--  Plugins (native vim.pack)
-- =========================================
vim.pack.add({
    { src = "https://github.com/neovim/nvim-lspconfig" },
    { src = "https://github.com/mason-org/mason.nvim" },
    { src = "https://github.com/mason-org/mason-lspconfig.nvim" },
    { src = "https://github.com/WhoIsSethDaniel/mason-tool-installer.nvim" },
})

-- =========================================
--  Mason setup
-- =========================================
require("mason").setup()
require("mason-lspconfig").setup()

require("mason-tool-installer").setup({
    ensure_installed = {
        -- Core language servers
        "lua_ls",
        "html",
        "cssls",
        "intelephense",
        "emmet_ls",
        --"gopls",

        -- Formatters / tools
        "stylua",
        "blade-formatter",
    },
})

-- =========================================
--  LSP Configurations
-- =========================================

-- Lua (for Neovim config)
vim.lsp.config("lua_ls", {
    settings = {
        Lua = {
            runtime = { version = "LuaJIT" },
            diagnostics = { globals = { "vim", "require" } },
            workspace = { library = vim.api.nvim_get_runtime_file("", true) },
            telemetry = { enable = false },
        },
    },
})

-- HTML
vim.lsp.config("html", {
    filetypes = { "html", "blade", "php" },
    init_options = { provideFormatter = true },
})

-- CSS
vim.lsp.config("cssls", {
    settings = {
        css = { validate = true },
        scss = { validate = true },
        less = { validate = true },
    },
})

-- PHP (Intelephense)
vim.lsp.config("intelephense", {
    filetypes = { "php", "blade" },
    settings = {
        intelephense = {
            environment = {
                includePaths = { "app", "routes", "resources/views" },
            },
            files = {
                maxSize = 5000000,
            },
            stubs = {
                "apache",
                "bcmath",
                "bz2",
                "calendar",
                "Core",
                "curl",
                "date",
                "dom",
                "fileinfo",
                "filter",
                "ftp",
                "gd",
                "hash",
                "iconv",
                "json",
                "libxml",
                "mbstring",
                "openssl",
                "pcre",
                "PDO",
                "pdo_mysql",
                "Phar",
                "readline",
                "Reflection",
                "session",
                "SimpleXML",
                "sockets",
                "sodium",
                "standard",
                "tokenizer",
                "xml",
                "xmlreader",
                "xmlwriter",
                "zip",
                "zlib",
                "laravel",
                "wordpress",
                "woocommerce",
            },
        },
    },
})

-- Laravel Blade (via emmet + formatter)
vim.lsp.config("emmet_ls", {
    filetypes = { "html", "css", "blade", "php" },
    init_options = {
        html = { options = { ["bem.enabled"] = true } },
    },
})

-- =========================================
--  Native autocompletion trigger
-- =========================================
vim.api.nvim_create_autocmd("LspAttach", {
    callback = function(ev)
        local client = vim.lsp.get_client_by_id(ev.data.client_id)
        if client ~= nil and client:supports_method("textDocument/completion") then
            vim.lsp.completion.enable(true, client.id, ev.buf, { autotrigger = true })
        end
    end,
})

Enter fullscreen mode Exit fullscreen mode

Ini yang terbaharu, telah dioptimize ke 155ms load.

-- =========================================
--  NeoVim 0.12+ Native Pack + LSP Config, optimize  with load 155ms
-- =========================================

-- Bootstrap plugins (native pack)
vim.pack.add({
    { src = "https://github.com/williamboman/mason.nvim.git" },
    { src = "https://github.com/williamboman/mason-lspconfig.nvim.git" }, -- ✅ Added
    { src = "https://github.com/neovim/nvim-lspconfig.git" },
    { src = "https://github.com/nvim-treesitter/nvim-treesitter.git",  build = ":TSUpdate" },
    { src = "https://github.com/hrsh7th/nvim-cmp.git" },
    { src = "https://github.com/hrsh7th/cmp-nvim-lsp.git" },
    { src = "https://github.com/hrsh7th/cmp-buffer.git" },
    { src = "https://github.com/L3MON4D3/LuaSnip.git" },
    { src = "https://github.com/echasnovski/mini.pairs.git" },
    { src = "https://github.com/echasnovski/mini.icons.git" },
    { src = "https://github.com/nvim-lualine/lualine.nvim.git" },
    { src = "https://github.com/ibhagwan/fzf-lua.git" },
    { src = "https://github.com/folke/tokyonight.nvim.git" },
    { src = "https://github.com/akinsho/toggleterm.nvim.git" },
    -- ❌ Removed nvim-web-devicons (using mini.icons instead)
})

-- =========================================
--  Mason setup
-- =========================================
require("mason").setup()
require("mason-lspconfig").setup({
    -- ensure_installed = { "lua_ls", "html", "intelephense", "ts_ls", "gopls", "pyright" },

})

-- =========================================
--  Autocompletion (nvim-cmp) ΓÇö must come BEFORE LSP config
-- =========================================
local cmp = require("cmp")
local luasnip = require("luasnip")

require("luasnip.loaders.from_vscode").lazy_load() -- optional: load VS Code snippets

cmp.setup({
    snippet = {
        expand = function(args)
            luasnip.lsp_expand(args.body)
        end,
    },
    mapping = cmp.mapping.preset.insert({
        ["<CR>"] = cmp.mapping.confirm({ select = true }),
        ["<Tab>"] = cmp.mapping.select_next_item(),
        ["<S-Tab>"] = cmp.mapping.select_prev_item(),
    }),
    sources = {
        { name = "nvim_lsp" },
        { name = "luasnip" }, -- ✅ Added
        { name = "buffer" },
    },
    experimental = { ghost_text = true },
})

-- =========================================
--  LSP (New Native API)
-- =========================================
local lsp = vim.lsp
local capabilities = require("cmp_nvim_lsp").default_capabilities() -- ✅ Now safe to call

local servers = { "lua_ls", "html", "intelephense", "ts_ls", "gopls", "pyright" }

for _, server in ipairs(servers) do
    lsp.config(server, {
        capabilities = capabilities,
        settings = {},
    })
    lsp.enable(server)
end

-- Optional: enhance lua_ls
lsp.config("lua_ls", {
    settings = {
        Lua = {
            diagnostics = { globals = { "vim" } },
            workspace = { checkThirdParty = false },
        },
    },
})

-- =========================================
--  Treesitter (Syntax Highlight)
-- =========================================
require("nvim-treesitter.configs").setup({
    ensure_installed = { "lua", "php", "blade", "html", "javascript", "json", "go" },
    highlight = { enable = true },
})

-- =========================================
--  UI & Aesthetic
-- =========================================
vim.cmd.colorscheme("tokyonight")

-- ✅ Mock nvim-web-devicons for compatibility
require("mini.icons").setup()
require("mini.icons").mock_nvim_web_devicons()

require("lualine").setup({
    options = { theme = "tokyonight" },
})

require("mini.pairs").setup()
require("toggleterm").setup({
    size = 15,
    open_mapping = [[<c-\>]],
    shade_terminals = true,
    shading_factor = 2,
    direction = "float",
    float_opts = { border = "curved", winblend = 0 },
})

-- Helper: Toggle lazygit (if installed)
local Terminal = require("toggleterm.terminal").Terminal
local lazygit = Terminal:new({ cmd = "lazygit", hidden = true, direction = "float" })
function _lazygit_toggle()
    lazygit:toggle()
end

-- =========================================
--  Display Settings
-- =========================================
vim.opt.number = true
vim.opt.relativenumber = true
vim.opt.cursorline = true
vim.opt.signcolumn = "yes"
vim.opt.termguicolors = true
vim.opt.scrolloff = 8
vim.opt.sidescrolloff = 8

-- =========================================
--  Clipboard Integration (WSL)
-- =========================================
--if vim.fn.has("wsl") == 1 then
--  vim.api.nvim_create_autocmd("TextYankPost", {
--      callback = function()
--          vim.fn.system("clip.exe", vim.fn.getreg('"'))
--      end,
--  })
--  vim.opt.clipboard = "unnamedplus"
--end


-- =========================================
--  Clipboard Integration (WSL - Lazy load)
-- =========================================
if vim.fn.has("wsl") == 1 then
    -- Simple manual yank -> clip.exe
    vim.api.nvim_create_autocmd("TextYankPost", {
        callback = function()
            vim.fn.system("clip.exe", vim.fn.getreg('"'))
        end,
    })

    -- Defer clipboard provider to load after UI ready (for speed)
    vim.api.nvim_create_autocmd("VimEnter", {
        once = true,
        callback = function()
            vim.defer_fn(function()
                vim.opt.clipboard = "unnamedplus"
            end, 300) -- delay 300ms after startup
        end,
    })
end
-- =========================================
--  Diagnostics / Auto Lint + Format
-- =========================================
vim.diagnostic.config({
    virtual_text = { prefix = "ΓùÅ" },
    signs = true,
    underline = true,
    update_in_insert = false,
    severity_sort = true,
})

-- Auto format before save
local lsp_format_group = vim.api.nvim_create_augroup("LspAutoFormat", { clear = true })
vim.api.nvim_create_autocmd("BufWritePre", {
    group = lsp_format_group,
    callback = function(event)
        local client = vim.lsp.get_clients({ bufnr = event.buf })[1]
        if client and client.supports_method("textDocument/formatting") then
            vim.lsp.buf.format({ async = false })
        end
    end,
})

-- =========================================
--  Keymaps
-- =========================================
vim.g.mapleader = " "
vim.g.maplocalleader = " "
local keymap = vim.keymap.set
local opts = { noremap = true, silent = true }

-- FZF
keymap("n", "<leader>ff", function() require("fzf-lua").files() end, opts)
keymap("n", "<leader>fg", function() require("fzf-lua").live_grep() end, opts)
keymap("n", "<leader>fb", function() require("fzf-lua").buffers() end, opts)
keymap("n", "<leader>fh", function() require("fzf-lua").help_tags() end, opts)

-- Format & Diagnostics
keymap("n", "<leader>lf", function() vim.lsp.buf.format({ async = true }) end, opts)
keymap("n", "<leader>ld", vim.diagnostic.open_float, opts)
keymap("n", "<leader>ln", vim.diagnostic.goto_next, opts)
keymap("n", "<leader>lp", vim.diagnostic.goto_prev, opts)

-- Quick actions
keymap("n", "<leader>w", "<cmd>w<CR>", opts)
keymap("n", "<leader>q", "<cmd>q<CR>", opts)
keymap("n", "<leader>ft", "<cmd>ToggleTerm<CR>", opts)
keymap("n", "<leader>fu", "<cmd>lua _lazygit_toggle()<CR>", opts)
keymap("t", "<Esc>", [[<C-\><C-n>]], opts)

-- Buffer navigation
keymap("n", "<leader>bb", "<cmd>bnext<CR>", opts)
keymap("n", "<leader>bp", "<cmd>bprevious<CR>", opts)
keymap("n", "<leader>bd", "<cmd>bd<CR>", opts)

-- =========================================
--  Memory Watcher
-- =========================================
local api = vim.api
local timer = vim.loop.new_timer()
local win, buf
local last = 0

local function create_win()
    buf = api.nvim_create_buf(false, true)
    local opts = {
        relative = "editor",
        width = 25,
        height = 3,
        row = 1,
        col = vim.o.columns - 28,
        style = "minimal",
        border = "rounded",
    }
    win = api.nvim_open_win(buf, false, opts)
end

local function update_mem()
    local current = vim.loop.resident_set_memory() / (1024 * 1024)
    local diff = current - last
    local sign = diff >= 0 and "+" or "-"
    local text = {
        string.format("Mem: %.2f MB", current),
        string.format("Change: %s%.2f MB", sign, math.abs(diff)),
    }
    api.nvim_buf_set_lines(buf, 0, -1, false, text)
    last = current
end

vim.api.nvim_create_user_command("MemWatch", function()
    if win and api.nvim_win_is_valid(win) then
        print("Memory watcher already running")
        return
    end
    create_win()
    timer:start(0, 2000, vim.schedule_wrap(update_mem))
    print("MemoryWarning Memory watcher started")
end, {})

vim.api.nvim_create_user_command("MemWatchStop", function()
    timer:stop()
    timer:close()
    if win and api.nvim_win_is_valid(win) then
        api.nvim_win_close(win, true)
    end
    print("MemoryWarning Memory watcher stopped")
end, {})

-- Auto-stop memory watcher on exit
vim.api.nvim_create_autocmd("VimLeavePre", {
    callback = function()
        pcall(vim.cmd.MemWatchStop)
    end,
})

-- =========================================
--  Plugin Update Helper
-- =========================================
vim.api.nvim_create_user_command("PackUpdate", function()
    print("🔄 Updating plugins...")
    vim.pack.update()
    print("✅ Plugins updated!")
end, { desc = "Update all plugins (vim.pack)" })

keymap("n", "<leader>pu", "<cmd>PackUpdate<CR>", { noremap = true, silent = true })

Enter fullscreen mode Exit fullscreen mode

Top comments (0)