~keving/dotfiles

59af46262252f2d930ee8b9d950bbb7fa58a7fb5 — Kevin Guillaumond 1 year, 8 months ago 911b905
Use init.lua instead of .vimrc when using neovim>=0.5
12 files changed, 528 insertions(+), 12 deletions(-)

D .config/nvim/coc-settings.json
R .vim/ftplugin/c.vim => .config/nvim/ftplugin/c.vim
R .vim/ftplugin/python.vim => .config/nvim/ftplugin/python.vim
R .vim/ftplugin/rst.vim => .config/nvim/ftplugin/rst.vim
A .config/nvim/init.lua
D .config/nvim/init.vim
A .config/nvim/lua/local_init.lua
A .config/nvim/lua/plugin_configs/nvim-compe_config.lua
A .config/nvim/lua/plugin_configs/nvim-lspconfig.lua
A .config/nvim/lua/utils.lua
A .vim/ftplugin
M .vimrc
D .config/nvim/coc-settings.json => .config/nvim/coc-settings.json +0 -4
@@ 1,4 0,0 @@
{
  // Add app.yaml so that CoC creates workspace folders for Google App Engine apps
  "coc.preferences.rootPatterns": [".git", ".hg", ".projections.json", "app.yaml"]
}

R .vim/ftplugin/c.vim => .config/nvim/ftplugin/c.vim +0 -0
R .vim/ftplugin/python.vim => .config/nvim/ftplugin/python.vim +0 -0
R .vim/ftplugin/rst.vim => .config/nvim/ftplugin/rst.vim +0 -0
A .config/nvim/init.lua => .config/nvim/init.lua +438 -0
@@ 0,0 1,438 @@
local cmd = vim.cmd  -- to execute Vim commands e.g. cmd('pwd')
local g = vim.g      -- a table to access global variables

-- Leader namespaces - for related actions
-- b: Buffers
-- e: Edit file (init.lua, etc)
-- g: Go (code completion)
-- h: Hunks (gitgutter)
-- r: Refactor
-- s: Spell checker, Source file (init.lua, etc), Sideways plugin
-- t: Tabs, Tests
g['mapleader'] = ','
g['mapleader'] = ','

local utils = require('utils')

-- Keep list of augroups
local augroup_defs = {}

-- Plugins
-- TODO make paq install itself here
vim.cmd 'packadd paq-nvim'         -- Load Paq
local paq = require'paq-nvim'.paq
paq{'savq/paq-nvim', opt=true}     -- Let Paq manage itself

-- General
paq 'scrooloose/nerdtree'     -- View of the file system
paq 'nvim-lua/popup.nvim'     -- Helper for other plugins
paq 'nvim-lua/plenary.nvim'   -- Helper for other plugins
paq 'nvim-telescope/telescope.nvim'
paq 'morhetz/gruvbox'         -- Color scheme
paq 'vim-airline/vim-airline' -- Status line at the bottom
paq 'mileszs/ack.vim'         -- ack/ag in vim
paq 'embear/vim-localvimrc'   -- Local vimrc files for project-specific settings

-- General programming
paq 'vim-syntastic/syntastic'  -- Syntax checker
paq 'tpope/vim-surround'       -- Act on surrounding things (e.g. quotes)
paq 'tpope/vim-repeat'         -- Repeat certain commands such as surround
paq 'tpope/vim-commentary'     -- Comment/uncomment code
paq 'janko/vim-test'           -- Run tests
paq 'tpope/vim-fugitive'       -- git integration
paq 'airblade/vim-gitgutter'   -- Shows git diff in the 'gutter' (sign column)
paq 'neovim/nvim-lspconfig'    -- Code navigation
paq 'hrsh7th/nvim-compe'       -- Code completion
paq 'knsh14/vim-github-link'   -- Generate shareable file permalinks

-- Python
paq 'numirias/semshi'          -- Syntax highlighting
paq 'nvie/vim-flake8'          -- Python style checker

-- Load plugin-specific configs
require 'plugin_configs/nvim-lspconfig'
require 'plugin_configs/nvim-compe_config'  -- TODO figure out why just 'nvim-compe' doesn't work


-- Plugin configs

-- NERDTree
-- Shortcut to open NERDTree
utils.map('n', '<leader>ne', ':NERDTreeToggle<Enter>')

