Eric Bower
·
2025-07-20
init.lua
1local o = vim.opt
2o.tabstop = 2
3o.shiftwidth = 2
4o.softtabstop = 2
5o.expandtab = true
6o.wrap = false
7o.autoread = true
8o.list = true -- show trailing characters
9o.signcolumn = "yes"
10o.backspace = "indent,eol,start"
11o.shell = "/bin/bash"
12o.colorcolumn = "101"
13o.completeopt = { "menuone", "noselect", "popup" }
14o.laststatus = 0
15o.winborder = "rounded"
16o.undofile = true
17o.ignorecase = true
18o.smartcase = true
19local g = vim.g
20g.mapleader = ","
21g.maplocalleader = ","
22
23local opts = { noremap = true, silent = true }
24local map = vim.keymap.set
25map("n", "<leader>b", "<C-O>", opts) -- prev item in jumplist
26map("n", "Q", "<nop>", opts) -- disable "Q"
27map("n", "<leader>w", ":!make fmt<CR>", opts) -- code format command
28map("t", "<Esc>", [[<C-\><C-n>]], opts) -- exit terminal mode
29map("n", "<C-k>", ":wincmd k<CR>", opts) -- navigate splits
30map("n", "<C-j>", ":wincmd j<CR>", opts)
31map("n", "<C-h>", ":wincmd h<CR>", opts)
32map("n", "<C-l>", ":wincmd l<CR>", opts)
33-- https://github.com/shell-pool/shpool/issues/71#issuecomment-2632396805
34map({ "n", "v", "i", "t" }, "<C-space><C-d>", function()
35 vim.cmd("!shpool detach")
36end)
37
38local autocmd = vim.api.nvim_create_autocmd
39autocmd("Filetype", { pattern = { "qf" }, command = "setlocal wrap" })
40autocmd("Filetype", { pattern = { "make" }, command = "setlocal tabstop=4 shiftwidth=4 softtabstop=4" })
41autocmd("Filetype", {
42 pattern = { "markdown" },
43 command = "setlocal wrap tw=79 formatoptions+=t tabstop=2 shiftwidth=2 softtabstop=2",
44})
45autocmd("FileType", {
46 group = vim.api.nvim_create_augroup("close_with_q", { clear = true }),
47 pattern = { "help", "man", "qf", "scratch", "fugitive", "nvim-pack" },
48 callback = function(args)
49 map("n", "q", "<cmd>quit<cr>", { buffer = args.buf })
50 end,
51})
52
53function setup_lsp()
54 map("n", "<leader>e", vim.diagnostic.open_float, opts)
55 map("n", "<leader>q", vim.diagnostic.setloclist, opts)
56
57 local on_attach = function(client, bufnr)
58 local chars = {}
59 for i = 32, 126 do
60 table.insert(chars, string.char(i))
61 end
62 -- auto-complete for any char
63 client.server_capabilities.completionProvider.triggerCharacters = chars
64 vim.lsp.completion.enable(true, client.id, bufnr, { -- built-in auto-complete
65 autotrigger = true,
66 convert = function(item)
67 return { abbr = item.label:gsub("%b()", "") }
68 end,
69 })
70 local bufopts = { noremap = true, silent = true, buffer = bufnr }
71
72 -- See `:help vim.lsp.*` for documentation on any of the below functions
73 map("n", "<leader>d", vim.lsp.buf.definition, bufopts)
74 map("n", "<leader>D", vim.lsp.buf.type_definition, bufopts)
75 map("n", "<leader>h", vim.lsp.buf.hover, bufopts)
76 map("n", "<leader>r", vim.lsp.buf.references, bufopts)
77 map("n", "<leader>i", vim.lsp.buf.implementation, bufopts)
78 map("i", "<C-k>", vim.lsp.completion.get, bufopts) -- open completion menu manually
79 end
80
81 local nvim_lsp = require("lspconfig")
82 function handler(server_name)
83 local opts = {
84 capabilities = capabilities,
85 on_attach = on_attach,
86 }
87 if server_name == "denols" then
88 opts.root_dir = nvim_lsp.util.root_pattern("deno.json", "deno.jsonc")
89 elseif server_name == "ts_ls" then
90 opts.root_dir = nvim_lsp.util.root_pattern("package.json")
91 -- https://github.com/neovim/nvim-lspconfig/issues/2507#issuecomment-1471438640
92 opts.single_file_support = false
93 end
94 nvim_lsp[server_name].setup(opts)
95 end
96
97 -- npm i -g vscode-langservers-extracted
98 handler("cssls")
99 handler("denols")
100 handler("gopls")
101 handler("html")
102 handler("jsonls")
103 -- npm i -g pyright
104 handler("pyright")
105 -- npm i -g typescript typescript-language-server
106 handler("ts_ls")
107 handler("zls")
108end
109
110function setup_fzf()
111 local fzf = require("fzf-lua")
112 local fzf_files = function()
113 fzf.files({ winopts = { preview = { hidden = "hidden" } } })
114 end
115 local fzf_symbols = function()
116 fzf.lsp_document_symbols({ winopts = { preview = { hidden = "hidden" } } })
117 end
118 map("n", "<leader>s", fzf_files, { desc = "Fzf Files", noremap = true, silent = true })
119 map("n", "<leader>F", fzf_symbols, { desc = "Fzf Symbols", noremap = true, silent = true })
120 map("n", "<leader>f", fzf.buffers, { desc = "Fzf Buffers", noremap = true, silent = true })
121 map("n", "<leader>S", fzf.live_grep, { desc = "Fzf Grep", noremap = true, silent = true })
122 fzf.setup({ "max-perf" })
123end
124
125vim.pack.add({
126 "https://github.com/nvim-lua/plenary.nvim",
127 "https://github.com/Mofiqul/dracula.nvim",
128 { src = "https://github.com/nvim-treesitter/nvim-treesitter", version = "main" },
129 "https://github.com/nvim-treesitter/nvim-treesitter-context",
130 "https://github.com/neovim/nvim-lspconfig",
131 "https://github.com/ibhagwan/fzf-lua",
132 "https://github.com/karb94/neoscroll.nvim",
133 "https://github.com/ruifm/gitlinker.nvim",
134 "https://github.com/tpope/vim-fugitive",
135})
136require("dracula").setup({})
137vim.cmd([[colorscheme dracula]])
138
139local ts_parsers = {
140 "bash",
141 "c",
142 "dockerfile",
143 "fish",
144 "git_config",
145 "git_rebase",
146 "gitattributes",
147 "gitcommit",
148 "gitignore",
149 "go",
150 "gomod",
151 "gosum",
152 "html",
153 "javascript",
154 "json",
155 "lua",
156 "make",
157 "markdown",
158 "python",
159 "rust",
160 "sql",
161 "toml",
162 "tsx",
163 "typescript",
164 "typst",
165 "vim",
166 "yaml",
167 "zig",
168}
169local nts = require("nvim-treesitter")
170nts.install(ts_parsers)
171autocmd("PackChanged", {
172 callback = function(args)
173 local spec = args.data.spec
174 if spec and spec.name == "nvim-treesitter" and args.data.kind == "update" then
175 vim.notify("nvim-treesitter was updated, updating parsers", vim.log.levels.INFO)
176 vim.schedule(function()
177 nts.update()
178 end)
179 end
180 end,
181})
182
183setup_lsp()
184setup_fzf()
185require("treesitter-context").setup({
186 max_lines = 3,
187 multiline_threshold = 1,
188 separator = "-",
189 min_window_height = 20,
190 line_numbers = true,
191})
192require("neoscroll").setup({ duration_multiplier = 0.4 })
193require("gitlinker").setup({})
194
195autocmd("FileType", { -- enable treesitter highlighting and indents
196 callback = function(args)
197 local filetype = args.match
198 local lang = vim.treesitter.language.get_lang(filetype)
199 if vim.treesitter.language.add(lang) then
200 vim.bo.indentexpr = "v:lua.require'nvim-treesitter'.indentexpr()"
201 vim.treesitter.start()
202 end
203 end,
204})