Updated Neovim

So I've updated my nvim config to be a little bit leaner. As nvim started to support lua natively, I've decided that it might be a good time to start with a leaner config as native lsp's have been introduced.

Since then, I've opted out of CoC for autocompletion and have started trimming down my use of plugins. I've also started toying with the idea that I might eventually start rewriting all my config in lua as a fun side project to learn another programming language while also diving into the awesomeness of nvim.

Here's my updated config file:

This is only for nvim (not vim). Vim Plug required for this config to work.

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => DEFAULTS
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let mapleader=" "
set smartcase
set incsearch
set ignorecase
set lazyredraw
set magic
set showmatch
set hlsearch

" Clear highlighting on escape in normal mode
nnoremap <esc> :noh<return><esc>
nnoremap <esc>^[ <esc>^[

set mat=2
set history=500
filetype plugin on
filetype indent on
set nobackup
set nowb
set noswapfile
set expandtab
set smarttab
set shiftwidth=2
set tabstop=2
syntax enable
syntax on
set number

au FocusGained,BufEnter * checktime

" (useful for handling the permission-denied error) only for vim not neovim
command! W execute 'w !sudo tee % > /dev/null' <bar> edit!

let $LANG='en'
set ruler
set cmdheight=1
set hid

" Configure backspace so it acts as it should act
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set foldcolumn=1

" Enable 256 colors palette in Gnome Terminal
if $COLORTERM == 'gnome-terminal'
  set t_Co=256
endif

set background=dark

" Set extra options when running in GUI mode
if has("gui_running")
  set guioptions-=T
  set guioptions-=e
  set t_Co=256
  set guitablabel=%M\ %t
endif

" Set utf8 as standard encoding and en_US as the standard language
set encoding=utf8

" Use Unix as the standard file type set ffs=unix,dos,mac

set termguicolors

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => PLUGINS
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
call plug#begin('~/.vim/plugged')
Plug 'kyazdani42/nvim-web-devicons' " for file icons
Plug 'kyazdani42/nvim-tree.lua'

Plug 'neovim/nvim-lspconfig'
Plug 'nvim-treesitter/nvim-treesitter'
Plug 'hrsh7th/nvim-compe'
Plug 'hrsh7th/vim-vsnip'
Plug 'theia-ide/typescript-language-server'

Plug 'airblade/vim-gitgutter'
Plug 'itchyny/lightline.vim'
Plug 'tpope/vim-fugitive'
Plug 'apzelos/blamer.nvim'
Plug 'pseewald/vim-anyfold'
Plug 'Yggdroot/indentLine'
Plug 'tpope/vim-commentary'
Plug 'nvim-lua/popup.nvim'
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-telescope/telescope.nvim'
Plug 'voldikss/vim-floaterm', {'branch': 'master'}

Plug 'kyoz/purify', { 'rtp': 'vim' }
Plug 'ghifarit53/tokyonight-vim'
Plug 'bluz71/vim-nightfly-guicolors'

Plug 'sbdchd/neoformat'

call plug#end()

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => GENERAL TEXT FORMATTING
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Remap VIM 0 to first non-blank character
map 0 ^

" Delete trailing white space on save, useful for some filetypes ;)
fun! CleanExtraSpaces()
let save_cursor = getpos(".")
let old_query = getreg('/')
silent! %s/\s\+$//e
call setpos('.', save_cursor)
call setreg('/', old_query)
endfun

if has("autocmd")
autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces()
endif


""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => COLORSCHEME
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
colorscheme nightfly

" let g:tokyonight_style = 'night' " available: night, storm
let g:tokyonight_enable_italic = 1
" colorscheme tokyonight

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VISUAL MODE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Visual mode pressing * or # searches for the current selection
" Super useful! From an idea by Michael Naumann
vnoremap <silent> * :<C-u>call VisualSelection('', '')<CR>/<C-R>=@/<CR><CR>
vnoremap <silent> # :<C-u>call VisualSelection('', '')<CR>?<C-R>=@/<CR><CR>

function! VisualSelection(direction, extra_filter) range
let l:saved_reg = @"
execute "normal! vgvy"

let l:pattern = escape(@", "\\/.*'$^~[]")
let l:pattern = substitute(l:pattern, "\n$", "", "")

if a:direction == 'gv'
  call CmdLine("Ack '" . l:pattern . "' " )
elseif a:direction == 'replace'
  call CmdLine("%s" . '/'. l:pattern . '/')
endif

let @/ = l:pattern
let @" = l:saved_reg
endfunction

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => WINDOW NAVIGATION
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => SPLITS
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <leader>v :vsplit<cr>'
map <leader>x :split<cr>


""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => BUFFERS
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Close the current buffer
map <leader>bd :Bclose<cr>:tabclose<cr>gT
" Close all the buffers
map <leader>ba :bufdo bd<cr>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => TABS
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" Useful mappings for managing tabs
map <leader>tn :tabnew<cr>

" Go to tab by <leader>{number 1 to 0}
noremap <leader>1 1gt
noremap <leader>2 2gt
noremap <leader>3 3gt
noremap <leader>4 4gt
noremap <leader>5 5gt
noremap <leader>6 6gt
noremap <leader>7 7gt
noremap <leader>8 8gt
noremap <leader>9 9gt
noremap <leader>0 :tablast<cr>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Copy to Clipboard
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
noremap <Leader>y "*y
noremap <Leader>y "+y

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => Floaterm
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <leader>` :FloatermNew--height=0.9 --width=0.9 <cr>
let g:floaterm_autoclose=1
let g:floaterm_rootmarkers=['.project', '.git', '.hg', '.svn', '.root', '.gitignore']
let g:floaterm_gitcommit='floaterm'

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" MOUSE SCROLLING FOR MAC
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set mouse=a
map <ScrollWheelUp> <C-Y>
map <ScrollWheelDown> <C-E>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" TELESCOPE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" " Emulate Control P with telescope
" nnoremap <leader>ff <cmd>Telescope find_files<cr>
nnoremap <silent> <C-p> <cmd>Telescope find_files<cr>

" " Emulate FlyGrep with telescope
" nnoremap <leader>fg <cmd>Telescope live_grep<cr>
nnoremap <leader>/ <cmd>Telescope live_grep<cr>

" " Emulate BufferList with telescope
nnoremap <leader><cr> <cmd>Telescope buffers<cr>
" nnoremap <leader>fh <cmd>Telescope help_tags<cr>

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" INDENTATION (remapping in visual mode as well)
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:indentLine_setColors = 0
let g:indentLine_char_list = ['|', '¦', '┆', '┊']
map <leader>i :IndentLinesToggle<cr>
:noremap > >>
:noremap < <<
:vnoremap < <gv
:vnoremap > >gv

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => GIT GUTTER
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:gitgutter_enabled = 1

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => LIGHT LINE
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
set laststatus=2
if !has('gui_running')
  set t_Co=256
endif

" Replace filename component of Lightline statusline
let g:lightline = {
  \ 'component_function': {
  \   'filename': 'FilenameForLightline'
  \ }
\ }

" Show full path of filename
function! FilenameForLightline()
    return expand('%')
endfunction


" Git Fugitive Bindings
map <leader>g :Git<cr>
map <leader>gd :Gdiffsplit<cr>
map <leader>gl :Git log<cr>
map <leader>gc :Commits<cr>
map <leader>gl :FloatermNew --height=0.9 --width=0.9 lazygit<cr>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" => VIM SURROUND
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
vmap Si S(i_<esc>f)
au FileType mako vmap Si S"i${ _(<esc>2f"a) }<esc>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" Blamer
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:blamer_enabled = 1

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" FOLDING
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd Filetype * AnyFoldActivate
let g:anyfold_fold_comments=1
set foldlevel=0  " close all folds
set foldlevel=99 " Open all folds

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" => FAST EDIT AND RELOAD VIM FILES
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
map <leader>e :e! ~/dot-files/init.vim<cr>
autocmd! bufwritepost ~/dot-files/init.vim source ~/dot-files/init.vim

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" => NVIM Tree
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
let g:nvim_tree_ignore = [ '.git', 'node_modules', '.cache' ] "empty by default
let g:nvim_tree_gitignore = 1 "0 by default
let g:nvim_tree_auto_open = 1 "0 by default, opens the tree when typing `vim $DIR` or `vim`
let g:nvim_tree_auto_close = 1 "0 by default, closes the tree when it's the last window
let g:nvim_tree_quit_on_open = 1 "0 by default, closes the tree when you open a file
let g:nvim_tree_follow = 1 "0 by default, this option allows the cursor to be updated when entering a buffer

nnoremap <leader>nn :NvimTreeToggle<CR>
nnoremap <leader>nf :NvimTreeFindFile<CR>
nnoremap <leader>nr :NvimTreeRefresh<CR>

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" => NVIM TreeSitter
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
lua <<EOF
require'nvim-treesitter.configs'.setup {
  ensure_installed = "maintained", -- one of "all", "maintained" (parsers with maintainers), or a list of languages
  ignore_install = { "javascript" }, -- List of parsers to ignore installing
  highlight = {
    enable = true,              -- false will disable the whole extension
    disable = { "c", "rust" },  -- list of language that will be disabled
  },
}
EOF

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" => AutoCompletion
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

lua << EOF
local nvim_lsp = require('lspconfig')

-- Use an on_attach function to only map the following keys
-- after the language server attaches to the current buffer
local on_attach = function(client, bufnr)
  local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
  local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end

  --Enable completion triggered by <c-x><c-o>
  buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')

  -- Mappings.
  local opts = { noremap=true, silent=true }

  -- See `:help vim.lsp.*` for documentation on any of the below functions
  buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
  buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
  buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
  buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
  buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
  buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
  buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
  buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
  buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
  buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
  buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
  buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
  buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
  buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
  buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
  buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)

end

-- Use a loop to conveniently call 'setup' on multiple servers and
-- map buffer local keybindings when the language server attaches
local servers = { "pyright", "rust_analyzer", "tsserver" }
for _, lsp in ipairs(servers) do
  nvim_lsp[lsp].setup { on_attach = on_attach }
end

require'compe'.setup {
  enabled = true;
  autocomplete = true;
  debug = false;
  min_length = 1;
  preselect = 'enable';
  throttle_time = 80;
  source_timeout = 200;
  incomplete_delay = 400;
  max_abbr_width = 100;
  max_kind_width = 100;
  max_menu_width = 100;
  documentation = true;

  source = {
    path = true;
    nvim_lsp = true;
  };
}

local t = function(str)
  return vim.api.nvim_replace_termcodes(str, true, true, true)
end

local check_back_space = function()
    local col = vim.fn.col('.') - 1
    if col == 0 or vim.fn.getline('.'):sub(col, col):match('%s') then
        return true
    else
        return false
    end
end

-- Use (s-)tab to:
--- move to prev/next item in completion menuone
--- jump to prev/next snippet's placeholder
_G.tab_complete = function()
  if vim.fn.pumvisible() == 1 then
    return t "<C-n>"
  elseif check_back_space() then
    return t "<Tab>"
  else
    return vim.fn['compe#complete']()
  end
end
_G.s_tab_complete = function()
  if vim.fn.pumvisible() == 1 then
    return t "<C-p>"
  else
    return t "<S-Tab>"
  end
end

vim.api.nvim_set_keymap("i", "<Tab>", "v:lua.tab_complete()", {expr = true})
vim.api.nvim_set_keymap("s", "<Tab>", "v:lua.tab_complete()", {expr = true})
vim.api.nvim_set_keymap("i", "<S-Tab>", "v:lua.s_tab_complete()", {expr = true})
vim.api.nvim_set_keymap("s", "<S-Tab>", "v:lua.s_tab_complete()", {expr = true})
EOF

set completeopt=menuone,noselect
let g:compe = {}
let g:compe.enabled = v:true
let g:compe.autocomplete = v:true
let g:compe.debug = v:false
let g:compe.min_length = 1
let g:compe.preselect = 'enable'
let g:compe.throttle_time = 80
let g:compe.source_timeout = 200
let g:compe.resolve_timeout = 800
let g:compe.incomplete_delay = 400
let g:compe.max_abbr_width = 100
let g:compe.max_kind_width = 100
let g:compe.max_menu_width = 100
let g:compe.documentation = v:true

let g:compe.source = {}
let g:compe.source.path = v:true
let g:compe.source.buffer = v:true
let g:compe.source.calc = v:true
let g:compe.source.nvim_lsp = v:true
let g:compe.source.nvim_lua = v:true
let g:compe.source.vsnip = v:true
let g:compe.source.ultisnips = v:true

inoremap <silent><expr> <C-Space> compe#complete()
inoremap <silent><expr> <CR>      compe#confirm('<CR>')
inoremap <silent><expr> <C-e>     compe#close('<C-e>')
inoremap <silent><expr> <C-f>     compe#scroll({ 'delta': +4 })
inoremap <silent><expr> <C-d>     compe#scroll({ 'delta': -4 })

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"" => AutoCompletion
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
autocmd BufWritePre *.js,*.jsx,*.ts,*.tsx Neoformat

Zigmund Sun Oo®