-- Ignore some files
cmd [[ let NERDTreeIgnore=['\.pyc$', '\~$'] ]]

-- Automatically close NERDTree when you open a file
g['NERDTreeQuitOnOpen'] = 1

-- Automatically close a tab if the only remaining window is NERDTree (TODO)
-- autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif

-- Automatically delete the buffer of the file you just deleted with NerdTree:
g['NERDTreeAutoDeleteBuffer'] = 1

-- Making it prettier
g['NERDTreeMinimalUI'] = 1
g['NERDTreeDirArrows'] = 1


-- Syntastic
g['syntastic_always_populate_loc_list'] = 1
g['syntastic_auto_loc_list'] = 1
g['syntastic_check_on_open'] = 1
g['syntastic_check_on_wq'] = 0

cmd "let g:syntastic_python_checkers = ['flake8']"  -- TODO bring pylint back

-- Show all levels of pylint messages
cmd 'let g:syntastic_quiet_messages = { "level": [] }'
cmd 'let g:syntastic_python_pylint_quiet_messages = { "level" : [] }'

-- Don't lint on buffer write (makes opening python files super slow)
vim.b['syntastic_mode'] = 'passive'

-- TODO probably need something better, but might just disappear if I find a way
-- to run pylint and flake8 asynchronously.
utils.map('n', '<leader>l', ':SyntasticCheck<CR>', {silent = true})


-- Telescope
-- Shortcut for 'go to buffer'
utils.map('n', 'gb', ':Telescope buffers<CR>') 
utils.map('n', '<leader>ff', ':Telescope find_files<CR>')


-- vim-test
-- Run tests in a split window
cmd "let g:test#strategy = 'neovim'"

-- vim-surround
-- Don't select extra space when working around quotes
-- https://github.com/tpope/vim-surround/issues/276
utils.map('n', [[ysa']], [[ys2i']])
utils.map('n', [[ysa"]], [[ys2i"]])
utils.map('n', [[ysa`]], [[ys2i`]])


-- General
-- Sets how many lines of history VIM has to remember
vim.o.history = 500

-- Access the system clipboard
cmd 'set clipboard+=unnamedplus'
-- vim.o.clipboard = vim.o.clipboard + { 'unnamedplus' }

-- Quickly edit/reload init.lua
utils.map('n', '<leader>ei', ':e ~/.config/nvim/init.lua<CR>', {silent = true})
utils.map('n', '<leader>si', ':luafile ~/.config/nvim/init.lua<CR>', {silent = true})
utils.map('n', '<leader>sc', ':luafile %<CR>', {silent = true})


-- User interface
-- Show the number of the current line and the relative number of the others
vim.o.number = true
vim.o.relativenumber = true

-- Show absolute numbers when in insert mode or losing focus
augroup_defs['number_toggle'] = {
    'BufEnter,FocusGained,InsertLeave * set relativenumber',
    'BufLeave,FocusLost,InsertEnter   * set norelativenumber'
}

-- Set 7 lines/columns to the cursor
vim.o.scrolloff = 7
vim.o.sidescrolloff = 7

-- First tab completes the longest common string; next tab completes the first alternative
vim.o.wildmode = 'longest:full,full'

-- Ignore compiled files and version control folders
local wildignore = '*.o,*~,*.pyc'
-- TODO not sure that's working
if vim.fn.has('win16') or vim.fn.has('win32') then
    wildignore = wildignore .. '.git\\*,.hg\\*,.svn\\*'
else
    wildignore = wildignore .. '*/.git/*,*/.hg/*,*/.svn/*,*/.DS_Store'
end
vim.o.wildignore = wildignore

-- Height of the command bar
vim.o.cmdheight = 2

-- A buffer becomes hidden when it is abandoned
vim.o.hidden = true

-- Configure backspace so it acts as it should act
vim.o.backspace = 'eol,start,indent'
cmd 'set whichwrap+=<,>,h,l'

-- Search
vim.o.ignorecase = true -- Ignore case when searching
vim.o.smartcase = true  -- When searching try to be smart about cases 

-- Stop highlighting last search pattern
utils.map('n', '<leader><cr>', ':noh<cr>', {silent = true})

-- Don't redraw while executing macros
vim.o.lazyredraw = true

-- Show matching brackets when text indicator is over them
vim.o.showmatch = true

