DEV Community

Cover image for Neovim LSP to replace VSCode
Cason Adams
Cason Adams

Posted on • Updated on

Neovim LSP to replace VSCode

If you are looking for a much simpler solution to replacing VSCode with a terminal editor I suggest reading my minimal vim post.

TLDR;

All the code for this is availible nvim-code

Setup

This post is going to assume that neovim 0.6+ is installed and ready to go. From that point lets lay down the directory structure we are going to be dealing with.

Neovim defaults to using ${HOME}/.config/nvim as the configuration directory. I am going to build off that as the base for config files.

nvim
├── after
│   └── ftplugin
│       └── python.lua
├── init.lua
├── lua
│   ├── _lsp.lua
│   ├── _options.lua
│   ├── _plugins.lua
│   ├── _statusline.lua
│   ├── _telescope.lua
│   ├── _treesitter.lua
│   └── _whichkey.lua
Enter fullscreen mode Exit fullscreen mode

init.lua

require("_options")
require("_plugins")
require("_lsp")
require("_treesitter")
require("_telescope")
require("_whichkey")
require("_statusline")

vim.cmd("colorscheme walh-gruvbox")
Enter fullscreen mode Exit fullscreen mode

_options.lua

I'm not going to cover all the options available, but here are some common ones that can be used or omitted. Heavily inspired by lunarvim.

vim.g.mapleader = " "

vim.g.border_style = "rounded"
vim.g.markdown_fenced_languages = {
    "bash=sh",
}

vim.opt.backup = false -- creates a backup file
vim.opt.clipboard = "" -- don't use clipboard
vim.opt.cmdheight = 1 -- more space in the neovim command line for displaying messages
vim.opt.colorcolumn = "99999" -- fixes indentline for now
vim.opt.completeopt = { "menuone", "noselect" }
vim.opt.conceallevel = 0 -- so that `` is visible in markdown files
vim.opt.cursorline = true -- highlight the current line
vim.opt.expandtab = true -- convert tabs to spaces
vim.opt.fileencoding = "utf-8" -- the encoding written to a file
vim.opt.foldexpr = "" -- set to "nvim_treesitter#foldexpr()" for treesitter based folding
vim.opt.foldmethod = "manual" -- folding set to "expr" for treesitter based folding
vim.opt.hidden = true -- required to keep multiple buffers and open multiple buffers
vim.opt.hlsearch = true -- highlight all matches on previous search pattern
vim.opt.ignorecase = true -- ignore case in search patterns
vim.opt.list = true
vim.opt.listchars = "tab:│ ,trail:·,nbsp:+"
vim.opt.number = true -- set numbered lines
vim.opt.numberwidth = 1 -- set number column width to 2 {default 4}
vim.opt.pumheight = 10 -- pop up menu height
vim.opt.relativenumber = false -- set relative numbered lines
vim.opt.scrolloff = 4 -- is one of my fav
vim.opt.shiftwidth = 2 -- the number of spaces inserted for each indentation
vim.opt.showmode = false -- we don't need to see things like -- INSERT -- anymore
vim.opt.sidescrolloff = 4
vim.opt.signcolumn = "yes" -- always show the sign column otherwise it would shift the text each time
vim.opt.smartcase = true -- smart case
vim.opt.smartindent = true -- make indenting smarter again
vim.opt.spell = false -- disable spell checking
vim.opt.spelllang = "en" -- language for spell checking
vim.opt.splitbelow = true -- force all horizontal splits to go below current window
vim.opt.splitright = true -- force all vertical splits to go to the right of current window
vim.opt.swapfile = false -- creates a swapfile
vim.opt.tabstop = 2 -- insert 2 spaces for a tab
vim.opt.termguicolors = false -- set term gui colors (most terminals support this)
vim.opt.timeoutlen = 500 -- timeout length
vim.opt.title = true -- set the title of window to the value of the titlestring
vim.opt.titlestring = "%<%F - nvim" -- what the title of the window will be set to
vim.opt.undodir = vim.fn.stdpath("cache") .. "/undo"
vim.opt.undofile = true -- enable persistent undo
vim.opt.updatetime = 300 -- faster completion
vim.opt.wrap = true -- display lines as one long line
vim.opt.writebackup = false -- if a file is being edited by another program (or was written to file while editing with another program) it is not allowed to be edited

