-- Mbess lefuturiste nvim config (2024-01-17) (sorry, not very well organized) -- TODO: add lot of keybindings -- -- Add keybinding to close a tab (all views in a tab neotree + buffer) -- Investigate why it's taking so long to switch tabs in vim -- Individually sort files by updated_at date inside each directory in nvim-neo-tree/neo-tree.nvim (recent files in each dir) -- Debugger feature -- Twig treesitter support -- Change name of variable with LSP -> rn -- PHP helpers? -- Python helpers? -- Tabs features? Or recent tabs? Quickly switch between tabs -- Add shortcut to open symbol definition in new tab local ensure_packer = function() local fn = vim.fn local install_path = fn.stdpath('data')..'/site/pack/packer/start/packer.nvim' if fn.empty(fn.glob(install_path)) > 0 then fn.system({'git', 'clone', '--depth', '1', 'https://github.com/wbthomason/packer.nvim', install_path}) vim.cmd [[packadd packer.nvim]] return true end return false end function str2bool(str_inp) return str_inp ~= nil and (str_inp == "1" or str_inp:lower() == "true" or str_inp:lower() == "yes") end local packer_bootstrap = ensure_packer() -- disable some built-in local disabled_built_ins = { "netrw", "netrwPlugin", "netrwSettings", "netrwFileHandlers", -- "gzip", -- "zip", -- "zipPlugin", -- "tar", -- "tarPlugin", "getscript", "getscriptPlugin", "vimball", "vimballPlugin", "2html_plugin", "logipat", "rrhelper", -- "spellfile_plugin", "matchit" } local user_log = function(message) local log_file_path = '/home/mbess/.logs/neovim.log' local log_file = io.open(log_file_path, "a") io.output(log_file) io.write(message.."\n") io.close(log_file) end for _, plugin in pairs(disabled_built_ins) do vim.g["loaded_" .. plugin] = 1 end local opt = vim.opt vim.cmd("set background=dark") opt.guifont = "Fira Code" opt.background = "dark" opt.number = true opt.relativenumber = true opt.hidden = true -- Hide default menu mode status (I have lualine so this is duplicated) opt.showmode = false -- Tabs options opt.autoindent = true opt.cindent = true opt.wrap = true opt.expandtab = true opt.smartindent = true opt.tabstop = 4 opt.softtabstop = 4 opt.shiftwidth = 4 opt.breakindent = true opt.showbreak = string.rep(" ", 3) -- Make it so that long lines wrap smartly opt.linebreak = true -- opt.wildmenu = true opt.updatetime = 50 opt.termguicolors = true opt.signcolumn = 'yes' opt.belloff = 'all' -- Keep padding opt.scrolloff = 10 -- Always ignore case when searching, unless there is a capital letter in the query opt.ignorecase = true opt.smartcase = true opt.splitright = true opt.splitbelow = true -- Cool floating window popup menu for completion on command line opt.pumblend = 17 opt.wildmode = "longest:full" opt.wildoptions = "pum" -- Ignore compiled files opt.wildignore = "__pycache__" opt.wildignore:append { "*.o", "*~", "*.pyc", "*pycache*" } opt.wildignore:append "Cargo.lock" opt.colorcolumn = "100" -- Highlight on yank (copy). It will do a nice highlight blink of the thing you just copied. -- use [[ ]] to do multi-line strings vim.api.nvim_exec( [[ augroup YankHighlight autocmd! autocmd TextYankPost * silent! lua vim.highlight.on_yank() augroup end ]], false ) vim.g.mapleader = " " -- Plugin list -- Packer require("packer").startup(function() use("wbthomason/packer.nvim") use("lewis6991/impatient.nvim") use("nvim-lua/plenary.nvim") use("nvim-lua/popup.nvim") use { "nvim-telescope/telescope.nvim", config = function() local actions = require('telescope.actions') require('telescope').setup { defaults = { mappings = { i = { [''] = actions.cycle_history_next, [''] = actions.cycle_history_prev } } } } end } use { "nvim-telescope/telescope-live-grep-args.nvim" } use { -- neotree "nvim-neo-tree/neo-tree.nvim", branch = "v2.x", requires = { "nvim-lua/plenary.nvim", "kyazdani42/nvim-web-devicons", -- not strictly required, but recommended "MunifTanjim/nui.nvim", }, config = function () require('neo-tree').setup({ enable_refresh_on_write = true, filesystem = { use_libuv_file_watcher = true, window = { mappings = { ["W"] = function (state) local Node = state.tree:get_node() print(node.name) end } } } }) end } -- TODO: figure how to show an outline for only the first level element, limit the depth -- have a choice of precision between the top levels components only and the deeper components -- the basic choice is to hop between functions or methods in a file use { "simrat39/symbols-outline.nvim", config = function () require("symbols-outline").setup({ autofold_depth = 1 -- not working? }) end -- commons shortcuts by default o, K, Ctrl+Space, r, a, h, l, W, E, R, ? } -- Language Server Protocol stuff use("neovim/nvim-lspconfig") use("hrsh7th/nvim-cmp") use("hrsh7th/cmp-nvim-lsp") use("hrsh7th/cmp-buffer") use("hrsh7th/cmp-path") use("ray-x/cmp-treesitter") use("saadparwaiz1/cmp_luasnip") -- use("WhoIsSethDaniel/toggle-lsp-diagnostics.nvim") use { "L3MON4D3/LuaSnip", tag = "v1.2.1", config = function () on_luasnip_load() end } use("rafamadriz/friendly-snippets") --use("williamboman/mason.nvim") -- Tree sitter stuff use { "nvim-treesitter/nvim-treesitter", -- commit = "26105050aae3a15dd85feaeb0439e253e31d5ceb", -- end of september run = ":TSUpdate" } use("nvim-treesitter/playground") -- add text objects like class, function use { "nvim-treesitter/nvim-treesitter-textobjects" } use { "nvim-treesitter/nvim-treesitter-context", config = function () require("treesitter-context").setup{ enable = true } end } use { "JoosepAlviste/nvim-ts-context-commentstring", config = function () require("nvim-treesitter.configs").setup{ context_commentstring = {enable = true} } end } -- use treesitter to auto add HTML tags -- use { -- 'windwp/nvim-ts-autotag', -- config = function () -- require('nvim-ts-autotag').setup({ -- autotag = { -- enable = false, -- } -- }) -- end -- } -- use treesitter to swap arguments use { 'mizlan/iswap.nvim', -- '~/workspace/iswap.nvim', config = function () require('iswap').setup({ autoswap = true }) end } -- Smart comments use("tpope/vim-commentary") -- Git integration -- use("tpope/vim-fugitive") use { 'TimUntersberger/neogit', commit = "74c9e29b61780345d3ad9d7a4a4437607caead4a", requires = 'nvim-lua/plenary.nvim', config = function () require('neogit').setup{ disable_builtin_notifications = true, disable_commit_confirmation = true } end } use { 'lewis6991/gitsigns.nvim', config = function () require('gitsigns').setup() end, on_attach = function(bufnr) end } -- Format use("sbdchd/neoformat") -- Resume issues found with LSP use { "folke/trouble.nvim", requires = "kyazdani42/nvim-web-devicons", config = function() require("trouble").setup {} end } use { "windwp/nvim-autopairs", config = function() require("nvim-autopairs").setup {} end } -- Enhanced increment and decrement use("monaqa/dial.nvim") -- Toggle helper -- plugin to toggle boolean values use { "rmagatti/alternate-toggler" } -- Lua pad: REPL lua in neovim context -- Useful to mess around with the lua API use { 'rafcamlet/nvim-luapad', requires = "antoinemadec/FixCursorHold.nvim" } -- Spell check helper -- -- use("kamykn/spelunker.vim") -- File navigation helper use { "ThePrimeagen/harpoon", -- config = function() -- require('harpoon').setup({ -- }) -- end } -- -- Colorscheme section use { "catppuccin/nvim", as = "catppuccin", config = function () end } use { 'kyazdani42/nvim-web-devicons', config = function() require'nvim-web-devicons'.setup { -- your personnal icons can go here (to override) -- you can specify color or cterm_color instead of specifying both of them -- DevIcon will be appended to `name` override = { vue = { icon = "", color = "#428850", cterm_color = "65", name = "Vue" } }; -- globally enable default icons (default to false) -- will get overriden by `get_icons` option default = true; } end } -- Preview HTML colors use("lilydjwg/colorizer") -- Add Sticky Buffers use { "stevearc/stickybuf.nvim", config = function() require("stickybuf").setup() end } -- add surround with 's' use { "ur4ltz/surround.nvim", config = function() require"surround".setup {mappings_style = "sandwich"} end } use { "tpope/vim-unimpaired" } use { "tpope/vim-repeat" } -- In-buffer navigation use { "mfussenegger/nvim-treehopper" } use { "phaazon/hop.nvim", branch = 'v2', config = function() require'hop'.setup { keys = 'etovxqpdygfblzhckisuran' } end } use { "indianboy42/hop-extensions", requires = {'phaazon/hop.nvim'} } -- Align things by comma -- use : `:Tabularize /,` -- It would be nicer if someone (me?) could develop a plugin that is based on treesitter and can automagically detect when it's a array, object etc. use("godlygeek/tabular") -- Ascii boxes -- Diagramms use("jbyuki/venn.nvim") use("gyim/vim-boxdraw") -- Old tab plugin -- use { -- 'romgrk/barbar.nvim', -- requires = {'kyazdani42/nvim-web-devicons'} -- } -- Implement the editorconfig specification (format rules for each project) use('editorconfig/editorconfig-vim') -- Non-LSP Language config -- Language specific config -- Use emmet use('mattn/emmet-vim') -- Consider using https://github.com/danymat/neogen to easily create functions annotation (can support php docs) -- use('lervag/vimtex') -- tex support is already here? -- use "folke/lua-dev.nvim" -- Trying to have gohtmltemplate Highlighting use "fatih/vim-go" use { 'mfussenegger/nvim-dap' } use { "rcarriga/nvim-dap-ui", requires = {"mfussenegger/nvim-dap"} } use { 'nvim-lualine/lualine.nvim', requires = { 'kyazdani42/nvim-web-devicons', opt = true }, config = function () require('lualine').setup { options = { icons_enabled = true, theme = 'auto', component_separators = { left = '', right = ''}, section_separators = { left = '', right = ''}, disabled_filetypes = { statusline = {}, winbar = {}, }, ignore_focus = {}, always_divide_middle = true, globalstatus = false, refresh = { statusline = 1000, tabline = 1000, winbar = 1000, } }, sections = { lualine_a = {'mode'}, lualine_b = {'branch', 'diff', 'diagnostics'}, lualine_c = {{'filename', path = 1}}, -- lualine_x = {'filetype'}, lualine_y = {'progress'}, lualine_z = {'location'} }, inactive_sections = { lualine_a = {}, lualine_b = {}, lualine_c = {'filename'}, lualine_x = {'location'}, lualine_y = {}, lualine_z = {} }, tabline = {}, winbar = {}, inactive_winbar = {}, extensions = {} } end } -- Language specific plugins use "aklt/plantuml-syntax" use "tyru/open-browser.vim" use "weirongxu/plantuml-previewer.vim" -- allow to easily create new telescope pickers -- useful to create ppq git recent files use { 'axkirillov/easypick.nvim', requires = 'nvim-telescope/telescope.nvim', config = function () local easypick = require("easypick") local base_branch = "master" easypick.setup({ pickers = { -- list recent updated files tracked by git { name = "recent_files", -- don't use the uniq util with sort, to preserve the original sorting order command = "git -c core.quotepath=off log --name-only --format='' | head -n 100 | awk '!seen[$0]++'", previewer = easypick.previewers.default() } } }) end } use { 'ethanholz/nvim-lastplace', config = function () require'nvim-lastplace'.setup { lastplace_ignore_buftype = {"quickfix", "nofile", "help"}, lastplace_ignore_filetype = {"gitcommit", "gitrebase", "svn", "hgcommit"}, lastplace_open_folds = true } end } -- markdown note plugins use({ "iamcco/markdown-preview.nvim", run = function() vim.fn["mkdp#util#install"]() end, }) -- disable it for now bc it overrode shit in NeoTree -- use({'jakewvincent/mkdnflow.nvim', -- config = function() -- require('mkdnflow').setup({ -- -- Config goes here; leave blank for defaults -- }) -- end -- }) -- new plugins -- append new plugins here if packer_bootstrap then require('packer').sync() end end) -- local map = vim.api.nvim_set_keymap local map = vim.keymap.set -- reload nvim config map("n", "r", "source ~/.config/nvim/init.lua") -- short cut to access system clipboard map("n", "Y", '"+y') map("v", "Y", '"+y') -- handy little things map("n", "", ":q") -- close a single buffer map("n", "", ":tabclose") -- close a whole tab (with Q uppercase) map("n", "", ":w") -- back to last buffer map("n", "bb", "") -- No highlights map("n", "nh", "noh") map("n", "h", "noh") -- Copy current buffer paths to system clipboard map("n", "yp", function() copy_rel_path_with_line() end) map("n", "ypr", function() copy_rel_path() end) map("n", "ypr", function() copy_rel_path_with_line() end) map("n", "ypa", function() copy_abs_path() end) -- Open URL in browser (replace netrw-gx) map("n", "gx", function() print() vim.fn.jobstart( {"xdg-open", vim.fn.expand("")}, { on_stdout = print_stdout, detach = true } ) end) -- Insert date + time map("n", "dt", function() local res = os.date("%Y-%m-%d %H:%M:%S") vim.api.nvim_put({res}, "", true, false) end) -- Insert only day date map("n", "dd", function() local res = os.date("%Y-%m-%d") vim.api.nvim_put({res}, "", true, false) end) -- using netrw -- map("n", "tt", "Explore") -- map("n", "th", "Sexplore") -- map("n", "tv", "Vexplore") -- launch neotree map("n", "tt", function() vim.api.nvim_command('Neotree') end) -- focus file in tree -- locate file, locate path, locate buffer in tree map("n", "tf", function() vim.api.nvim_command('Neotree reveal') end) map("n", "tb", function() vim.api.nvim_command('Neotree buffers') end) -- launch neogit map("n", "ng", function() vim.api.nvim_command('Neogit') end) -- launch neoformat map("n", "nf", function() vim.api.nvim_command('Neoformat') end) -- launch troubles map("n", "tr", function() vim.api.nvim_command('Trouble') end) -- in buffer navigation -- map("v", "", function() require('tsht').nodes() end) -- map("n", "", function() require('tsht').move({ side = "start" }) end) -- Hop nvim keybindings (quick jumps) -- Similar function can be triggered with Ctrl+BackSpace map("n", "H", function() -- hop in all the buffer by word require('hop').hint_words() end) map("n", "hl", function() -- hop to a line require('hop').hint_lines_skip_whitespace() end) map("n", "hv", function() -- keep the position of the cursor column wise require('hop').hint_vertical() end) map("n", "hs", function() require('hop-extensions').hint_textobjects() end) map("n", "", function() require('hop-extensions').hint_textobjects() end) -- Symbols outline -- TODO: add a command variant to only show the top-level elements map("n", "so", function () vim.cmd("SymbolsOutline") end) -- map("n", "sO", function () -- vim.cmd("SymbolsOutlineOpen") -- end) -- Harpoon -- map("n", "h", function() require("harpoon.ui").toggle_quick_menu() end) -- map("n", "a", function() require("harpoon.mark").add_file() end) -- map("n", "", function () require("harpoon.ui").nav_file(1) end) -- map("n", "", function () require("harpoon.ui").nav_file(2) end) -- map("n", "", function () require("harpoon.ui").nav_file(3) end) -- map("n", "", function () require("harpoon.ui").nav_file(4) end) -- reserved for style file -- map("n", "", function () require("harpoon.ui").nav_file(1) end) -- reserved for template file -- reserved for controller file -- map("n", "", function () require("harpoon.ui").nav_file("Controller") end) -- Dial: Improved increment map("n", "", require("dial.map").inc_normal(), {noremap = true}) map("n", "", require("dial.map").dec_normal(), {noremap = true}) map("v", "", require("dial.map").inc_visual(), {noremap = true}) map("v", "", require("dial.map").dec_visual(), {noremap = true}) map("v", "g", require("dial.map").inc_gvisual(), {noremap = true}) map("v", "g", require("dial.map").dec_gvisual(), {noremap = true}) -- let g:at_custom_alternates = {'===': '!==', 'yes':'no'} -- vim.cmd [[ -- let g:at_custom_alternates = {'===': '!==', 'yes': 'no'} -- ]] -- https://github.com/rmagatti/alternate-toggler/issues/6 vim.g.at_custom_alternates = { ['==='] = '!==', ['yes'] = 'no', ['open'] = 'close', ['always'] = 'never', ['allow'] = 'deny', ['before'] = 'after', ['let'] = 'var', ['public'] = 'private', ['begin'] = 'end' } map("n", "ta", ":ToggleAlternate") -- swap with map("n", "ss", function() vim.api.nvim_command('ISwap') end) map("n", "sw", function() vim.api.nvim_command('ISwapWith') end) map("n", "sl", function() vim.api.nvim_command('ISwapNodeWithLeft') end) map("n", "sr", function() vim.api.nvim_command('ISwapNodeWithRight') end) -- Telescope binding map("n", "ff", function () require('telescope.builtin').find_files() end) -- Ctrl+P map("n", "", function () -- It would be great if we could enter regex pattern to match on files require('telescope.builtin').find_files() end) -- TODO: find files with telescope but also search in the ignored files -- map("n", "", function () -- require('telescope.builtin').find_files() -- end) -- live grep keybind map("n", "fg", function () -- previously was: -- require('telescope.builtin').live_grep() -- -- arguments of ripgrep -- use '"search" --type py' to search in python file only -- or use '"search" -g "*.py"' to do glob search on file name -- or use '"search" -g "!*.py"' to exclude file name pattern -- another cool feature will be to do only search on a subdirectory (preferentially the current directory of neotree) require('telescope').extensions.live_grep_args.live_grep_args() end) map("n", "SS", function () require('telescope').extensions.live_grep_args.live_grep_args({search = "hello world"}) end) map("n", "fb", function () require('telescope.builtin').buffers() end) map("n", "fh", function () require('telescope.builtin').help_tags() end) map("n", "fs", function () require('telescope.builtin').lsp_workspace_symbols() end) map("n", "fw", function () -- useful to quickly jump to ANY workspace symbols (also include random variables) require('telescope.builtin').lsp_dynamic_workspace_symbols() end) map("n", "fo", function () -- recent files history require('telescope.builtin').oldfiles({only_cwd = true}) end) map("n", "fW", function () -- useful to quickly jump to major workspace symbols (class, functions, interfaces, etc...) -- require('telescope.builtin').lsp_dynamic_workspace_symbols() end) -- Search for symbols accross project -- map("n", "fs", function () -- require('telescope.builtin').lsp() -- end) -- find recent files map("n", "fr", function () vim.api.nvim_command('Easypick recent_files') end) -- Treesitter config require'nvim-treesitter.configs'.setup { ensure_installed = "all", sync_install = false, highlight = { enable = true, additional_vim_regex_highlighting = false, }, indent = { enable = true }, incremental_selection = { enable = true, keymaps = { init_selection = "", node_incremental = "", scope_incremental = "", node_decremental = "", }, }, textobjects = { select = { enable = true, -- Automatically jump forward to textobj, similar to targets.vim lookahead = true, keymaps = { -- You can use the capture groups defined in textobjects.scm ["af"] = "@function.outer", ["if"] = "@function.inner", ["ac"] = "@class.outer", ["ic"] = "@class.inner", ["aa"] = "@block.outer", ["ii"] = "@block.inner", ["i,"] = '@parameter.inner', ["a,"] = '@parameter.outer', }, -- You can choose the select mode (default is charwise 'v') selection_modes = { ['@parameter.outer'] = 'v', -- charwise ['@function.outer'] = 'V', -- linewise ['@class.outer'] = '', -- blockwise }, -- Useful to include whitespace after a function for example (so the whitespace get deleted or copied and stick with the belonging block) include_surrounding_whitespace = true, }, move = { enable = true, set_jumps = true, -- whether to set jumps in the jumplist goto_next_start = { ["]m"] = "@function.outer", ["]]"] = { query = "@class.outer", desc = "Next class start" }, -- -- You can use regex matching (i.e. lua pattern) and/or pass a list in a "query" key to group multiple queires. ["]o"] = "@loop.*", -- ["]o"] = { query = { "@loop.inner", "@loop.outer" } } -- -- You can pass a query group to use query from `queries//.scm file in your runtime path. -- Below example nvim-treesitter's `locals.scm` and `folds.scm`. They also provide highlights.scm and indent.scm. ["]s"] = { query = "@scope", query_group = "locals", desc = "Next scope" }, ["]z"] = { query = "@fold", query_group = "folds", desc = "Next fold" }, }, goto_next_end = { ["]M"] = "@function.outer", ["]["] = "@class.outer", }, goto_previous_start = { ["[m"] = "@function.outer", ["[["] = "@class.outer", }, goto_previous_end = { ["[M"] = "@function.outer", ["[]"] = "@class.outer", }, -- Below will go to either the start or the end, whichever is closer. -- Use if you want more granular movements -- Make it even more gradual by adding multiple queries and regex. goto_next = { ["]d"] = "@conditional.outer", }, goto_previous = { ["[d"] = "@conditional.outer", } }, }, } vim.opt.foldmethod = "expr" vim.opt.foldexpr = "nvim_treesitter#foldexpr()" vim.opt.foldlevelstart = 8 -- LSP Config local nvim_lsp = require 'lspconfig' -- TODO: fix auto-imports not working with rust -- LSP Servers -- docs: WHERE IS THE FING DOCS? -- https://github.com/neovim/nvim-lspconfig/blob/master/doc/server_configurations.md local servers = {'clangd', 'pyright', 'tsserver', 'gopls', 'volar', 'svelte' } for _, lsp in ipairs(servers) do nvim_lsp[lsp].setup { on_attach = on_attach, } end nvim_lsp['rust_analyzer'].setup{ on_attach = on_attach, init_options = { ["rust-analyzer.checkOnSave.command"] = "clippy" } } nvim_lsp.phpactor.setup{ on_attach = on_attach, init_options = { ["language_server_phpstan.enabled"] = false, ["language_server_psalm.enabled"] = false, } } nvim_lsp.svelte.setup{ init_options = { ["svelte.plugin.typescript.enable"] = false, ["svelte.plugin.typescript.diagnostics.enable"] = false, } } nvim_lsp['hls'].setup{ filetypes = { 'haskell', 'lhaskell', 'cabal' } } local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true nvim_lsp.cssls.setup{ capabilities = capabilities } local runtime_path = vim.split(package.path, ';') table.insert(runtime_path, 'lua/?.lua') table.insert(runtime_path, 'lua/?/init.lua') -- Cmp config local cmp = require'cmp' cmp.setup({ snippet = { -- REQUIRED - you must specify a snippet engine expand = function(args) -- vim.fn["vsnip#anonymous"](args.body) -- For `vsnip` users. require('luasnip').lsp_expand(args.body) -- For `luasnip` users. -- require('snippy').expand_snippet(args.body) -- For `snippy` users. -- vim.fn["UltiSnips#Anon"](args.body) -- For `ultisnips` users. end, }, window = { -- completion = cmp.config.window.bordered(), -- documentation = cmp.config.window.bordered(), }, mapping = cmp.mapping.preset.insert({ [''] = cmp.mapping.scroll_docs(-4), [''] = cmp.mapping.scroll_docs(4), [''] = cmp.mapping.complete(), [''] = cmp.mapping.abort(), [''] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. }), sources = { { name = 'nvim_lsp', keyword_length = 4 }, { name = 'nvim_lua', keyword_length = 4 }, { name = 'path', keyword_length = 4 }, { name = 'treesitter', keyword_length = 4 }, { name = "luasnip", keyword_length = 4 }, { name = "buffer", keyword_length = 5 }, }, experimental = { -- I like the new menu better! Nice work hrsh7th native_menu = false, -- Let's play with this for a day or two ghost_text = false, }, sorting = { -- TODO: Would be cool to add stuff like "See variable names before method names" in rust, or something like that. comparators = { cmp.config.compare.offset, cmp.config.compare.exact, cmp.config.compare.score, -- copied from cmp-under, but I don't think I need the plugin for this. -- I might add some more of my own. function(entry1, entry2) local _, entry1_under = entry1.completion_item.label:find "^_+" local _, entry2_under = entry2.completion_item.label:find "^_+" entry1_under = entry1_under or 0 entry2_under = entry2_under or 0 if entry1_under > entry2_under then return false elseif entry1_under < entry2_under then return true end end, cmp.config.compare.kind, cmp.config.compare.sort_text, cmp.config.compare.length, cmp.config.compare.order, }, }, -- sources = cmp.config.sources({ -- { name = 'nvim_lsp' }, -- -- { name = 'vsnip' }, -- For vsnip users. -- -- { name = 'luasnip' }, -- For luasnip users. -- -- { name = 'ultisnips' }, -- For ultisnips users. -- -- { name = 'snippy' }, -- For snippy users. -- }, { -- { -- name = 'buffer', -- options = { -- keyword_length = 5 -- } -- }, -- }) }) -- Toggle diags DiagnosticsConfig = vim.diagnostic.config() DiagnosticsEnabled = true function toggle_lsp_diag() if not DiagnosticsEnabled then vim.diagnostic.config(DiagnosticsConfig) DiagnosticsEnabled = true else DiagnosticsConfig = vim.diagnostic.config() vim.diagnostic.config({ virtual_text = false, sign = false, float = false, update_in_insert = false, severity_sort = false, underline = false, }) DiagnosticsEnabled = false end end -- Language server keybindings -- LSP keybindings map("n", "gd", function () vim.lsp.buf.definition() end) map("n", "od", function () -- open definition in a new tab -- vim.lsp.buf.definition() print("Open def in new tab") -- vim.api.nvim_exec( -- [[ normal ] ]], -- -- [[normal dd]], -- false -- ) end) map("n", "gD", function () vim.lsp.buf.declaration() end) -- go to implementation map("n", "gi", function () vim.lsp.buf.implementation() end) -- go to usage -- go to callers of a function map("n", "lc", function () vim.lsp.buf.incoming_calls() end) map("n", "gw", function () vim.lsp.buf.document_symbol() end) map("n", "gr", function () vim.lsp.buf.references() end) map("n", "ld", function () vim.lsp.buf.type_definition() end) map("n", "K", function () vim.lsp.buf.hover() end) map("n", "", function () vim.lsp.buf.signature_help() end) map("n", "ac", function () vim.lsp.buf.code_action() end) -- Rename action map("n", "rn", function () vim.lsp.buf.rename() end) -- Show_line_diagnostics map("n", "di", function () vim.diagnostic.open_float() end) -- Format whole buffer with LSP map("n", "F", function () vim.lsp.buf.format { async = true } end) -- Toggle LSP diags -- keywords: disable lsp map("n", "td", function() toggle_lsp_diag() end) -- Tabs keymaps -- -- Move to previous/next -- map('n', '', 'BufferPrevious') -- map('n', '', 'BufferNext') -- -- Re-order to previous/next -- map('n', '', 'BufferMovePrevious') -- map('n', '>', 'BufferMoveNext') -- -- Goto buffer in position... -- map('n', '', 'BufferGoto 1') -- map('n', '', 'BufferGoto 2') -- map('n', '', 'BufferGoto 3') -- map('n', '', 'BufferGoto 4') -- map('n', '', 'BufferGoto 5') -- map('n', '', 'BufferGoto 6') -- map('n', '', 'BufferGoto 7') -- map('n', '', 'BufferGoto 8') -- map('n', '', 'BufferGoto 9') -- map('n', '', 'BufferLast') -- -- Pin/unpin buffer -- map('n', '', 'BufferPin') -- -- Close buffer -- map('n', '', 'BufferClose') -- -- Wipeout buffer -- -- :BufferWipeout -- -- Close commands -- -- :BufferCloseAllButCurrent -- -- :BufferCloseAllButPinned -- -- :BufferCloseAllButCurrentOrPinned -- -- :BufferCloseBuffersLeft -- -- :BufferCloseBuffersRight -- -- Magic buffer-picking mode -- map('n', '', 'BufferPick') -- -- Sort automatically by... -- map('n', 'bb', 'BufferOrderByBufferNumber') -- map('n', 'bd', 'BufferOrderByDirectory') -- map('n', 'bl', 'BufferOrderByLanguage') -- map('n', 'bw', 'BufferOrderByWindowNumber') map("n", "gh", ":lua print('this is a msg')") vim.g.hook_cmp_toggle = true -- LuaSnip config / Snippets -- imap luasnip#expand_or_jumpable() ? 'luasnip-expand-or-jump' : '' -- " -1 for jumping backwards. -- inoremap lua require'luasnip'.jump(-1) -- snoremap lua require('luasnip').jump(1) -- snoremap lua require('luasnip').jump(-1) -- " For changing choices in choiceNodes (not strictly necessary for a basic setup). -- imap luasnip#choice_active() ? 'luasnip-next-choice' : '' -- smap luasnip#choice_active() ? 'luasnip-next-choice' : '' function on_luasnip_load() local ls = require("luasnip") ls.config.set_config({ history = true, updateevents = "TextChanged,TextChangedI", enable_autosnippets = true, }) ls.filetype_extend("svelte", { "html" }) ls.filetype_extend("svelte", { "typescript" }) require("luasnip.loaders.from_vscode").lazy_load() -- This replace the diagraph menu vim.keymap.set({"i", "s"}, "", function () if ls.expand_or_jumpable() then ls.expand_or_jump() end end) vim.keymap.set({"i", "s"}, "", function () if ls.jumpable(-1) then ls.jump(-1) end end) vim.keymap.set("i", "", function () if ls.choice_active() then ls.change_choice() end end) local events = require("luasnip.util.events") local ai = require("luasnip.nodes.absolute_indexer") local fmt = require("luasnip.extras.fmt").fmt local extras = require("luasnip.extras") local m = extras.m local l = extras.l local rep = extras.rep local postfix = require("luasnip.extras.postfix").postfix ls.add_snippets("all", { ls.snippet("somefoobarlel", { -- equivalent to "${1:cond} ? ${2:then} : ${3:else}" ls.insert_node(1, "cond"), ls.text_node(" ? "), ls.insert_node(2, "then"), ls.text_node(" : "), ls.insert_node(3, "else") }), ls.snippet("lorem", { ls.text_node("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.") }) }) ls.add_snippets("rust", { ls.snippet("dbg", { ls.text_node("dbg!("), ls.insert_node(1, "value"), ls.text_node(");") }) }) function mysplit (inputstr, sep) if sep == nil then sep = "%s" end local t={} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do table.insert(t, str) end return t end vim.api.nvim_create_user_command('SnipList', function () -- Will create a read only buffer and show the description of all the snippets local res = vim.inspect(require'luasnip'.available()) if win and vim.api.nvim_win_is_valid(win) then vim.api.nvim_set_current_win(win) else -- We open a new buffer vim.api.nvim_command('botright vnew') win = vim.api.nvim_get_current_win() buf = vim.api.nvim_get_current_buf() vim.api.nvim_buf_set_name(buf, "SnipList") vim.api.nvim_buf_set_option(buf, 'buftype', 'nofile') vim.api.nvim_buf_set_option(buf, 'swapfile', false) vim.api.nvim_buf_set_option(buf, 'bufhidden', 'wipe') vim.api.nvim_buf_set_option(buf, 'modifiable', true) vim.api.nvim_buf_set_option(buf, 'filetype', 'lua') -- Uncomment to disable numbers -- vim.api.nvim_set_option_value('number', false, { scope = "local" }) -- vim.api.nvim_set_option_value('relativenumber', false, { scope = "local" }) -- We set the buffer content vim.api.nvim_buf_set_lines(buf, 0, -1, false, mysplit(res, "\n")) vim.api.nvim_buf_set_option(buf, 'modifiable', false) end end, {}) end require("catppuccin").setup({ flavour = "mocha", -- redondant color_overrides = { all = { } }, custom_highlights = function(colors) return { ["@constant.builtin"] = { fg = colors.peach, style = {} }, -- change the syntax highlighting of comments to make them easier to read and notice -- I once read a blog post about how comments in code should be put in front and not hidden with some gray colorscheme ["@comment"] = { fg = colors.red, style = { "italic", "bold" } }, } end }) vim.cmd.colorscheme "catppuccin" vim.api.nvim_exec( [[ function! DetectGoHtmlTmpl() if expand('%:e') == "html" && search("{{") != 0 set filetype=gohtmltmpl endif endfunction augroup filetypedetect au! BufRead,BufNewFile * call DetectGoHtmlTmpl() augroup END ]], true ) -- vim.g.gruvbox_contrast_dark = "hard" -- little shortcut to insert new line without going into insert mode with Ctrl+Enter map("n", "", function () vim.api.nvim_put({"",""}, "", true, false) end) -- Tabs manipulations map("n", "T0", function() vim.api.nvim_command('tabm 0') end) map("n", "Ti", function() vim.api.nvim_command('tabm +1') end) map("n", "Td", function() vim.api.nvim_command('tabm -1') end) -- Move after last tab vim.api.nvim_create_user_command('MoveTabAtLastTab', function () local tabpages = vim.api.nvim_list_tabpages() vim.api.nvim_command('tabm '..#tabpages) end, {}) map("n", "Te", function() vim.api.nvim_command('MoveTabAtLastTab') end) -- Tabs/Tabspages navigation with alt map("n", "", function () vim.api.nvim_command("tabp") end) map("n", "", function () vim.api.nvim_command("tabn") end) map("n", "", function () vim.api.nvim_command("tabp") end) -- Go to nth tab local function jump_to_nth_tab(tab_position) local tabpages = vim.api.nvim_list_tabpages() if tab_position > #tabpages then return end print(tab_position) vim.api.nvim_set_current_tabpage(tabpages[tab_position]) end local function jump_to_last_tab() local tabpages = vim.api.nvim_list_tabpages() print(#tabpages) end map("n", "", function () jump_to_nth_tab(0) end) map("n", "", function () jump_to_last_tab() end) map("n", "", function () jump_to_nth_tab(10) end) map("n", "", function () jump_to_nth_tab(11) end) map("n", "", function () jump_to_nth_tab(12) end) for i = 1, 9 do map("n", "", function () jump_to_nth_tab(i) end) end -- common utils function to accept user input from bottom status line local function user_input(message) vim.api.nvim_call_function("inputsave", {}) local val = vim.api.nvim_call_function("input", { message }) vim.api.nvim_call_function("inputrestore", {}) return val end -- Now a way to jump to specific tabs via file name match map("n", "", function () -- Ask user the file startup user_res = user_input("TabJump: ") pages = vim.api.nvim_list_tabpages() if #pages == 1 then return end for tab_pos in ipairs(pages) do win = vim.api.nvim_tabpage_get_win(tab_pos) buf = vim.api.nvim_win_get_buf(win) file_path = vim.api.nvim_buf_get_name(buf) res = mysplit(file_path, "/") file_name = res[#res] search_res = string.find(file_name, user_res) if search_res then vim.api.nvim_set_current_tabpage(tab_pos) vim.api.nvim_echo({}, false, {}) return end end vim.api.nvim_notify("TabJump: No match found", 0, {}) end) -- Search helper local function visual_selection_range() local _, csrow, cscol, _ = unpack(vim.fn.getpos("'<")) local _, cerow, cecol, _ = unpack(vim.fn.getpos("'>")) if csrow < cerow or (csrow == cerow and cscol <= cecol) then return csrow - 1, cscol - 1, cerow - 1, cecol else return cerow - 1, cecol - 1, csrow - 1, cscol end end function get_current_selected() local current_mode = vim.api.nvim_get_mode()['mode'] if ( current_mode == "v" or current_mode == "V" ) then local _, select_start_row, select_start_col, _ = unpack(vim.fn.getpos("'<")) local _, select_end_row, select_end_col, _ = unpack(vim.fn.getpos("'>")) -- get the range -- print(select_start_row, select_start_col) -- print(select_end_row, select_end_col) selected_text = vim.api.nvim_buf_get_text(0, select_start_row-1, select_start_col-1, select_end_row-1, select_end_col-1, {}) if #selected_text == 0 then return nil end return selected_text[1] end return nil end function copy_rel_path() -- get full path: expand("%:p") -- get relative path: expand("%") -- vim.fn.setreg("+", vim.fn.expand("%")) path = vim.fn.fnamemodify(vim.fn.expand("%"), ":~:.") vim.fn.setreg("+", path) print("Copied relative to system clipboard") end function copy_rel_path_with_line() path = vim.fn.fnamemodify(vim.fn.expand("%"), ":~:.") .. ':' .. vim.fn.getpos('.')[2] vim.fn.setreg("+", path) end function copy_abs_path() vim.fn.setreg("+", vim.fn.expand("%:p")) print("Copied absolute to system clipboard") end function copy_abs_path_with_line() path = vim.fn.setreg("+", vim.fn.expand("%:p")) .. ':' .. vim.fn.getpos('.')[2] vim.fn.setreg("+", path) end -- Search the term selected function handle_search_selection() print("handle search selection") selected = get_current_selected() if selected == nil then return nil end vim.api.nvim_exec( "normal! /lelhello", false ) end map("n", "S", handle_search_selection) map("v", "S", handle_search_selection) -- Restrict the search to a range -- map("n", "S", function () -- end) -- Handy Git signs shortcuts map("n", "gb", function() vim.api.nvim_command('Gitsigns blame_line') end) map("n", "gs", function() vim.api.nvim_command('Gitsigns stage_hunk') end) map("n", "gu", function() vim.api.nvim_command('Gitsigns undo_stage_hunk') end) map("n", "gd", function() vim.api.nvim_command('Gitsigns toggle_deleted') end) map("n", "gD", function() vim.api.nvim_command('Gitsigns diffthis') end) map("n", "gS", function() vim.api.nvim_command('Gitsigns stage_buffer') end) map("n", "ghr", function() vim.api.nvim_command('Gitsigns reset_hunk') end) map("n", "ghp", function() vim.api.nvim_command('Gitsigns preview_hunk') end) vim.api.nvim_create_user_command('CopyRelPath', function () copy_rel_path() end, {}) vim.api.nvim_create_user_command('CopyAbsPath', copy_abs_path, {}) vim.api.nvim_create_user_command('CopyRelPathWithLine', copy_rel_path_with_line, {}) vim.api.nvim_create_user_command('CopyAbsPathWithLine', copy_abs_path_with_line, {}) vim.api.nvim_create_user_command('ReverseLinesOder', function () -- https://superuser.com/questions/189947/how-do-i-reverse-selected-lines-order-in-vim -- step 1: select lines -- 2: hit : -- 3: type !tac -- 4: profit print("select lines : then !tac") end, {}) -- PATCH: in order to address the message: -- vim.treesitter.query.get_query() is deprecated, use vim.treesitter.query.get() instead. :help deprecated -- This feature will be removed in Nvim version 0.10 local orig_notify = vim.notify local filter_notify = function(text, level, opts) -- more specific to this case if type(text) == "string" and (string.find(text, "get_query", 1, true) or string.find(text, "get_node_text", 1, true)) then -- for all deprecated and stack trace warnings -- if type(text) == "string" and (string.find(text, ":help deprecated", 1, true) or string.find(text, "stack trace", 1, true)) then return end orig_notify(text, level, opts) end vim.notify = filter_notify -- Check for POPEQUER notebook env var -- launch the popequer lua file local popequer_enabled = str2bool(os.getenv("POPEQUER_ENABLED")) if popequer_enabled then require "popequer" end vim.cmd("set wrap")