-- How many tenths of a second to blink when matching brackets
vim.o.matchtime = 2

-- Time in milliseconds to wait for a mapped sequence to complete.
vim.o.timeoutlen = 500

-- Add a bit extra margin to the left
vim.o.foldcolumn = '1'


-- Colors and Fonts
vim.o.cursorline = true
cmd 'colorscheme gruvbox'
vim.o.termguicolors = true

-- Use Unix as the standard file type
vim.o.fileformats = 'unix,dos,mac'


-- Text, tab and indent
-- Use spaces instead of tabs
vim.o.expandtab = true

-- 1 tab == 2 spaces
local indent = 2 
vim.o.shiftwidth = indent
vim.o.tabstop = indent -- Number of visual spaces per TAB
vim.o.softtabstop = indent -- Number of spaces per TAB when editing
vim.o.shiftround = true -- Indenting rounds to a multiple of 2 (instead of just changing by 2)

-- Limit lines to 80 characters and still wrap longer lines
vim.o.linebreak = true
vim.o.textwidth = 80
vim.o.colorcolumn = '80'

vim.o.smartindent = true


-- Visual mode
-- Visual mode pressing * or # searches for the current selection
utils.map('v', '*', ':<C-u>call VisualSelection("", "")<CR>/<C-R>=@/<CR><CR>', {silent = true})
utils.map('v', '#', ':<C-u>call VisualSelection("", "")<CR>?<C-R>=@/<CR><CR>', {silent = true})


-- Terminal mode
-- Better command to switch from insert to normal mode
utils.map('t', '<C-o>', [[<C-\><C-n>]])


-- Moving around, tabs, windows and buffers
-- Map j to gj so vim behaves as expected with wrapped lines
-- But keep normal behaviour if doing something like 4j
cmd "nnoremap <expr> j v:count ? 'j' : 'gj'"
cmd "nnoremap <expr> k v:count ? 'k' : 'gk'"

-- Specify where splits should occur
vim.o.splitbelow = true
vim.o.splitright = true

 -- Smart way to move between windows
utils.map('n', '<C-j>', '<C-W>j')
utils.map('n', '<C-k>', '<C-W>k')
utils.map('n', '<C-h>', '<C-W>h')
utils.map('n', '<C-l>', '<C-W>l')

-- Close the current buffer
utils.map('n', '<leader>bd', ':Bclose<cr>')

-- Useful mappings for managing tabs
utils.map('n', '<leader>tn', ':tabnew<cr>')
utils.map('n', '<leader>to', ':tabonly<cr>')
utils.map('n', '<leader>tc', ':tabclose<cr>')
utils.map('n', '<leader>tm', ':tabmove ')
utils.map('n', '<leader>t<leader>', ':tabnext ')

-- Opens a new tab with the current buffer's path
utils.map('n', '<leader>te', ':tabedit <c-r>=expand("%:p:h")<cr>/')

-- Switch CWD to the directory of the open buffer
utils.map('n', '<leader>cd', ':cd %:p:h<cr>:pwd<cr>')

-- Specify the behavior when switching between buffers 
vim.o.switchbuf = 'useopen,usetab,newtab'
vim.o.showtabline = 1

-- Return to last edit position when opening files
-- TODO
-- au BufReadPost * if line("'\"") > 1 && line("'\"") <= line("$") | exe "normal! g'\"" | endif


-- Editing mappings
-- Map Y to act like D and C, i.e. to yank until EOL, rather than act as yy,
-- which is the default
utils.map('n', 'Y', 'y$')

-- Don't write to yank buffer when deleting a single character
utils.map('n', 'x', '"_x')
utils.map('n', 'X', '"_X')

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

-- autocmd BufWritePre *.txt,*.js,*.py,*.wiki,*.sh,*.coffee :call CleanExtraSpaces()


-- Code
-- Enable code folding
vim.o.foldmethod = 'indent'
vim.o.foldlevel = 99

-- Enable folding with the spacebar
utils.map('n', '<space>', 'za')

-- Show list of tags if there are multiples matches
-- https://stackoverflow.com/a/42078499/
utils.map('n', '<C-]>', 'g<C-]>')