vim.opt.showtabline = 2 -- always show tabs
vim.opt.laststatus = 2 -- hide statusline
Enter fullscreen mode Exit fullscreen mode

_plugins.lua

I have to admit using neovims builtin lsp is nice but it comes with the requirement to install many plugins to get a similar experience with VSCode.

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_bootstrap = fn.system({
        "git",
        "clone",
        "--depth",
        "1",
        "https://github.com/wbthomason/packer.nvim",
        install_path,
    })
end

return require("packer").startup(function()
    use({
        "L3MON4D3/LuaSnip",
        "casonadams/walh",
        "folke/trouble.nvim",
        "hrsh7th/cmp-buffer",
        "hrsh7th/cmp-cmdline",
        "hrsh7th/cmp-nvim-lsp",
        "hrsh7th/cmp-path",
        "hrsh7th/nvim-cmp",
        "jose-elias-alvarez/null-ls.nvim",
        "neovim/nvim-lspconfig",
        "nvim-lua/lsp-status.nvim",
        "nvim-treesitter/nvim-treesitter",
        "saadparwaiz1/cmp_luasnip",
        "tamago324/nlsp-settings.nvim",
        "wbthomason/packer.nvim",
        "williamboman/nvim-lsp-installer",
    })
    use({
        "rafamadriz/friendly-snippets",
    })
    use({
        "nvim-telescope/telescope.nvim",
        requires = { "nvim-lua/plenary.nvim" },
    })
    use({
        "nvim-lualine/lualine.nvim",
        requires = { "kyazdani42/nvim-web-devicons", opt = true },
    })
    use({
        "folke/which-key.nvim",
        config = function()
            require("which-key").setup({})
        end,
    })
    use({
        "terrortylor/nvim-comment",
        config = function()
            require("nvim_comment").setup({})
        end,
    })
    use({
        "lewis6991/gitsigns.nvim",
        config = function()
            require("gitsigns").setup({ yadm = { enable = true } })
        end,
    })
    use({
        "ethanholz/nvim-lastplace",
        event = "BufRead",
        config = function()
            require("nvim-lastplace").setup({
                lastplace_ignore_buftype = { "quickfix", "nofile", "help" },
                lastplace_ignore_filetype = { "gitcommit", "gitrebase", "svn", "hgcommit" },
                lastplace_open_folds = true,
            })
        end,
    })
    -- Automatically set up your configuration after cloning packer.nvim
    -- Put this at the end after all plugins
    if packer_bootstrap then
        require("packer").sync()
    end
end)
Enter fullscreen mode Exit fullscreen mode

_lsp.lua

local cmp = require("cmp")
local lsp_status = require("lsp-status")

local win = require("lspconfig.ui.windows")
local _default_opts = win.default_opts

win.default_opts = function(options)
    local opts = _default_opts(options)
    opts.border = "rounded"
    return opts
end

-- statusline progress setup
lsp_status.config({
    current_function = false,
    show_filename = false,
    diagnostics = false,
    status_symbol = "",
    select_symbol = nil,
    update_interval = 200,
})

