2 -- “This is the editor of a Real Coder.
3 -- Not as clumsy as a full blown IDE.
4 -- An elegant editor for a more civilized age.”
5 -- ― Bernie Innocenti, https://codewiz.org
8 -- Set this to replace GitHub default URLs
9 -- local github_url = 'https://github.com/'
10 local github_url = 'git@github.com:'
12 -- Bootstrap Packer if not already installed
14 local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim'
15 if fn.empty(fn.glob(install_path)) > 0 then
16 local packer_url = github_url .. "wbthomason/packer.nvim"
17 print("Bootstrapping packer from ", packer_url)
18 packer_bootstrap = fn.system({'git', 'clone', '--depth', '1', packer_url, install_path})
21 require('packer').startup({function(use)
22 use 'wbthomason/packer.nvim'
23 use { 'nvim-treesitter/nvim-treesitter',
24 run = function() require('nvim-treesitter.install').update({ with_sync = true }) end, }
25 use { 'nvim-telescope/telescope.nvim', requires = { {'nvim-lua/plenary.nvim'} } }
26 use { 'nvim-lualine/lualine.nvim', requires = { 'kyazdani42/nvim-web-devicons', opt = true } }
27 use { 'kyazdani42/nvim-tree.lua', requires = { 'kyazdani42/nvim-web-devicons', }, tag = 'nightly' }
28 use 'dstein64/nvim-scrollview'
30 use 'neovim/nvim-lspconfig'
31 use 'hrsh7th/cmp-nvim-lsp'
32 use 'hrsh7th/cmp-buffer'
33 use 'hrsh7th/cmp-path'
34 use 'hrsh7th/cmp-cmdline'
35 use 'hrsh7th/nvim-cmp'
36 use 'hrsh7th/cmp-vsnip'
37 use 'hrsh7th/vim-vsnip'
38 -- use 'hrsh7th/cmp-nvim-lsp-signature-help'
39 use "ray-x/lsp_signature.nvim"
41 if packer_bootstrap then
42 -- FIXME: this runs asynchronously, causing the rest of the
43 -- lua script to fail on first run
44 require('packer').sync()
48 git = { default_url_format = github_url .. '%s.git' }
53 if github_url ~= nil then
54 -- Replace GitHub url for all treesitter plugins
55 for _, config in pairs(require("nvim-treesitter.parsers").get_parser_configs()) do
56 config.install_info.url = config.install_info.url:gsub("https://github.com/", github_url)
60 require("nvim-treesitter.install").prefer_git = true
61 require("nvim-treesitter.configs").setup {
67 local opts = { noremap=true, silent=true }
68 local map = vim.api.nvim_set_keymap
70 require("telescope").setup()
71 map('n', '<C-p>', '<cmd>Telescope git_files<cr>', opts)
72 map('n', 'ff', '<cmd>Telescope find_files<cr>', opts)
73 map('n', 'fg', '<cmd>Telescope live_grep<cr>', opts)
74 map('n', 'fb', '<cmd>Telescope buffers<cr>', opts)
75 map('n', 'fh', '<cmd>Telescope help_tags<cr>', opts)
77 require("nvim-tree").setup()
78 map('n', 'o', ':NvimTreeFocus<CR>', opts)
79 map('n', '<S-o>', ':NvimTreeClose<CR>', opts)
80 map('n', '<C-o>', ':NvimTreeFindFile<CR>', opts)
82 require('lualine').setup {
85 section_separators = { left = '', right = '' },
86 component_separators = { left = '', right = '' },
87 -- section_separators = '', component_separators = '',
88 show_filename_only = false,
93 { 'mode', fmt = function(str) return str:sub(1,1) end }
96 { 'branch', fmt = function(branch) return branch == 'master' and '' or branch end },
99 { 'filename', path = 1, },
102 { 'filetype', icon_only = true, },
138 local has_words_before = function()
139 local line, col = unpack(vim.api.nvim_win_get_cursor(0))
140 return col ~= 0 and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil
143 local feedkey = function(key, mode)
144 vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(key, true, true, true), mode, true)
147 local cmp = require'cmp'
149 -- view = { entries = "native" },
156 format = function(entry, vim_item)
157 vim_item.kind = kind_icons[vim_item.kind]
159 if vim_item.menu ~= nil and string.len(vim_item.menu) > max_width then
160 vim_item.menu = string.sub(vim_item.menu, 1, max_width - 1) .. "…"
166 -- REQUIRED - you must specify a snippet engine
167 expand = function(args)
168 vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users.
171 mapping = cmp.mapping.preset.insert({
172 ['<C-b>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),
173 ['<C-f>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),
174 ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),
175 ['<C-y>'] = cmp.config.disable, -- Specify `cmp.config.disable` if you want to remove the default `<C-y>` mapping.
176 ['<C-e>'] = cmp.mapping({
177 i = cmp.mapping.abort(),
178 c = cmp.mapping.close(),
180 ['<CR>'] = cmp.mapping.confirm({ select = true }),
182 ["<Tab>"] = cmp.mapping(function(fallback)
183 if cmp.visible() then
184 cmp.select_next_item()
185 elseif vim.fn["vsnip#available"](1) == 1 then
186 feedkey("<Plug>(vsnip-expand-or-jump)", "")
187 elseif has_words_before() then
190 fallback() -- Sends a already mapped key. In this case, it's probably `<Tab>`.
194 ["<S-Tab>"] = cmp.mapping(function()
195 if cmp.visible() then
196 cmp.select_prev_item()
197 elseif vim.fn["vsnip#jumpable"](-1) == 1 then
198 feedkey("<Plug>(vsnip-jump-prev)", "")
202 sources = cmp.config.sources({
203 { name = 'nvim_lsp' },
204 -- { name = 'nvim_lsp_signature_help', },
207 -- { name = 'buffer' },
211 -- cmp.setup.cmdline('/', {
212 -- mapping = cmp.mapping.preset.cmdline(),
214 -- keyword_length = 2,
217 -- { name = 'buffer' }
221 cmp.setup.cmdline(':', {
222 mapping = cmp.mapping.preset.cmdline(),
226 sources = cmp.config.sources({
234 local capabilities = vim.lsp.protocol.make_client_capabilities()
235 capabilities = require('cmp_nvim_lsp').update_capabilities(capabilities)
237 -- Disable snippets support for rust-analyzer because it spams the completion
238 capabilities.textDocument.completion.completionItem.snippetSupport = false
239 -- print(vim.inspect(capabilities))
243 -- vim.lsp.set_log_level("debug")
244 vim.diagnostic.config({
246 virtual_text = false,
247 update_in_insert = false,
258 local on_attach = function(client, bufnr)
259 local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
260 local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
262 buf_set_option("formatexpr", "v:lua.vim.lsp.formatexpr()")
263 buf_set_option("omnifunc", "v:lua.vim.lsp.omnifunc")
264 buf_set_option("tagfunc", "v:lua.vim.lsp.tagfunc")
266 vim.opt.completeopt = {"menu", "menuone", "noinsert"}
268 require "lsp_signature".on_attach({
269 hi_parameter = "IncSearch"
272 local opts = { noremap=true, silent=true }
273 -- See `:help vim.lsp.*` for documentation on any of the below functions
274 buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
275 buf_set_keymap('n', '<C-]>', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
276 buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
277 buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
278 buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
279 buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
280 buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
281 buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
282 buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
283 buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
284 buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
285 buf_set_keymap('n', '<space>ca', '<cmd>lua vim.lsp.buf.code_action()<CR>', opts)
286 buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
288 buf_set_keymap('n', '<space>e', '<cmd>lua vim.diagnostic.open_float()<CR>', opts)
289 buf_set_keymap('n', '<space>q', '<cmd>lua vim.diagnostic.setloclist()<CR>', opts)
290 buf_set_keymap('n', '[d', '<cmd>lua vim.diagnostic.goto_prev()<CR>', opts)
291 buf_set_keymap('n', ']d', '<cmd>lua vim.diagnostic.goto_next()<CR>', opts)
293 buf_set_keymap('n', "=", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
294 buf_set_keymap('v', "=", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
295 buf_set_keymap('n', "gq", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
296 buf_set_keymap('v', "gq", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
299 local lspconfig = require'lspconfig';
300 lspconfig.rust_analyzer.setup{
301 on_attach = on_attach,
302 capabilities = capabilities,
304 lspconfig.tsserver.setup{
305 on_attach = on_attach,
306 capabilities = capabilities,
308 lspconfig.clangd.setup{
309 on_attach = on_attach,
310 capabilities = capabilities,
311 -- cmd = { vim.loop.os_homedir() .. "clangd", "--background-index" },
312 cmd = { "clangd", "--background-index" },
313 root_dir = lspconfig.util.root_pattern("compile_commands.json", "compile_flags.txt"),
315 lspconfig.pylsp.setup{
316 on_attach = on_attach,
317 capabilities = capabilities,
320 configurationSources = {"pylint"},
322 autopep8 = { enabled = true },
323 mypy = { enabled = true },
324 pylint = { enabled = true },
325 flake8 = { enabled = false },
326 pycodestyle = { enabled = false },
327 pyflakes = { enabled = false },
333 -- Alt-key window navication and more
334 map('t', '<A-h>', '<C-\\><C-n>h', opts)
335 map('t', '<A-j>', '<C-\\><C-n>j', opts)
336 map('t', '<A-k>', '<C-\\><C-n>k', opts)
337 map('t', '<A-l>', '<C-\\><C-n>l', opts)
338 map('i', '<A-h>', '<C-\\><C-n>h', opts)
339 map('i', '<A-j>', '<C-\\><C-n>j', opts)
340 map('i', '<A-k>', '<C-\\><C-n>k', opts)
341 map('i', '<A-l>', '<C-\\><C-n>l', opts)
342 map('n', '<A-h>', '<C-w>h', opts)
343 map('n', '<A-j>', '<C-w>j', opts)
344 map('n', '<A-k>', '<C-w>k', opts)
345 map('n', '<A-l>', '<C-w>l', opts)