In this how-to I am going to show you how to configure neovim to act like a small and efficient UI IDE for various programming languages.
Neovim is going to be configured in lua.
Before beginning you need the following packages installed, or ports build:
-> editors/neovim
-> www/npm
-> Clangd (if you want to have C/C++ language-server-protocol support. It should already be available in FreeBSD)
Let us begin with the folder structure.
I strived to make a clean folder structure for easy modifications and extensions, should they be needed.
1) Delete your nvim directories if you have already used neovim before, or create a backup.
Neovim usually places its directories in
Delete these directories by issuing:
If you wish to create a backup issue:
In case you want to revert back to your old settings.
2) Create the folder structure.
For creating the structure issue the following command:
Now we are going to install some plugins, starting with the plugin manager lazy vim.
Lazy vim is a plugin manager which only loads plugins if needed (lazy loads them).
Create a file called
Paste the following content into the file.
Next we are going to install plugins I consider to be enhancements for the current neovim editor.
Choose only plugins you think that you will eventually need.
1) nvim-treesitter
This plugin is a configurations and abstraction layer.
To put it into simple words, it is a tool which abstracts the steps to create .so files for different programming lanugages in order to allow precise syntax highlighting.
Create a nvim-treesitter.lua file in
In the ensure_installed section place only the languages you want to be syntax highlighted.
For a list of supported languages visit their github page.
2) My preferred color theme and transparency
This one just serves as an idea for your preferred color theme.
Create a nvim-color-theme.lua file in
To enable a transparent background (should you decide to want it), issue
3) nvim-autopairs
This plugin enables to create a pair of:
-> parentheses ()
-> square brackets []
-> triangle brackets <>
-> braces {}
-> single quotation marks ''
-> double quotation marks ""
-> backquotes ``
it puts your mouse inside the pair each time you want to create one.
Create a nvim-autopairs.lua file in
4) nvim-cmp (auto completion suggestions for many languages)
Create a nvim-cmp.lua file in
Set your theme for the window to your liking, or delete vim.api.* and the window section to get VS-Code like colors for the completion window.
If luasnip reports problems during installation, close lazy vim, and the editor.
Then reopen the editor, and type in
Now luasnip should be installed, and working.
The problem happens in luasnips make file due to a OS check from line 37 to 42, I guess.
5) nvim-neo-tree
Create a nvim-neo-tree.lua file in
6) nvim-telescope
Create a nvim-telescope.lua file in
7) nvim-lualine
Create a nvim-telescope.lua file in
Choose a config based on your preferences.
8) nvim-lspconfig
This one is quite interesting as it offers best community effort configurations for various lsp servers.
For me it works with different languages like a charm.
Create a nvim-lspconfig.lua file in
To get a list of supported LSP servers visit their github page.
Let us now create the editor configs as well as some keybindings to make the work with neovim easier.
Create a editor-settings.lua file in
Adjust the file to your liking.
Create a keybindings.lua file in
The last two keybindings (Telescope find_files, and Telescope buffers) only work if plugin number 6 (nvim-telescope) is installed.
The last step is to create a init.lua file in
Paste the following contents into the init.lua file:
These are the LSPs I am currently using.
Extend or shrink the LSP list to your liking.
If you want to install for example bashls or pyright issue the following command as root:
To uninstall language server protocols issue the following command as root:
One thing to note, I am aware that there is a debug adapter protocol (dap) and a dap-ui out there for various languages, but I am not using them right now.
If the need should ever arise, I am going to update this how-to.
Hopefully this how-to will help other users get neovim set up faster and easier for their programming needs.
If you have questions, suggestions feel free to post them.
Neovim is going to be configured in lua.
Before beginning you need the following packages installed, or ports build:
-> editors/neovim
-> www/npm
-> Clangd (if you want to have C/C++ language-server-protocol support. It should already be available in FreeBSD)
Let us begin with the folder structure.
I strived to make a clean folder structure for easy modifications and extensions, should they be needed.
1) Delete your nvim directories if you have already used neovim before, or create a backup.
Neovim usually places its directories in
~/.config, ~/.local/share, ~/.local/state.Delete these directories by issuing:
Code:
rm -rf ~/.config/nvim ~/.local/share/nvim ~/.local/state/nvim
If you wish to create a backup issue:
Code:
mv ~/.config/nvim ~/.config/nvim.bak
2) Create the folder structure.
For creating the structure issue the following command:
Code:
mkdir -p ~/.config/nvim/lua/{configs,plugin-manager,plugins,lsp-config}
Now we are going to install some plugins, starting with the plugin manager lazy vim.
Lazy vim is a plugin manager which only loads plugins if needed (lazy loads them).
Create a file called
lazy.lua in ~/.config/nvim/lua/plugins/manager by issuing:
Code:
touch ~/.config/nvim/lua/plugins/manager/lazy.lua
Paste the following content into the file.
Code:
-- Neovims plugin manager
-- Bootstrap lazy vim
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not (vim.uv or vim.loop).fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"https://github.com/folke/lazy.nvim.git",
"--branch=stable", -- latest stable release
lazypath,
})
end
vim.opt.rtp:prepend(lazypath)
-- Configure lazy vims behaviour
require("lazy").setup({
spec = {
-- Tell lazy vim where it should look for plugins
{ import = "plugins.enhancements" },
{ import = "plugins.lsp-config" }
},
checker = {
enabled = true, -- Check for plugin updates upon start
notify = false, -- Notify on update
},
change_detection = {
notify = false, -- Notify on detection change
},
})
-- Enable transparent background in lazys UI
function Transparent(color)
color = color
vim.cmd.colorscheme(color)
vim.api.nvim_set_hl(0, "Normal", { bg = "none" })
vim.api.nvim_set_hl(0, "NormalFloat", { bg = "none" })
end
Transparent()
Next we are going to install plugins I consider to be enhancements for the current neovim editor.
Choose only plugins you think that you will eventually need.
1) nvim-treesitter
This plugin is a configurations and abstraction layer.
To put it into simple words, it is a tool which abstracts the steps to create .so files for different programming lanugages in order to allow precise syntax highlighting.
Create a nvim-treesitter.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- Configuration and abstraction layer, adds more syntax highlighting for different kind of languages
return {
"nvim-treesitter/nvim-treesitter",
event = { "BufReadPre", "BufNewFile" },
build = ":TSUpdate",
dependencies = {
"windwp/nvim-ts-autotag",
},
config = function()
local treesitter = require("nvim-treesitter.configs")
treesitter.setup({
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = { enable = true },
autotag = {
enable = true,
},
ensure_installed = {
"bash",
"c",
"c_sharp",
"cmake",
"comment",
"cpp",
"css",
"csv",
"diff",
"disassembly",
"html",
"javascript",
"json",
"lua",
"make",
"python",
},
incremental_selection = {
enable = true,
keymaps = {
init_selection = "<C-space>",
node_incremental = "<C-space>",
scope_incremental = false,
node_decremental = "<bs>",
},
},
rainbow = {
enable = true,
disable = { "html" },
extended_mode = false,
max_file_lines = nil,
},
context_commentstring = {
enable = true,
enable_autocmd = false,
},
})
end,
}
For a list of supported languages visit their github page.
2) My preferred color theme and transparency
This one just serves as an idea for your preferred color theme.
Create a nvim-color-theme.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- My preferred color theme for neovim and transparency feature for the background
return {
"Mofiqul/dracula.nvim",
"xiyaowong/transparent.nvim",
lazy = false,
priority = 1000,
config = function()
vim.cmd("colorscheme dracula")
end,
}
:TransparentEnable while being inside the editor.3) nvim-autopairs
This plugin enables to create a pair of:
-> parentheses ()
-> square brackets []
-> triangle brackets <>
-> braces {}
-> single quotation marks ''
-> double quotation marks ""
-> backquotes ``
it puts your mouse inside the pair each time you want to create one.
Create a nvim-autopairs.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- Enable autopair capability for neovim
return {
"windwp/nvim-autopairs",
event = "InsertEnter",
config = function()
require("nvim-autopairs").setup({
disable_filetype = { "TelescopePrompt", "vim" },
})
end,
}
4) nvim-cmp (auto completion suggestions for many languages)
Create a nvim-cmp.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- Completion capabilities for neovim
return {
"hrsh7th/nvim-cmp",
event = "InsertEnter",
dependencies = {
"hrsh7th/cmp-buffer", -- Source for text in buffer
"hrsh7th/cmp-path", -- Source for file system paths
{
"L3MON4D3/LuaSnip", -- Snippet Engine
version = "v2.*",
build = "make install_jsregexp", -- Allow lsp-snippet-transformations
},
"rafamadriz/friendly-snippets", -- Preconfigured snippets for different languages
"onsails/lspkind.nvim", -- VS-Code like pictograms
},
config = function()
local cmp = require("cmp")
local lspkind = require("lspkind")
local luasnip = require("luasnip")
require("luasnip.loaders.from_vscode").lazy_load() -- Required for friendly-snippets to work
-- Settings for the appearance of the completion window
vim.api.nvim_set_hl(0, "CmpNormal", { bg = "#000000", fg = "#ffffff" })
vim.api.nvim_set_hl(0, "CmpSelect", { bg = "#000000", fg = "#b5010f" })
vim.api.nvim_set_hl(0, "CmpBorder", { bg = "#000000", fg = "#b5010f" })
cmp.setup({
snippet = {
expand = function(args)
luasnip.lsp_expand(args.body)
end,
},
mapping = cmp.mapping.preset.insert({
["<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.Replace,
select = true,
}),
}),
sources = cmp.config.sources({
{ name = "nvim_lsp" },
{ name = "luasnip" },
{ name = "buffer" },
{ name = "path" },
}),
window = {
completion = {
border = "rounded",
winhighlight = "Normal:CmpNormal,CursorLine:CmpSelect,FloatBorder:CmpBorder",
}
},
})
vim.cmd([[
set completeopt=menuone,noinsert,noselect
highlight! default link CmpItemKind CmpItemMenuDefault
]])
end,
}
If luasnip reports problems during installation, close lazy vim, and the editor.
Then reopen the editor, and type in
:Lazy.Now luasnip should be installed, and working.
The problem happens in luasnips make file due to a OS check from line 37 to 42, I guess.
5) nvim-neo-tree
Create a nvim-neo-tree.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- Tree like file system manager
return {
"nvim-neo-tree/neo-tree.nvim",
branch = "v3.x",
dependencies = {
"nvim-lua/plenary.nvim",
"nvim-tree/nvim-web-devicons",
"MunifTanjim/nui.nvim",
},
}
6) nvim-telescope
Create a nvim-telescope.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- A highly extendable fuzzy finder over lists
return {
"nvim-telescope/telescope.nvim",
tag = "0.1.6",
dependencies = { "nvim-lua/plenary.nvim" },
}
7) nvim-lualine
Create a nvim-telescope.lua file in
~/.config/nvim/lua/plugins/enhancements and paste the following content into it:
Code:
-- A lightweight statusline for neovim
-- Bubbles config for lualine
-- Author: lokesh-krishna
-- MIT license, see LICENSE for more details.
-- stylua: ignore
local colors = {
blue = '#80a0ff',
cyan = '#79dac8',
black = '#080808',
white = '#c6c6c6',
red = '#ff5189',
violet = '#d183e8',
grey = '#303030',
}
local bubbles_theme = {
normal = {
a = { fg = colors.black, bg = colors.violet },
b = { fg = colors.white, bg = colors.grey },
c = { fg = colors.white },
},
insert = { a = { fg = colors.black, bg = colors.blue } },
visual = { a = { fg = colors.black, bg = colors.cyan } },
replace = { a = { fg = colors.black, bg = colors.red } },
inactive = {
a = { fg = colors.white, bg = colors.black },
b = { fg = colors.white, bg = colors.black },
c = { fg = colors.white },
},
}
return {
"nvim-lualine/lualine.nvim",
dependencies = { "nvim-tree/nvim-web-devicons" },
config = function()
require('lualine').setup {
options = {
theme = bubbles_theme,
component_separators = '',
section_separators = { left = '', right = '' },
},
sections = {
lualine_a = { { 'mode', separator = { left = '' }, right_padding = 2 } },
lualine_b = { 'filename', 'branch' },
lualine_c = {'%=', --[[ add your center compoentnts here in place of this comment ]] },
lualine_x = {},
lualine_y = { 'filetype', 'progress' },
lualine_z = { { 'location', separator = { right = '' }, left_padding = 2 }, },
},
inactive_sections = {
lualine_a = { 'filename' },
lualine_b = {},
lualine_c = {},
lualine_x = {},
lualine_y = {},
lualine_z = { 'location' },
},
tabline = {},
extensions = {},
}
end,
}
8) nvim-lspconfig
This one is quite interesting as it offers best community effort configurations for various lsp servers.
For me it works with different languages like a charm.
Create a nvim-lspconfig.lua file in
~/.config/nvim/lua/plugins/lsp-config and paste the following content into it:
Code:
-- Best effort collection of LSP server configurations
return {
"neovim/nvim-lspconfig",
event = { "BufReadPre", "BufNewFile" },
dependencies = {
"hrsh7th/cmp-nvim-lsp",
{ "folke/lazydev.nvim", opts = {} },
},
config = function()
-- local nvim_lsp = require("lspconfig")
-- local protocol = require("vim.lsp.protocol")
local on_attach = function(client, bufnr)
-- Format on save
if client.server_capabilities.documentFormattingProvider then
vim.api.nvim_create_autocmd("BufWritePre", {
group = vim.api.nvim_create_augroup("Format", { clear = true }),
buffer = bufnr,
callback = function()
vim.lsp.buf.format()
end,
})
end
end
end,
}
Let us now create the editor configs as well as some keybindings to make the work with neovim easier.
Create a editor-settings.lua file in
~/.config/nvim/lua/configs and paste the following content into it:
Code:
-- Editor settings
vim.opt.number = true -- Print the line number in front of each line
vim.opt.relativenumber = true -- Show the line number relative to the line with the cursor in front of each line.
vim.opt.clipboard = "unnamedplus" -- uses the clipboard register for all operations except yank.
vim.opt.syntax = "on" -- When this option is set, the syntax with this name is loaded.
vim.opt.autoindent = true -- Copy indent from current line when starting a new line.
vim.opt.cursorline = true -- Highlight the screen line of the cursor with CursorLine.
vim.opt.expandtab = true -- In Insert mode: Use the appropriate number of spaces to insert a <Tab>.
vim.opt.shiftwidth = 4 -- Number of spaces to use for each step of (auto)indent.
vim.opt.tabstop = 4 -- Number of spaces that a <Tab> in the file counts for.
vim.opt.encoding = "UTF-8" -- Sets the character encoding used inside Vim.
vim.opt.ruler = true -- Show the line and column number of the cursor position, separated by a comma.
vim.opt.mouse = "a" -- Enable the use of the mouse. "a" you can use on all modes
vim.opt.title = true -- When on, the title of the window will be set to the value of 'titlestring'
vim.opt.hidden = true -- When on a buffer becomes hidden when it is |abandon|ed
vim.opt.ttimeoutlen = 0 -- The time in milliseconds that is waited for a key code or mapped key sequence to complete.
vim.opt.wildmenu = true -- When 'wildmenu' is on, command-line completion operates in an enhanced mode.
vim.opt.showcmd = true -- Show (partial) command in the last line of the screen. Set this option off if your terminal is slow.
vim.opt.showmatch = true -- When a bracket is inserted, briefly jump to the matching one.
vim.opt.inccommand = "split" -- When nonempty, shows the effects of :substitute, :smagic, :snomagic and user commands with the :command-preview flag as you type.
vim.opt.splitright = true -- When on, splitting a window will put the new windows to the right side of the current one
vim.opt.splitbelow = true -- When on, splitting a window will put the new window below the current one
vim.opt.termguicolors = true -- Enable terminal GUI colors in neovims UI
Create a keybindings.lua file in
~/.config/nvim/lua/configs and paste the following content into it:
Code:
-- Keybindings for neovim editor
-- Redefine map leader from "\" to " "
vim.g.mapleader = " "
-- Make mapping to keys easier
local function map(mode, lhs, rhs)
vim.keymap.set(mode, lhs, rhs, { silent = true })
end
-- Save
map("n", "<leader>w", "<CMD>update<CR>")
-- Quit
map("n", "<leader>q", "<CMD>q<CR>")
-- Exit insert mode
map("i", "jk", "<ESC>")
-- NeoTree
map("n", "<leader>e", "<CMD>Neotree toggle<CR>")
map("n", "<leader>r", "<CMD>Neotree focus<CR>")
-- New Windows
map("n", "<leader>o", "<CMD>vsplit<CR>")
map("n", "<leader>p", "<CMD>split<CR>")
-- Window Navigation
map("n", "<C-h>", "<C-w>h")
map("n", "<C-l>", "<C-w>l")
map("n", "<C-k>", "<C-w>k")
map("n", "<C-j>", "<C-w>j")
-- Resize Windows
map("n", "<C-Left>", "<C-w><")
map("n", "<C-Right>", "<C-w>>")
map("n", "<C-Up>", "<C-w>+")
map("n", "<C-Down>", "<C-w>-")
-- Find files
map("n", "<leader>ff", "<cmd>Telescope find_files<cr>")
-- Show files in buffer
map("n", "<leader>fb", "<cmd>Telescope buffers<cr>")
The last step is to create a init.lua file in
~/.config/nvim to ensure that every piece gets connected.Paste the following contents into the init.lua file:
Code:
-- Load editor settings
require("configs.editor-settings")
-- Load keybindings
require("configs.keybindings")
-- Load plugin manager
require("plugins.manager.lazy")
-- Load corresponding LSP choosen by file extension
require("lspconfig").bashls.setup({})
require("lspconfig").clangd.setup({})
require("lspconfig").pyright.setup({})
Extend or shrink the LSP list to your liking.
If you want to install for example bashls or pyright issue the following command as root:
Code:
npm i -g bash-language-server
npm i -g pyright
To uninstall language server protocols issue the following command as root:
Code:
npm uninstall -g language-server-protocol-name
One thing to note, I am aware that there is a debug adapter protocol (dap) and a dap-ui out there for various languages, but I am not using them right now.
If the need should ever arise, I am going to update this how-to.
Hopefully this how-to will help other users get neovim set up faster and easier for their programming needs.
If you have questions, suggestions feel free to post them.
Last edited: