dotfiles/config/nvim/init.lua (view raw)
Oleksandr Smirnov
Oleksandr Smirnov
olexsmir@gmail.com nvim: update ruler, include filename, 1 month ago
olexsmir@gmail.com nvim: update ruler, include filename, 1 month ago
| 1 | vim.loader.enable() |
| 2 | require("vim._core.ui2").enable { enable = true } |
| 3 | |
| 4 | vim.cmd.packadd "nvim.undotree" |
| 5 | vim.cmd.packadd "cfilter" |
| 6 | |
| 7 | vim.g.loaded_perl_provider = 0 |
| 8 | vim.g.loaded_ruby_provider = 0 |
| 9 | vim.g.loaded_node_provider = 0 |
| 10 | vim.g.loaded_python3_provider = 0 |
| 11 | for _, p in ipairs { |
| 12 | "netrw", "netrwPlugin", "netrwSettings", "netrwFileHandlers", "nvim_dir_plugin", |
| 13 | "gzip", "zip", "zipPlugin", "tar", "tarPlugin", |
| 14 | "getscript", "getscriptPlugin", "vimball", "vimballPlugin", "remote_plugins", "rrhelper", |
| 15 | "tohtml", "2html_plugin", |
| 16 | "logipat", "matchit", |
| 17 | } do vim.g["loaded_" .. p] = 1 end |
| 18 | |
| 19 | -- i like my helpers ------------------------------------------------- |
| 20 | Config = {} |
| 21 | Config.map = function(mode, from, to, buffer) |
| 22 | vim.keymap.set(mode, from, to, { silent = true, buffer = buffer or false }) |
| 23 | end |
| 24 | |
| 25 | Config.add = function(opts) |
| 26 | local spec = type(opts) == "string" and { src = opts } or opts |
| 27 | spec.src = "https://github.com/" .. spec.src |
| 28 | spec.version = spec.version or vim.version.range "*" |
| 29 | spec.name = spec.name or nil |
| 30 | vim.pack.add { spec } |
| 31 | end |
| 32 | |
| 33 | local grp = vim.api.nvim_create_augroup("olexsmir", { clear = true }) |
| 34 | Config.autocmd = function(ev, opts) |
| 35 | vim.api.nvim_create_autocmd(ev, vim.tbl_extend("force", { group = grp }, opts)) |
| 36 | end |
| 37 | Config.aucmd = function(ev, pattern, callback, once) |
| 38 | Config.autocmd(ev, { pattern = pattern, callback = callback, once = once }) |
| 39 | end |
| 40 | |
| 41 | Config.later = vim.schedule |
| 42 | Config.onpack = function(pname, kinds, callback) |
| 43 | if type(kinds) == "string" then kinds = { kinds } end |
| 44 | Config.aucmd("PackChanged", "*", function(ev) |
| 45 | if not (ev.data.spec.name == pname and vim.tbl_contains(kinds, ev.data.kind)) then return end |
| 46 | if not ev.data.active then vim.cmd.packadd(pname) end |
| 47 | callback() |
| 48 | end) |
| 49 | end |
| 50 | |
| 51 | -- settings ---------------------------------------------------------- |
| 52 | Config.later(function() vim.o.clipboard = "unnamedplus" end) |
| 53 | Config.later(function() |
| 54 | vim.diagnostic.config { |
| 55 | virtual_text = { virt_text_pos = "eol", current_line = false }, |
| 56 | float = { source = "if_many" }, |
| 57 | signs = { text = { |
| 58 | [vim.diagnostic.severity.ERROR] = "", |
| 59 | [vim.diagnostic.severity.WARN] = "", |
| 60 | [vim.diagnostic.severity.HINT] = "", |
| 61 | [vim.diagnostic.severity.INFO] = "", |
| 62 | } }, |
| 63 | } |
| 64 | end) |
| 65 | |
| 66 | vim.cmd.colorscheme "kolir" |
| 67 | |
| 68 | vim.g.mapleader = " " |
| 69 | vim.g.maplocalleader = "-" |
| 70 | |
| 71 | vim.o.smartindent = true |
| 72 | vim.o.expandtab = true |
| 73 | vim.o.shiftwidth = 4 |
| 74 | vim.o.softtabstop = 4 |
| 75 | vim.o.tabstop = 4 |
| 76 | |
| 77 | vim.o.exrc = true |
| 78 | vim.o.secure = true |
| 79 | vim.o.ignorecase = true |
| 80 | vim.o.smartcase = true |
| 81 | vim.o.cursorline = true |
| 82 | vim.o.number = true |
| 83 | vim.o.termguicolors = true |
| 84 | vim.o.infercase = true |
| 85 | vim.o.completeopt = "menuone,noselect,noinsert,fuzzy,popup" |
| 86 | vim.o.splitbelow = true |
| 87 | vim.o.splitright = true |
| 88 | vim.o.pumheight = 8 |
| 89 | vim.o.scrolloff = 14 |
| 90 | vim.o.sidescrolloff = 16 |
| 91 | vim.o.smoothscroll = true |
| 92 | vim.o.signcolumn = "yes" |
| 93 | vim.o.title = true |
| 94 | vim.o.wrap = false |
| 95 | vim.o.foldenable = false |
| 96 | |
| 97 | vim.o.undofile = true |
| 98 | vim.o.swapfile = false |
| 99 | vim.o.writebackup = false |
| 100 | |
| 101 | vim.o.spell = false |
| 102 | vim.o.spelllang = "en_us,uk" |
| 103 | |
| 104 | vim.o.laststatus = 0 |
| 105 | vim.o.showmode = false |
| 106 | vim.o.ruler = true |
| 107 | vim.o.rulerformat = "%50(%=%{%v:lua.require'ruler'()%}%)" |
| 108 | |
| 109 | vim.o.list = true |
| 110 | vim.opt.listchars:append { |
| 111 | space = "·", |
| 112 | trail = "~", |
| 113 | tab = "│·", |
| 114 | } |
| 115 | |
| 116 | --- keymaps ---------------------------------------------------------- |
| 117 | vim.o.langmap = table.concat({ |
| 118 | "\'ʼ;`~", "№;#", |
| 119 | "йЙ;qQ", "цЦ;wW", "уУ;eE", "кК;rR", "еЕ;tT", "нН;yY", "гГ;uU", "шШ;iI", "щЩ;oO", "зЗ;pP", "хХ;[{", "їЇ;]}", -- "ґҐ;\\|", |
| 120 | "фФ;aA", "ыЫ;sS", "вВ;dD", "аА;fF", "пП;gG", "рР;hH", "оО;jJ", "лЛ;kK", "дД;lL", [[жЖ]], [[єЄ;'"]], |
| 121 | "яЯ;zZ", "чЧ;xX", "сС;cC", "мМ;vV", "иИ;bB", "тТ;nN", "ьЬ;mM", [[бБ;\,<]], "юЮ;.>", |
| 122 | }, ',') |
| 123 | |
| 124 | vim.keymap.del("n", "grn") |
| 125 | vim.keymap.del({ "n", "x" }, "gra") |
| 126 | vim.keymap.del("n", "grr") |
| 127 | vim.keymap.del("n", "grx") |
| 128 | vim.keymap.del("n", "gri") |
| 129 | vim.keymap.del("n", "grt") |
| 130 | |
| 131 | Config.map("i", "<c-r><c-d>", "<c-r>=strftime('%F')<cr>") |
| 132 | |
| 133 | Config.map("t", "<esc><esc>", "<C-\\><C-n>") |
| 134 | Config.map("i", "jk", "<esc>") |
| 135 | Config.map("n", "gd", "<C-]>") -- tags ux |
| 136 | Config.map("n", "<C-d>", "<C-d>zz") |
| 137 | Config.map("n", "<C-u>", "<C-u>zz") |
| 138 | Config.map("n", "<leader>q", "<cmd>quit!<cr>") |
| 139 | Config.map("n", "<leader>w", "<cmd>update<cr>") |
| 140 | Config.map("n", "<leader>h", "<cmd>nohlsearch<cr>") |
| 141 | Config.map("n", "<leader>u", "<cmd>Undotree<cr>") |
| 142 | Config.map("n", "<leader>n", "<cmd>e ~/org/todo.md<cr>") |
| 143 | Config.map({ "n", "x" }, "<leader>z", "1z=") |
| 144 | |
| 145 | Config.map("n", "<C-h>", "<cmd>wincmd h<cr>") |
| 146 | Config.map("n", "<C-j>", "<cmd>wincmd j<cr>") |
| 147 | Config.map("n", "<C-k>", "<cmd>wincmd k<cr>") |
| 148 | Config.map("n", "<C-l>", "<cmd>wincmd l<cr>") |
| 149 | Config.map("n", "<C-Left>", "<cmd>vertical resize -2<cr>") |
| 150 | Config.map("n", "<C-Down>", "<cmd>resize +2<cr>") |
| 151 | Config.map("n", "<C-Up>", "<cmd>resize -1<cr>") |
| 152 | Config.map("n", "<C-Right>", "<cmd>vertical resize +2<cr>") |
| 153 | |
| 154 | Config.map("n", "<A-j>", ":move .+1<CR>==") |
| 155 | Config.map("n", "<A-k>", ":move .-2<CR>==") |
| 156 | Config.map("v", "<A-j>", ":move '>+1<CR>gv-gv") |
| 157 | Config.map("v", "<A-k>", ":move '<-2<CR>gv-gv") |
| 158 | Config.map("v", "<", "<gv") |
| 159 | Config.map("v", ">", ">gv") |
| 160 | |
| 161 | Config.map("n", "<C-q>", function() |
| 162 | for _, win in ipairs(vim.fn.getwininfo()) do |
| 163 | if win.quickfix == 1 and win.loclist == 0 then |
| 164 | vim.cmd.cclose() |
| 165 | return |
| 166 | end |
| 167 | end |
| 168 | vim.cmd.copen() |
| 169 | end) |
| 170 | |
| 171 | Config.map("n", "<C-n>", function() vim.cmd "silent! 1argument" end) |
| 172 | Config.map("n", "<C-m>", function() vim.cmd "silent! 2argument" end) |
| 173 | Config.map("n", "<C-,>", function() vim.cmd "silent! 3argument" end) |
| 174 | Config.map("n", "<C-.>", function() vim.cmd "silent! 4argument" end) |
| 175 | Config.map("n", "<leader>a", function() |
| 176 | vim.cmd("argadd %") |
| 177 | vim.cmd("argdedup") |
| 178 | end) |
| 179 | |
| 180 | --- autocmds --------------------------------------------------------- |
| 181 | Config.aucmd("TextYankPost", nil, function() vim.hl.hl_op { higroup = "Visual" } end) |
| 182 | |
| 183 | Config.aucmd("VimResized", nil, function() |
| 184 | vim.cmd "tabdo wincmd =" |
| 185 | vim.cmd("tabnext " .. vim.fn.tabpagenr()) |
| 186 | end) |
| 187 | |
| 188 | Config.aucmd("BufReadPost", "*", function() vim.fn.setpos(".", vim.fn.getpos "'\"") end) |
| 189 | |
| 190 | Config.aucmd("TermOpen", "term://*", function() |
| 191 | vim.cmd.startinsert() |
| 192 | vim.keymap.set('n', '<leader>q', '<cmd>hide<CR>', { buffer = true }) |
| 193 | end) |
| 194 | Config.aucmd("TermRequest", nil, function(ev) |
| 195 | local pwd, n = string.gsub(ev.data.sequence, "\027]7;file://[^/]*", "") |
| 196 | if n <= 0 then return end |
| 197 | if vim.fn.isdirectory(pwd) == 0 then return end |
| 198 | if vim.api.nvim_get_current_buf() ~= ev.buf then return end |
| 199 | vim.cmd.cd(pwd) |
| 200 | end) |
| 201 | |
| 202 | Config.autocmd("FileType", { pattern = { "help", "man" }, command = "wincmd L" }) |
| 203 | Config.aucmd("FileType", "*", function() |
| 204 | vim.opt_local.formatoptions:append("l") -- long lines not broken in insert mode |
| 205 | vim.opt_local.formatoptions:append("1") -- don't break a line after a one-letter word |
| 206 | |
| 207 | vim.opt_local.formatoptions:remove("c") -- autowrap comments using textwidth with leader |
| 208 | vim.opt_local.formatoptions:remove("r") -- don't auto-insert comment leader on enter in insert |
| 209 | vim.opt_local.formatoptions:remove("o") -- don't auto-insert comment leader on o/O in normal |
| 210 | vim.opt_local.formatoptions:remove("n") -- don't recognizes numbered lists |
| 211 | vim.opt_local.formatoptions:remove("2") -- don't use the indent of second paragraph line |
| 212 | end) |
| 213 | |
| 214 | --- lsp -------------------------------------------------------------- |
| 215 | vim.lsp.enable { "clerk", "gleam", "gopls", "lua_ls", "ts_ls" } |
| 216 | Config.aucmd("LspAttach", nil, function(ev) |
| 217 | local bufnr = ev.buf |
| 218 | local client = vim.lsp.get_client_by_id(ev.data.client_id) |
| 219 | if not client then error "couldn't get an lsp server" end |
| 220 | |
| 221 | if client.name ~= "clerk" then client.server_capabilities.semanticTokensProvider = nil end |
| 222 | if client:supports_method(vim.lsp.protocol.Methods.textDocument_codeLens) then |
| 223 | vim.lsp.codelens.enable(true, { bufnr = bufnr }) |
| 224 | end |
| 225 | |
| 226 | Config.map("n", "gd", Snacks.picker.lsp_definitions, bufnr) |
| 227 | Config.map("n", "gr", Snacks.picker.lsp_references, bufnr) |
| 228 | Config.map("n", "gi", Snacks.picker.lsp_implementations, bufnr) |
| 229 | Config.map("n", "gl", vim.diagnostic.open_float, bufnr) |
| 230 | Config.map({ "n", "x" }, "<leader>la", vim.lsp.buf.code_action, bufnr) |
| 231 | Config.map("n", "<leader>lf", function() vim.lsp.buf.format { async = true } end, bufnr) |
| 232 | Config.map("n", "<leader>ll", vim.lsp.codelens.run, bufnr) |
| 233 | Config.map("n", "<leader>lr", vim.lsp.buf.rename, bufnr) |
| 234 | Config.map("n", "<leader>lS", Snacks.picker.lsp_symbols, bufnr) |
| 235 | Config.map("n", "<leader>ls", Snacks.picker.lsp_workspace_symbols, bufnr) |
| 236 | Config.map("n", "<leader>li", function() |
| 237 | vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled { bufnr = bufnr }, { bufnr = bufnr }) |
| 238 | vim.print "Inlay hints toggled" |
| 239 | end, bufnr) |
| 240 | end) |
| 241 | |
| 242 | --- plugins ---------------------------------------------------------- |
| 243 | Config.add { src = "tpope/vim-surround", version = "master" } |
| 244 | Config.add { src = "tpope/vim-speeddating", version = "master" } |
| 245 | Config.add { src = "tpope/vim-repeat", version = "master" } |
| 246 | Config.add "wakatime/vim-wakatime" |
| 247 | |
| 248 | Config.add "j-hui/fidget.nvim" |
| 249 | Config.later(function() |
| 250 | require("fidget").setup { |
| 251 | progress = { display = { |
| 252 | render_limit = 2, |
| 253 | done_ttl = 2, |
| 254 | } }, |
| 255 | } |
| 256 | end) |
| 257 | |
| 258 | vim.cmd.packadd "viye" |
| 259 | Config.later(function() |
| 260 | -- HACK: wait till https://github.com/neovim/neovim/pull/37727 gets merged |
| 261 | -- ln -s ~/code/gopher.nvim ~/.local/share/nvim/site/pack/my-plugins/opt/gopher.nvim |
| 262 | vim.cmd.packadd "gopher.nvim" |
| 263 | |
| 264 | vim.cmd.packadd "curl.nvim" |
| 265 | |
| 266 | vim.cmd.packadd "utest.nvim" |
| 267 | require("utest").setup {} |
| 268 | Config.map("n", "<leader>tn", require("utest").run) |
| 269 | Config.map("n", "<leader>tt", require("utest").run_file) |
| 270 | Config.map("n", "<leader>tc", require("utest").cancel) |
| 271 | Config.map("n", "<leader>tr", require("utest").clear) |
| 272 | Config.map("n", "<leader>tq", require("utest").qf) |
| 273 | end) |
| 274 | |
| 275 | Config.add { src = "saghen/blink.cmp", version = vim.version.range "1.x" } |
| 276 | Config.later(function() |
| 277 | require("blink.cmp").setup { |
| 278 | keymap = { |
| 279 | preset = "enter", |
| 280 | ["<C-u>"] = { "scroll_documentation_up", "fallback" }, |
| 281 | ["<C-d>"] = { "scroll_documentation_down", "fallback" }, |
| 282 | ["<C-l>"] = { "snippet_forward", "accept", "fallback" }, |
| 283 | }, |
| 284 | completion = { documentation = { |
| 285 | auto_show = true, |
| 286 | auto_show_delay_ms = 300, |
| 287 | } }, |
| 288 | sources = { default = { "lsp", "path", "snippets", "buffer" } }, |
| 289 | } |
| 290 | |
| 291 | vim.lsp.config("*", { |
| 292 | flags = { debounce_text_changes = 150 }, |
| 293 | capabilities = require("blink.cmp").get_lsp_capabilities(), |
| 294 | }) |
| 295 | end) |
| 296 | |
| 297 | -- treesitter |
| 298 | Config.onpack("nvim-treesitter", "update", function() vim.cmd.TSUpdate() end) |
| 299 | Config.add { src = "nvim-treesitter/nvim-treesitter", version = "main" } |
| 300 | Config.add "nvim-treesitter/nvim-treesitter-context" |
| 301 | |
| 302 | Config.later(function() require("treesitter-context").setup { max_lines = 3 } end) |
| 303 | Config.aucmd("FileType", "*", function(ev) |
| 304 | if not ev.match or ev.match == "" or ev.match == "text" then vim.treesitter.stop() end |
| 305 | pcall(vim.treesitter.start, ev.buf) |
| 306 | end) |