-- Ruby autocomplete
-- TODO
-- autocmd FileType ruby,eruby let g:rubycomplete_buffer_loading = 1 
-- autocmd FileType ruby,eruby let g:rubycomplete_classes_in_global = 1
-- autocmd FileType ruby,eruby let g:rubycomplete_rails = 1

-- Run tests
-- Using ,tj because ,tn is used by tabs
utils.map('n', '<leader>tj', ':TestNearest<CR>')
utils.map('n', '<leader>tf', ':TestFile<CR>')
utils.map('n', '<leader>ts', ':TestSuite<CR>')
utils.map('n', '<leader>tl', ':TestLast<CR>')
utils.map('n', '<leader>tg', ':TestVisit<CR>')


-- Spell checking
-- Toggle and untoggle spell checking
utils.map('n', '<leader>ss', ':setlocal spell!<cr>')

-- Next misspelled word
utils.map('n', '<leader>sn', ']s')
-- Previous misspelled word
utils.map('n', '<leader>sp', '[s')
-- Add to dictionary
utils.map('n', '<leader>sa', 'zg')
-- Suggest corrections
utils.map('n', '<leader>s?', 'z=')
-- Replace with first correction
utils.map('n', '<leader>s1', 'z=1<CR><CR>')

utils.map('n', '<leader>se', ':setlocal spelllang=en_en<CR>')
utils.map('n', '<leader>sf', ':setlocal spelllang=fr<CR>')


-- Misc
-- Remove the Windows ^M - when the encodings gets messed up
utils.map('n', '<leader>m', "mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm")

-- Quickly open a scratchpad for scribble
utils.map('n', '<leader>q', ':e ~/scratchpad<cr>')

-- Toggle paste mode on and off
utils.map('n', '<leader>pp', ':setlocal paste!<cr>')