-- completion setup
cmp.setup({
    snippet = {
        expand = function(args)
            -- vim.fn["vsnip#anonymous"](args.body)
            require("luasnip").lsp_expand(args.body) -- For `luasnip` users.
            -- vim.fn["UltiSnips#Anon"](args.body)
        end,
    },
    mapping = {
        ["<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({ select = false }),
        ["<Tab>"] = cmp.mapping(cmp.mapping.select_next_item(), { "i", "s" }),
        ["<S-Tab>"] = cmp.mapping(cmp.mapping.select_prev_item(), { "i", "s" }),
    },
    sources = {
        { name = "nvim_lsp" },
        { name = "luasnip" },
        -- { name = "ultisnips" },
        -- { name = "vsnip" },
        { name = "buffer" },
        { name = "path" },
    },
})

-- helper function for mappings
local m = function(mode, key, result)
    vim.api.nvim_buf_set_keymap(0, mode, key, "<cmd> " .. result .. "<cr>", {
        noremap = true,
        silent = true,
    })
end

-- function to attach completion when setting up lsp
local on_attach = function(client)
    lsp_status.register_progress()
    lsp_status.on_attach(client)

    -- Mappings.
    m("n", "ga", "lua vim.lsp.buf.code_action()")
    m("n", "gD", "lua vim.lsp.buf.declaration()")
    m("n", "gd", "lua vim.lsp.buf.definition()")
    m("n", "ge", "lua vim.lsp.diagnostic.goto_next()")
    m("n", "gE", "lua vim.lsp.diagnostic.goto_prev()")
    m("n", "gi", "lua vim.lsp.buf.implementation()")
    m("n", "gr", "lua vim.lsp.buf.references()")
    m("n", "K", "lua vim.lsp.buf.hover()")
    -- m("n", "<space>rn", "lua vim.lsp.buf.rename()")
    m("n", "gl", "lua vim.lsp.diagnostic.show_line_diagnostics()")
    -- m("n", "<space>f", "lua vim.lsp.buf.formatting()")
end

-- setup lsp installer
local lsp_installer = require("nvim-lsp-installer")
-- Provide settings first!
lsp_installer.settings({
    ui = {
        icons = {
            server_installed = "✓",
            server_pending = "➜",
            server_uninstalled = "✗",
        },
    },
})
lsp_installer.on_server_ready(function(server)
    local opts = {
        on_attach = on_attach,
        capabilities = require("cmp_nvim_lsp").update_capabilities(vim.lsp.protocol.make_client_capabilities()),
        flags = {
            debounce_text_changes = 150,
        },
    }
    server:setup(opts)
end)

-- lsp settings
require("nlspsettings").setup()

-- diagnostics
vim.diagnostic.config({
    virtual_text = false,
    underline = true,
    float = {
        source = "always",
    },
    severity_sort = true,
    --[[ virtual_text = {
      prefix = "»",
      spacing = 4,
    }, ]]
    signs = true,
    update_in_insert = false,
})
Enter fullscreen mode Exit fullscreen mode

_treesitter.lua

require'nvim-treesitter.configs'.setup {
  ensure_installed = "maintained",
  sync_install = false,
  highlight = {
    enable = true,
    additional_vim_regex_highlighting = false,
  },
}
Enter fullscreen mode Exit fullscreen mode

_telescope.lua

require("telescope").setup({
    defaults = {
        border = true,
        layout_strategy = "bottom_pane",
        layout_config = {
            height = 0.30,
            width = 1.00,
        },
        -- path_display = { "shorten" },
        sorting_strategy = "ascending",
    },
})

require("trouble").setup({
  icons=false
})
Enter fullscreen mode Exit fullscreen mode

_whichkey.lua

local which_key = {
    setup = {
        plugins = {
            marks = true,
            registers = true,
            presets = {
                operators = false,
                motions = false,
                text_objects = false,
                windows = true,
                nav = true,
                z = true,
                g = true,
            },
            spelling = { enabled = true, suggestions = 20 },
        },
        icons = {
            breadcrumb = "»",
            separator = "➜",
            group = "+",
        },
        window = {
            border = "none", -- none, single, double, shadow
            position = "bottom", -- bottom, top
            margin = { 1, 0, 1, 0 },
            padding = { 2, 2, 2, 2 },
        },
        layout = {
            height = { min = 4, max = 25 },
            width = { min = 20, max = 50 },
            spacing = 3,
        },
        hidden = { "<silent>", "<cmd>", "<Cmd>", "<CR>", "call", "lua", "^:", "^ " },
        show_help = true,
    },

    opts = {
        mode = "n",
        prefix = "<leader>",
        buffer = nil,
        silent = true,
        noremap = true,
        nowait = true,
    },
    vopts = {
        mode = "v",
        prefix = "<leader>",
        buffer = nil,
        silent = true,
        noremap = true,
        nowait = true,
    },
    -- NOTE: Prefer using : over <cmd> as the latter avoids going back in normal-mode.
    -- see https://neovim.io/doc/user/map.html#:map-cmd
    vmappings = {},
    mappings = {
        ["c"] = { ":BufferClose!<CR>", "Close Buffer" },
        ["e"] = { ":Telescope file_browser <CR>", "File Browser" },
        ["f"] = { ":Telescope find_files <CR>", "Find File" },
        ["h"] = { ":nohlsearch<CR>", "No Highlight" },
        b = {
            name = "Buffers",
            l = { ":Telescope buffers<CR>", "List Buffers" },
            b = { ":b#<cr>", "Previous" },
            d = { ":bd<cr>", "Delete" },
            f = { ":Telescope buffers <cr>", "Find" },
            n = { ":bn<cr>", "Next" },
            p = { ":bp<cr>", "Previous" },
        },
        p = {
            name = "Packer",
            c = { ":PackerCompile<cr>", "Compile" },
            i = { ":PackerInstall<cr>", "Install" },
            r = { ":lua require('lvim.utils').reload_lv_config()<cr>", "Reload" },
            s = { ":PackerSync<cr>", "Sync" },
            S = { ":PackerStatus<cr>", "Status" },
            u = { ":PackerUpdate<cr>", "Update" },
        },
        l = {
            name = "LSP",
            a = { ":Telescope lsp_code_actions<cr>", "Code Action" },
            d = {
                ":Telescope lsp_document_diagnostics<cr>",
                "Document Diagnostics",
            },
            w = {
                ":Telescope diagnostics<cr>",
                "Workspace Diagnostics",
            },
            f = { ":lua vim.lsp.buf.formatting()<cr>", "Format" },
            i = { ":LspInfo<cr>", "Info" },
            I = { ":LspInstallInfo<cr>", "Installer Info" },
            r = { ":lua vim.lsp.buf.rename()<cr>", "Rename" },
        },
        s = {
            name = "Search",
            b = { ":Telescope git_branches <cr>", "Checkout branch" },
            c = { ":Telescope colorscheme <cr>", "Colorscheme" },
            C = { ":Telescope commands <cr>", "Commands" },
            f = { ":Telescope find_files <cr>", "Find File" },
            h = { ":Telescope help_tags <cr>", "Find Help" },
            j = { ":Telescope jumplist <cr>", "Jumplist" },
            k = { ":Telescope keymaps <cr>", "Keymaps" },
            M = { ":Telescope man_pages <cr>", "Man Pages" },
            r = { ":Telescope oldfiles <cr>", "Open Recent File" },
            R = { ":Telescope registers <cr>", "Registers" },
            t = { ":Telescope live_grep <cr>", "Text" },
            n = { ":Telescope live_grep search_dirs={os.getenv('NOTES')} <cr>", "Notes" },
            p = {
                ":lua require('telescope.builtin.internal').colorscheme({enable_preview = true})<cr>",
                "Colorscheme with Preview",
            },
        },
        T = {
            name = "Treesitter",
            i = { ":TSConfigInfo<cr>", "Info" },
        },
        t = {
            name = "Diagnostics",
            t = { "<cmd>TroubleToggle<cr>", "trouble" },
            w = { "<cmd>TroubleToggle workspace_diagnostics<cr>", "workspace" },
            d = { "<cmd>TroubleToggle document_diagnostics<cr>", "document" },
            q = { "<cmd>TroubleToggle quickfix<cr>", "quickfix" },
            l = { "<cmd>TroubleToggle loclist<cr>", "loclist" },
            r = { "<cmd>TroubleToggle lsp_references<cr>", "references" },
        },
    },
}

function map(mode, lhs, rhs, opts)
        local options = { noremap = true, silent = true }
    if opts then
        options = vim.tbl_extend("force", options, opts)
    end
    vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end

map("n", "H", ":bp<CR>")
map("n", "L", ":bn<CR>")

map("n", "<tab>", ":tabnext<CR>")
map("n", "<S-tab>", ":tabprevious<CR>")

map("n", "<C-h>", ":wincmd h<CR>")
map("n", "<C-j>", ":wincmd j<CR>")
map("n", "<C-k>", ":wincmd k<CR>")
map("n", "<C-l>", ":wincmd l<CR>")

local wk = require("which-key")
wk.setup(which_key.setup)

local opts = which_key.opts
local vopts = which_key.vopts

local mappings = which_key.mappings
local vmappings = which_key.vmappings

wk.register(mappings, opts)
wk.register(vmappings, vopts)

if which_key.on_config_done then
    which_key.on_config_done(wk)
end
Enter fullscreen mode Exit fullscreen mode

_statusline.lua

local lsp_status = require("lsp-status")

local function lsp_progress()
    return lsp_status.status()
end

local function extract_highlight_colors(color_group, scope)
    if vim.fn.hlexists(color_group) == 0 then
        return nil
    end
    local color = vim.api.nvim_get_hl_by_name(color_group, true)
    if color.background ~= nil then
        color.bg = string.format("#%06x", color.background)
        color.background = nil
    end
    if color.foreground ~= nil then
        color.fg = string.format("#%06x", color.foreground)
        color.foreground = nil
    end
    if scope then
        return color[scope]
    end
    return color
end

local colors = {
    gray = 8,
    red = 9,
    green = 10,
    yellow = 11,
    blue = 12,
    magenta = 13,
    cyan = 14,
    white = 15,
    background = extract_highlight_colors("StatusLine", "bg"),
    foreground = 7,
}

local custom_theme = {
    normal = {
        a = { bg = colors.foreground, fg = colors.background },
        b = { bg = colors.background, fg = colors.foreground },
        c = { bg = colors.background, fg = colors.foreground },
    },
    insert = {
        a = { bg = colors.cyan, fg = colors.background },
        b = { bg = colors.background, fg = colors.cyan },
        c = { bg = colors.background, fg = colors.foreground },
    },
    visual = {
        a = { bg = colors.yellow, fg = colors.background },
        b = { bg = colors.background, fg = colors.yellow },
        c = { bg = colors.background, fg = colors.foreground },
    },
    replace = {
        a = { bg = colors.red, fg = colors.background },
        b = { bg = colors.background, fg = colors.red },
        c = { bg = colors.background, fg = colors.foreground },
    },
    command = {
        a = { bg = colors.magenta, fg = colors.background },
        b = { bg = colors.background, fg = colors.magenta },
        c = { bg = colors.background, fg = colors.foreground },
    },
    inactive = {
        a = { bg = colors.background, fg = colors.gray },
        b = { bg = colors.background, fg = colors.gray },
        c = { bg = colors.background, fg = colors.gray },
    },
}

local components = {
    mode = {
        function()
            return " "
        end,
        padding = { left = 0, right = 0 },
    },
    filename = {
        "filename",
    },
    diagnostics = {
        "diagnostics",
        sources = { "nvim_diagnostic" },
        symbols = { error = " ", warn = " ", info = " ", hint = " " },
    },
    treesitter = {
        function()
            local b = vim.api.nvim_get_current_buf()
            if next(vim.treesitter.highlighter.active[b]) then
                return ""
            end
            return ""
        end,
    },
    location = { "location" },
    progress = { "progress" },
    encoding = {
        "o:encoding",
        fmt = string.upper,
    },
    filetype = { "filetype" },
}

require("lualine").setup({
    options = {
        theme = custom_theme,
        icons_enabled = false,
        component_separators = { left = "", right = "" },
        section_separators = { left = "", right = "" },
        disabled_filetypes = { "dashboard", "NvimTree", "Outline" },
    },
    sections = {
        lualine_a = {},
        lualine_b = {
            components.filename,
        },
        lualine_c = {
            components.diff,
        },
        lualine_x = {
            lsp_progress,
            components.diagnostics,
        },
        lualine_y = {
            components.treesitter,
        },
        lualine_z = {},
    },
    inactive_sections = {
        lualine_a = {},
        lualine_b = {
            "filename",
        },
        lualine_c = {},
        lualine_x = {},
        lualine_y = {},
        lualine_z = {},
    },
    tabline = {
        lualine_a = {},
        lualine_b = { { "buffers" } },
        lualine_c = {},
        lualine_x = {},
        lualine_y = { { "tabs", mode = 0 } },
        lualine_z = {},
    },
    extensions = { "nvim-tree" },
})
Enter fullscreen mode Exit fullscreen mode

Conclusion

Sooo much config I know! I am sorry about all of that. But it think having all of this config makes everything customizable for anyone. Take the settings I made as a grain of salt, I have an opinion about how vim should be for me. Hopefully this is just a foundation that someone can use to get up and running then modify things to the prefered settings. I also, left some commented out settings for further tinkering.

So if you have made it this far the next step is to try it out. Let see how it works.

main.py test

Create a file nvim main.py. On first load nvim is going to complain because none of the plugins are setup. Go ahead and just type q until the complaints end. We need restart nvim now that packer has been installed. qa then nvim main.py. Now we have packer we can :PackerSync this will install and update all the plugins defined in _plugins.lua. Close nvim one more time :qa. Now we got that over with then get on to testing out our setup. nvim main.py (notice that tree-sitter is installing a few things) let that happen in the background. Wait for tree-sitter to finish before exiting. Put this snippet in the file.

#!/usr/bin/env python

def echo(msg):
    print msg

if __name__ == "__main__":
    echo("Hello World!")
Enter fullscreen mode Exit fullscreen mode

Save :w

install pyright server

Now we need to install the lsp server to work with python files. This can be done a few different ways fastest is to :LspInstall pyright, or one can access a "dashboard" with :LspInstallInfo and then use the help ? to see options. u will upgrade the server under the cursor, and i will install the server under the cursor.

Now that pyright is installed lets make sure it is working.

testing pyright

Notice line 4 msg is underlined and an E is indicated in the gitgutter. Move the cursor to line 4 and trigger the line diagnostics gl. If you see the popup you are configured correctly!

black formatter

I didn't go into very much detail about custom settings for the language servers that get installed or formatting and linting. Here is an
w to use black as the python formatter. We are using null-ls for the formatting here.

after/ftplugin/python.lua

 local null_ls = require("null-ls")

local sources = {
    null_ls.builtins.formatting.black,
}

null_ls.setup({ sources = sources })
Enter fullscreen mode Exit fullscreen mode

Note null_ls can setup all settings in a regular way like the other lua files we created. Using the after dir / lazy loading is just one way of doing this.

Make sure black in installed pip install black. Lets try it out with our main.py file. Update it to the following, then save :w.

#!/usr/bin/env python
def echo(msg):
    print(msg)
if __name__ == "__main__":
    echo("Hello World!")
Enter fullscreen mode Exit fullscreen mode
  • Note leader is space

Now to tell nvim to format with the defined formatter send leader lf.

And the result should be a nicely formatted python file.

python format

And that about wraps it up.

Discussion (16)

Collapse
voyeg3r profile image
Sérgio Araújo

It would be great adding a safe call at each plugin setting like this:

local cmp_status_ok, cmp = pcall(require, "cmp")
if not cmp_status_ok then
    return
end
Enter fullscreen mode Exit fullscreen mode

Just in case the call fail, we just get a return without trying to read the rest of config file, the same for the packer config:

-- Use a protected call so we don't error out on first use
local status_ok, packer = pcall(require, "packer")
if not status_ok then
    return
end
Enter fullscreen mode Exit fullscreen mode
Collapse
voyeg3r profile image
Sérgio Araújo

By the way pcall it is, if I am not wrong, the same as a try catch statement.

Collapse
casonadams profile image
Cason Adams Author

Great suggestion. I updated the git repo. Not sure if I should update this post or not. I am thinking no. And hopefully most people just go look at the source repo.

Thread Thread
kchawla_pi profile image
Kshitij Chawla

I always add an update to my posts. A lot of new devs rely on good blogs to get started.

Collapse
chanid profile image
ChaniD

Why?

Collapse
casonadams profile image
Cason Adams Author

Why replace vscode?

I work in a terminal.

Collapse
sumanthlingappa profile image
Sumanth Lingappa

@casonadams
Great article.

However, I find it difficult to understand, vscode has Remote-SSH extension and you can connect vscode to your server.

My personal experience has been 'its difficult to maintain huge nvim/vim configs over a period of time'. And instead of focusing on my actual work, I end up in configure-reconfigure vim/nvim configs most of the time.

Since I am very comfortable with vim, I use vscode-vim all the time.

Thread Thread
casonadams profile image
Cason Adams Author

Thanks! It's not that vscode is bad and yes there are some other amazing features like the remote connect offering, and live share.

For me I use nvim as my daily driver because I work in a terminal all day. And I find it fun to tweak things here and there as needed.

I do follow your word of caution that one can go down a hole of wasted time with config tweaking. And the whole point of learning vim, is that's it's installed on more servers. So if you need to hop on a machine and check it out you can. But that defeats the purpose of this article, because once you configure vim this way, it's not vanilla any more.

Thanks for your comment.

Thread Thread
sumanthlingappa profile image
Sumanth Lingappa

Agreed.

I am a big fan of vim/nvim and I am using vim for 10 years.

Recently, when I looked back, I was (wasting) a lot of my time in trying out new configs just for the fun of it.

And decided to stick to vscode as the main editor, ofcourse with vscode-vim extension :-)

