Install Neovim
- Using brew
brew install neovim
- Using curl
curl -LO https://github.com/neovim/neovim/releases/download/nightly/nvim-macos.tar.gz tar xzf nvim-macos.tar.gz ./nvim-osx64/bin/nvim
Configuration
- Create config files
~/.config/neovim/init.lua
~/.config/neovim/lua/options.lua
~/.config/neovim/lua/config.lua
~/.config/neovim/lua/plugins.lua
~/.config/neovim/after/plugin/lspconfig.lua
- init.lua
require('options');
require('config');
require('plugins');
- options.lua
-------------------- HELPERS ------------------------------
local scopes = {o = vim.o, b = vim.bo, w = vim.wo}
local function opt(scope, key, value)
scopes[scope][key] = value
if scope ~= 'o' then scopes['o'][key] = value end
end
-------------------- OPTIONS -------------------------------
local indent = 4
opt('b', 'expandtab', true) -- Use spaces instead of tabs
opt('b', 'shiftwidth', indent) -- Size of an indent
opt('b', 'smartindent', true) -- Insert indents automatically
opt('b', 'tabstop', indent) -- Number of spaces tabs count for
opt('o', 'completeopt', 'menuone,noinsert,noselect') -- Completion options (for deoplete)
opt('o', 'hidden', true) -- Enable modified buffers in background
opt('o', 'ignorecase', true) -- Ignore case
opt('o', 'joinspaces', false) -- No double spaces with join after a dot
opt('o', 'scrolloff', 4 ) -- Lines of context
opt('o', 'shiftround', true) -- Round indent
opt('o', 'sidescrolloff', 8 ) -- Columns of context
opt('o', 'smartcase', true) -- Don't ignore case with capitals
opt('o', 'splitbelow', true) -- Put new windows below current
opt('o', 'splitright', true) -- Put new windows right of current
opt('o', 'termguicolors', true) -- True color support
opt('o', 'wildmode', 'list:longest') -- Command-line completion mode
opt('w', 'list', true) -- Show some invisible characters (tabs...)
opt('w', 'number', true) -- Print line number
opt('w', 'relativenumber', false) -- Relative line numbers
opt('w', 'wrap', false) -- Disable line wrap
opt('o', 'swapfile', false) -- Disable swapfile
opt('o', 'history', 1000)
opt('o', 'autoread', true)
opt('o', 'backup', false)
opt('o', 'writebackup', false)
opt('w', 'cursorline', true)
opt('o', 'pumheight', 10)
opt('o', 'fileencoding', 'utf-8')
opt('o', 'cmdheight', 2)
opt('o', 'mouse', 'a')
opt('o', 'updatetime', 50)
--opt('o', 'timeoutlen', 100)
opt('o', 'clipboard', 'unnamedplus')
opt('o', 'wildmenu', true)
opt('o', 'wildmode', 'full')
opt('o', 'lazyredraw', true)
opt('o', 'signcolumn', 'yes:1')
opt('o', 'background', 'dark')
opt('o', 'synmaxcol', 200) -- syntax file is slow,
opt('o', 'foldlevelstart', 99) -- no fold closed
----------------------- DISABLE BUILT-IN PLUGINS -------------------------
local disabled_built_ins = {
"netrw",
"netrwPlugin",
"netrwSettings",
"netrwFileHandlers",
"gzip",
"zip",
"zipPlugin",
"tar",
"tarPlugin",
"getscript",
"getscriptPlugin",
"vimball",
"vimballPlugin",
"2html_plugin",
"logipat",
"rrhelper",
"spellfile_plugin",
"matchit"
}
for _, plugin in pairs(disabled_built_ins) do
vim.g["loaded_" .. plugin] = 1
end
- config.lua
-------------------- HELPERS ------------------------------
local cmd = vim.cmd -- to execute Vim commands e.g. cmd('pwd')
local g = vim.g -- a table to access global variables
local function map(mode, lhs, rhs, opts)
local options = {noremap = true}
if opts then options = vim.tbl_extend('force', options, opts) end
vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end
-------------------- CONFIG -------------------------------
g['mapleader'] = ' ' -- leader key
g['maplocalleader'] = ' ' -- leader key
g['node_host_prog'] = vim.call('system', 'which neovim-node-host | tr -d "\n"')
-- register
g['peekup_paste_before'] = '<leader>P'
g['peekup_paste_after'] = '<leader>p'
cmd [[au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false, timeout=200}]]
-- Remove trailing space
cmd [[autocmd InsertLeavePre * :%s/\s\+$//e]]
-------------------- MAPPINGS -------------------------------
map('n', '<Leader>sv', ':source $MYVIMRC<CR>')
map('n', '<Space>', '<Nop>', { noremap = true, silent = true })
-- <Tab> to navigate the completion menu
map('i', '<S-Tab>', 'pumvisible() ? "\\<C-p>" : "\\<Tab>"', {expr = true})
map('i', '<Tab>', 'pumvisible() ? "\\<C-n>" : "\\<Tab>"', {expr = true})
map('n', '\\', '<cmd>noh<CR>') -- Clear highlights
map('n', '<Leader>j', ':j<CR>')
map('n', '<Leader>J', ':j!<CR>')
map('n', '<Leader>w', ':w<CR>')
-- keep visual selection after indenting
map('v', '>', '>gv');
map('v', '<', '<gv');
-- copy file path
map('n', '<Leader>cp', ':let @*=expand("%")<CR>')
map('n', '<S-u>', '<C-u>')
map('n', '<S-d>', '<C-d>')
map('n', 'qo', ':only<CR>')
map('', '<C-S-Left>', ':vertical resize -5<CR>')
map('', '<C-S-Right>', ':vertical resize +5<CR>')
map('', '<C-S-Up>', ':resize +5<CR>')
map('', '<C-S-Down>', ':resize -5<CR>')
-- switch window using hjkl
map('n', '<S-h>', '<C-w>h')
map('n', '<S-j>', '<C-w>j')
map('n', '<S-k>', '<C-w>k')
map('n', '<S-l>', '<C-w>l')
-- move selection using jk
map('v', '<S-j>', ':m\'>+<CR>gv=gv')
map('v', '<S-k>', ':m-2<CR>gv=gv')
-- escape visual selection
map('v', ';;', '<Esc>')
-- disable recording macros
map('n', 'q', '<Nop>')
map('n', 'Q', '<Nop>')
map('n', 'qq', ':q<CR>')
map('n', 'QQ', ':q!<CR>')
-- paste on selection
map('x', 'p', [["_dP]])
- plugins.lua
-------------------- PLUGIN MANAGER ------------------------------
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
vim.fn.system({
"git",
"clone",
"--filter=blob:none",
"--single-branch",
"https://github.com/folke/lazy.nvim.git",
lazypath,
})
end
vim.opt.runtimepath:prepend(lazypath)
-------------------- PLUGINS ------------------------------
require('lazy').setup({ -- Packer can manage itself as an optional plugin
-- lsp
'neovim/nvim-lspconfig',
'williamboman/mason.nvim',
'williamboman/mason-lspconfig.nvim',
-- utilities. autocomplete, surround, pair, etc ...
{
'echasnovski/mini.nvim',
config = function()
require('mini.align').setup()
require('mini.comment').setup()
require('mini.completion').setup()
require('mini.fuzzy').setup()
require('mini.jump').setup()
require('mini.jump2d').setup()
require('mini.misc').setup()
require('mini.pairs').setup()
require('mini.statusline').setup()
require('mini.surround').setup()
require('mini.trailspace').setup()
require('mini.ai').setup()
end
},
-- Useful status updates for LSP
{
'j-hui/fidget.nvim',
config = true,
},
{ -- Highlight, edit, and navigate code
'nvim-treesitter/nvim-treesitter',
build = function()
pcall(require('nvim-treesitter.install').update { with_sync = true })
end,
config = function()
require('nvim-treesitter.configs').setup({
sync_install = false,
auto_install = true,
highlight = {
enable = true,
additional_vim_regex_highlighting = false,
},
indent = {
enable = true,
},
autotag = {
enable = true,
}
})
-- folding with treesitter
vim.opt.foldmethod = "expr"
vim.opt.foldexpr = "nvim_treesitter#foldexpr()"
end
},
-- Git related plugins
{
'f-person/git-blame.nvim',
cmd = 'GitBlameToggle',
keys = { { '<Leader>gb', '<cmd>GitBlameToggle<CR>' } },
config = function()
vim.g['gitblame_date_format'] = '%r' -- relative date
vim.g['gitblame_enabled'] = 0 -- default disabled
end
},
-- theme
{
'ellisonleao/gruvbox.nvim',
config = function()
require('gruvbox').setup({
contrast = 'hard',
transparent_mode = true,
})
vim.cmd('colorscheme gruvbox')
end,
},
-- Detect tabstop and shiftwidth automatically
'tpope/vim-sleuth',
-- Fuzzy Finder (files, lsp, etc)
{
'nvim-telescope/telescope.nvim',
branch = '0.1.x',
dependencies = { 'nvim-lua/plenary.nvim' },
keys = {
{ '<Leader>fl', '<cmd>Telescope current_buffer_fuzzy_find theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>ff', '<cmd>Telescope find_files theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fg', '<cmd>Telescope live_grep theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fb', '<cmd>Telescope buffers theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fh', '<cmd>Telescope help_tags theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fv', '<cmd>Telescope git_files theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fp', '<cmd>Telescope planets theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fk', '<cmd>Telescope keymaps theme=get_ivy layout_config={height=0.5}<CR>' },
{ '<Leader>fc', '<cmd>Telescope builtin theme=get_ivy layout_config={height=0.5}<CR>' },
},
config = {
defaults = {
mappings = {
i = {
['<C-u>'] = false,
['<C-d>'] = false,
},
},
},
}
},
-- Fuzzy Finder Algorithm which requires local dependencies to be built. Only load if `make` is available
{
'nvim-telescope/telescope-fzf-native.nvim',
dependencies = { 'nvim-telescope/telescope.nvim' },
build = 'make',
cond = vim.fn.executable 'make' == 1,
config = function()
require('telescope').load_extension('fzf');
end,
},
-- improve default vim ui. e.g. code actions
{
'stevearc/dressing.nvim',
event = 'VeryLazy',
},
-- quick fix list
{'kevinhwang91/nvim-bqf', ft = 'qf'},
-- search and replace
{
'windwp/nvim-spectre',
dependencies = {
'nvim-lua/plenary.nvim'
},
keys = {
{ '<Leader>sr', '<cmd>lua require("spectre").open()<CR>' },
{ '<Leader>sw', '<cmd>lua require("spectre").open_visual({select_word=true})<CR>' },
{ '<Leader>sp', '<cmd>lua require("spectre").open_file_search()<CR>' },
},
config = true,
},
-- marks
{
'ThePrimeagen/harpoon',
dependencies = { 'nvim-lua/plenary.nvim' },
keys = {
{ '<Leader>ha', '<cmd>lua require("harpoon.mark").add_file()<CR>' },
{ '<Leader>ht', '<cmd>lua require("harpoon.ui").toggle_quick_menu()<CR>' },
{ '<Leader>hn', '<cmd>lua require("harpoon.ui").nav_next()<CR>' },
{ '<Leader>hp', '<cmd>lua require("harpoon.ui").nav_prev()<CR>' },
}
},
-- file explorer
{
'nvim-tree/nvim-tree.lua',
cmd = 'NvimTreeFindFileToggle',
keys = { { '<Leader>e', '<cmd>NvimTreeFindFileToggle<CR>' } },
dependencies = {
'nvim-tree/nvim-web-devicons', -- optional, for file icons
},
tag = 'nightly', -- optional, updated every week. (see issue #1193)
config = {
respect_buf_cwd = true,
sort_by = 'case_sensitive',
view = {
adaptive_size = true,
mappings = {
list = {
{ key = 'u', action = 'dir_up' },
},
},
},
renderer = {
group_empty = true,
},
filters = {
dotfiles = true,
},
},
},
-- startup page
{
'mhinz/vim-startify',
lazy = false,
keys = { { '<Leader>S', '<cmd>Startify<CR>' } },
config = function()
vim.g['startify_lists'] = {{type = 'bookmarks', header = {'Bookmarks'}}}
vim.g['startify_bookmarks'] = {
{ i = '~/.config/nvim/init.lua' },
{ p = '~/.config/nvim/lua/plugins.lua' },
{ c = '~/.config/nvim/lua/config.lua' },
{ o = '~/.config/nvim/lua/options.lua' },
{ s = '~/.config/nvim/after/plugin' },
{ z = '~/.zshrc' },
{ g = '~/.gitconfig' },
{ t = '~/.tmux.conf'},
}
end,
},
-- startup time
{
'dstein64/vim-startuptime',
cmd = "StartupTime",
},
-- jk to escape
{
'max397574/better-escape.nvim',
config = true,
},
-- case convert
{
'tpope/vim-abolish',
event = 'VeryLazy',
}
})
- luaconfig.lua
local status_ok, mason, mason_lspconfig, lspconfig
status_ok, mason = pcall(require, 'mason')
if not status_ok then
return
end
status_ok, mason_lspconfig = pcall(require, 'mason-lspconfig')
if not status_ok then
return
end
status_ok, lspconfig = pcall(require, 'lspconfig')
if not status_ok then
return
end
-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(_, bufnr)
-- Enable completion triggered by <c-x><c-o>
vim.api.nvim_buf_set_option(bufnr, 'omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
-- See `:help vim.lsp.*` for documentation on any of the below functions
local bufopts = { noremap=true, silent=true, buffer=bufnr }
vim.keymap.set('n', 'gD', vim.lsp.buf.declaration, bufopts)
vim.keymap.set('n', 'gd', vim.lsp.buf.definition, bufopts)
vim.keymap.set('n', 'K', vim.lsp.buf.hover, bufopts)
vim.keymap.set('n', 'gi', vim.lsp.buf.implementation, bufopts)
vim.keymap.set('n', '<C-k>', vim.lsp.buf.signature_help, bufopts)
vim.keymap.set('n', '<Leader>wa', vim.lsp.buf.add_workspace_folder, bufopts)
vim.keymap.set('n', '<Leader>wr', vim.lsp.buf.remove_workspace_folder, bufopts)
vim.keymap.set('n', '<Leader>wl', function()
print(vim.inspect(vim.lsp.buf.list_workspace_folders()))
end, bufopts)
vim.keymap.set('n', '<Leader>D', vim.lsp.buf.type_definition, bufopts)
vim.keymap.set('n', '<Leader>rn', vim.lsp.buf.rename, bufopts)
vim.keymap.set('n', '<Leader>ca', vim.lsp.buf.code_action, bufopts)
vim.keymap.set('n', 'gr', vim.lsp.buf.references, bufopts)
vim.keymap.set('n', '<Leader>f', function() vim.lsp.buf.format { async = true } end, bufopts)
end
mason.setup()
mason_lspconfig.setup({
ensure_installed = { 'sumneko_lua' },
automatic_installation = true
})
mason_lspconfig.setup_handlers({
function (server_name)
lspconfig[server_name].setup {
on_attach = on_attach
}
end,
['sumneko_lua'] = function ()
lspconfig.sumneko_lua.setup {
settings = {
Lua = {
diagnostics = {
globals = { 'vim' }
}
}
}
}
end,
})
Install / Sync up
- Open neovim
- Sync packages
:Lazy sync
- To install language server just open any file and run
:LspInstall
to install related server
Top comments (2)
Used lazy.nvim for blazing fast load.
awfull