-- Helper functions
-- Don't close window, when deleting a buffer
-- TODO find out how to write in lua (can't use <SID> inside nvim_exec)
-- command! Bclose call <SID>BufcloseCloseIt()
-- function! <SID>BufcloseCloseIt()
--    let l:currentBufNum = bufnr("%")
--    let l:alternateBufNum = bufnr("#")

--    if buflisted(l:alternateBufNum)
--      buffer #
--    else
--      bnext
--    endif

--    if bufnr("%") == l:currentBufNum
--      new
--    endif

--    if buflisted(l:currentBufNum)
--      execute("bdelete! ".l:currentBufNum)
--    endif
-- endfunction

vim.api.nvim_exec([[
function! CmdLine(str)
    exe "menu Foo.Bar :" . a:str
    emenu Foo.Bar
    unmenu Foo
endfunction 

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
]], false)


-- Local configuration
-- TODO make it optional to have that file
require 'local_init'
-- assert(io.open('lua/local_init.lua', 'r'))




_G.tab_complete = function()
  if vim.fn.pumvisible() == 1 then
    return utils.t "<C-n>"
  elseif utils.check_back_space() then
    return utils.t "<Tab>"
  else
    return vim.fn['compe#complete']()
  end
end

_G.s_tab_complete = function()
  if vim.fn.pumvisible() == 1 then
    return utils.t "<C-p>"
  else
    return utils.t "<S-Tab>"
  end
end

utils.map("i", "<Tab>", "v:lua.tab_complete()", {expr = true})
utils.map("s", "<Tab>", "v:lua.tab_complete()", {expr = true})
utils.map("i", "<S-Tab>", "v:lua.s_tab_complete()", {expr = true})
utils.map("s", "<S-Tab>", "v:lua.s_tab_complete()", {expr = true})

-- Create augroups
utils.nvim_create_augroups(augroup_defs)


-- TODO
-- Rewrite usages of cmd and nvim_exec in Lua
-- Tidy code with plugin-specific config to its own files, like https://github.com/ibhagwan/nvim-lua

D .config/nvim/init.vim => .config/nvim/init.vim +0 -3
@@ 1,3 0,0 @@
set runtimepath^=~/.vim runtimepath+=~/.vim/after
let &packpath=&runtimepath
source ~/.vimrc

A .config/nvim/lua/local_init.lua => .config/nvim/lua/local_init.lua +6 -0
@@ 0,0 1,6 @@
local cmd = vim.cmd
local g = vim.g

-- g['localvimrc_whitelist'] = ['/Users/kevinguillaumond/src/lvimrc']
cmd "let g:localvimrc_whitelist=['/Users/kevinguillaumond/src/lvimrc']"
g['localvimrc_sandbox'] = 0

A .config/nvim/lua/plugin_configs/nvim-compe_config.lua => .config/nvim/lua/plugin_configs/nvim-compe_config.lua +17 -0
@@ 0,0 1,17 @@
local cmd = vim.cmd  -- to execute Vim commands e.g. cmd('pwd')

-- Insert mode completion (required)
vim.o.completeopt = 'menuone,noselect'

require'compe'.setup({
  enabled = true,
  source = {
    path = true,
    buffer = true,
    nvim_lsp = true,
  },
})

-- vim-compe mappings
cmd 'inoremap <silent><expr> <CR>  compe#confirm("<CR>")'
cmd 'inoremap <silent><expr> <C-e> compe#close("<C-e>")'

A .config/nvim/lua/plugin_configs/nvim-lspconfig.lua => .config/nvim/lua/plugin_configs/nvim-lspconfig.lua +26 -0
@@ 0,0 1,26 @@
local cmd = vim.cmd

local utils = require('utils')

-- Set up pyright
require'lspconfig'.pyright.setup{}

utils.map('n', '<leader>rr', '<cmd>lua vim.lsp.buf.rename()<CR>', {silent = true})
utils.map('n', 'gd', '<cmd>lua vim.lsp.buf.definition()<CR>', {silent = true})
utils.map('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', {silent = true})
utils.map('n', 'K', '<cmd>lua vim.lsp.buf.hover()<CR>', {silent = true}) -- TODO still try vim docs first


-- TODO Map K to this so it shows vim documentation first
vim.api.nvim_exec([[
function! s:show_documentation()
  if (index(['vim','help'], &filetype) >= 0)
    execute 'h '.expand('<cword>')
  else
    call <cmd>lua vim.lsp.buf.hover()<CR>
  endif
endfunction
]], false)

-- Disable LSP diagnostics for now
vim.lsp.handlers['textDocument/publishDiagnostics'] = function() end

A .config/nvim/lua/utils.lua => .config/nvim/lua/utils.lua +38 -0
@@ 0,0 1,38 @@
local utils = {}


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

function utils.check_back_space()
    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

local scopes = { o = vim.o, b = vim.bo, w = vim.wo }

function utils.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

function utils.nvim_create_augroups(definitions)
  for group_name, definition in pairs(definitions) do
    vim.api.nvim_command('augroup '..group_name)
    vim.api.nvim_command('autocmd!')
    for _, def in ipairs(definition) do
      local command = table.concat(vim.tbl_flatten{'autocmd', def}, ' ')
      vim.api.nvim_command(command)
    end
    vim.api.nvim_command('augroup END')
  end
end


return utils

A .vim/ftplugin => .vim/ftplugin +1 -0
@@ 0,0 1,1 @@
../.config/nvim/ftplugin/
\ No newline at end of file

M .vimrc => .vimrc +2 -5
@@ 59,6 59,7 @@ Plug 'airblade/vim-gitgutter'  " Shows git diff in the 'gutter' (sign column)
Plug 'neoclide/coc.nvim', {'branch': 'release'}  " Intellisense engine 
Plug 'ludovicchabant/vim-gutentags'  " Keep tags files up to date
Plug 'AndrewRadev/sideways.vim' " Move function arguments left and right
Plug 'knsh14/vim-github-link'  " Generate shareable file permalinks

" Python
" Better syntax highlighting


@@ 75,7 76,7 @@ Plug 'tpope/vim-rails'

" Some plugins to consider
" Plugin 'easymotion/vim-easymotion'    " Vim motion on speed!
" Plugin 'slj/gundo.vim'           " Display undo tree in graphical form
" Plugin 'mbbill/undotree'           " Display undo tree in graphical form
" Plugin 'garbas/vim-snipmate'     " Code snippets
" Plugin 'jiangmiao/auto-pairs'    " Insert/delete parens/quotes in pairs
" Plugin 'skywind3000/asyncrun.vim'     " Kick off builds/tests asynchronously


@@ 142,10 143,6 @@ let g:gutentags_ctags_exclude = ['.tox', '*.json']
"  }}}

" NERDTree {{{
" Open NERDTree by default
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif

" Shortcut to open NERDTree
nnoremap <leader>ne :NERDTreeToggle<Enter>