Thread Thread
casonadams profile image
Cason Adams Author

So I tinkered with vscode for a bit, and there is just as much config with it as there is vim. With less flexibility. Going to stick with vim. Thanks for the thoughts though.

Thread Thread
sumanthlingappa profile image
Sumanth Lingappa

@casonadams I would love to see your work in your vim config.

Have you made any videos?

Collapse
abdoulayegk profile image
Abdoulaye Balde

I also have a very simple and nice configuration check it out here.
github.com/abdoulayegk/dotefiles
Here is how it looks.
To install it just follow the instructions given in the above link or just download it and put the init.vim file inside the is file ~/.config/nvim then open nvim it will install everything for you.
Enjoy 😊🤩

Collapse
casonadams profile image
Cason Adams Author

Looks like you are using coc and viml. I have a similar (much simpler) example in this post

This post is very specific to getting up and running with neovim and the built-in LSP. Including some nice to haves to walk away from VSCode, and live in a terminal editor.

Collapse
eggbean profile image
eggbean

It'll probably take hours for me to translate my vimscript configuration to lua, so I want to hear if there would be any advantages in doing so.

Collapse
casonadams profile image
Cason Adams Author

Haha, yeah this post is my hours of converting my viml to lua. I'm not sure on the bang for the buck yet.

But using lua moving forward might open more doors.

I think if one were wanting to start using the built-in lsp stuff it will be worth the effort.

Collapse
juanfrank77 profile image
Juan F Gonzalez

Yessss. Let's go Vim!