-----------------------
-- Globals & Options --
-----------------------
vim.g.mapleader = " "
-- UI & Visuals
vim.o.number = false
vim.o.signcolumn = "yes"
vim.o.colorcolumn = "80"
vim.o.showtabline = 1
vim.o.wrap = false
vim.o.termguicolors = true
pcall(vim.cmd.colorscheme, "eink")
-- Indentation
vim.o.tabstop = 4
vim.o.shiftwidth = 4
vim.o.softtabstop = 4
vim.o.expandtab = false
vim.o.smartindent = true
-- Search
vim.o.hlsearch = false
vim.o.incsearch = true
-- File handling
vim.o.backup = false
vim.o.swapfile = false
vim.o.undofile = true
vim.o.undodir = os.getenv("HOME") .. "/.vim/undodir"
vim.o.updatetime = 250
-- Diagnostics Config
vim.diagnostic.config({
signs = {
text = {
[vim.diagnostic.severity.ERROR] = "E",
[vim.diagnostic.severity.WARN] = "W",
[vim.diagnostic.severity.INFO] = "I",
[vim.diagnostic.severity.HINT] = "H",
},
},
virtual_text = true,
})
--------------
-- Packages --
--------------
vim.pack.add({
-- Terminal
{ src = "https://github.com/akinsho/toggleterm.nvim" },
-- Telescope
{ src = "https://github.com/nvim-lua/plenary.nvim" },
{ src = "https://github.com/nvim-telescope/telescope.nvim" },
-- LSP & Mason
{ src = "https://github.com/neovim/nvim-lspconfig" },
{ src = "https://github.com/mason-org/mason.nvim" },
{ src = "https://github.com/mason-org/mason-lspconfig.nvim" },
-- Autocomplete
{ src = "https://github.com/hrsh7th/cmp-nvim-lsp" },
{ src = "https://github.com/hrsh7th/cmp-buffer" },
{ src = "https://github.com/hrsh7th/cmp-path" },
{ src = "https://github.com/hrsh7th/cmp-cmdline" },
{ src = "https://github.com/hrsh7th/nvim-cmp" },
})
---------------------------
-- Plugin Configurations --
---------------------------
-- Mason & LSP Config
require("mason").setup()
require("mason-lspconfig").setup()
-- ToggleTerm
local status_ok, toggleterm = pcall(require, "toggleterm")
if status_ok then
toggleterm.setup({
size = 20,
open_mapping = [[<c-\>]],
hide_numbers = true,
direction = "float",
float_opts = { border = "curved" },
})
end
-- CMP (Autocomplete)
local cmp = require("cmp")
cmp.setup({
snippet = {
expand = function(args)
vim.snippet.expand(args.body)
end,
},
window = {
completion = { winhighlight = "Normal:Pmenu,FloatBorder:Pmenu,Search:None" },
documentation = { winhighlight = "Normal:Pmenu,FloatBorder:Pmenu,Search:None" },
},
mapping = cmp.mapping.preset.insert({
['<Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then cmp.select_next_item() else fallback() end
end, { 'i', 's' }),
['<S-Tab>'] = cmp.mapping(function(fallback)
if cmp.visible() then cmp.select_prev_item() else fallback() end
end, { 'i', 's' }),
['<CR>'] = cmp.mapping.confirm({ select = true }),
}),
sources = cmp.config.sources({ { name = "nvim_lsp" }, }, { { name = "buffer" } }, { { name = "path" } })
})
--------------------------------
-- Autocommands & LSP Keymaps --
--------------------------------
-- FileType specific indentation
vim.api.nvim_create_autocmd("FileType", {
pattern = { "javascript", "typescript", "javascriptreact", "typescriptreact" },
callback = function()
vim.opt_local.tabstop = 2
vim.opt_local.softtabstop = 2
vim.opt_local.shiftwidth = 2
end,
})
-- LSP Attach
vim.api.nvim_create_autocmd("LspAttach", {
group = vim.api.nvim_create_augroup("UserLspConfig", {}),
callback = function(ev)
-- Enable completion triggered by <c-x><c-o>
vim.bo[ev.buf].omnifunc = 'v:lua.vim.lsp.omnifunc'
-- Helper function to make mapping easier
local function map(keys, func, desc, mode)
mode = mode or "n"
vim.keymap.set(mode, keys, func, { buffer = ev.buf, desc = desc })
end
map("gd", vim.lsp.buf.definition, "Go to definition")
map("<leader>f", vim.lsp.buf.format, "Format code using LSP")
map("K", function() vim.lsp.buf.hover({ border = "rounded" }) end, "LSP hover")
map("<leader>vd", vim.diagnostic.open_float, "Show diagnostics")
map("<leader>vca", vim.lsp.buf.code_action, "Code actions")
map("<leader>vrr", vim.lsp.buf.references, "Show references")
map("<leader>vrn", vim.lsp.buf.rename, "Rename symbol")
map("<C-h>", vim.lsp.buf.signature_help, "Signature help", "i")
end,
})
-----------------------------
-- General Keymaps & Utils --
-----------------------------
-- Telescope
local builtin = require("telescope.builtin")
vim.keymap.set("n", "<leader>ff", builtin.find_files, {})
vim.keymap.set("n", "<leader>F", function()
builtin.grep_string({ search = vim.fn.input("Grep > ") });
end)
vim.keymap.set('n', '<leader>fr', builtin.lsp_references)
-- Standard operations
vim.keymap.set("n", "<leader>tn", vim.cmd.tabnew, { desc = "Open new tab" })
vim.keymap.set("n", "<leader>pf", vim.cmd.Ex, { desc = "Open file explorer" })
vim.keymap.set("n", "<C-d>", "<C-d>zz", { desc = "Scroll down and center" })
vim.keymap.set("n", "<C-u>", "<C-u>zz", { desc = "Scroll up and center" })
vim.keymap.set("n", "n", "nzzzv", { desc = "Find next search result and center" })
vim.keymap.set("n", "N", "Nzzzv", { desc = "Find previous search result and center" })
vim.keymap.set("x", "<leader>p", [["_dP]], { desc = "Paste without overwriting clipboard" })
vim.keymap.set({ "n", "v" }, "<leader>y", [["+y]], { desc = "Copy to system clipboard" })
vim.keymap.set("n", "Q", "<nop>", { desc = "Disable Q" })
vim.keymap.set("v", "<", "<gv", { desc = "Indent left and stay in visual mode" })
vim.keymap.set("v", ">", ">gv", { desc = "Indent right and stay in visual mode" })
vim.keymap.set("n", "<leader>s", [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]],
{ desc = "Search and replace word under cursor" }
)
-- Utility: Auto-assign global marks
local function set_next_global_mark()
local marks = vim.fn.getmarklist()
local used_marks = {}
for _, mark in pairs(marks) do
if mark.mark:match("^'[A-Z]$") then
used_marks[mark.mark:sub(2)] = true
end
end
for i = 65, 90 do -- ASCII values for 'A' to 'Z'
local mark = string.char(i)
if not used_marks[mark] then
vim.cmd("mark " .. mark)
print("Mark set: " .. mark)
return
end
end
print("No available global marks")
end
vim.keymap.set("n", "<leader>a", set_next_global_mark,
{ desc = "Set next available global mark" }
)
vim.keymap.set("n", "<C-ESC><C-ESC>", ":delmarks ABCDEFGHIJKLMNOPQRSTUVWXYZ<CR>",
{ desc = "Remove all global marks" }
)
vim.keymap.set("n", "<C-E>", ":marks ABCDEFGHIJKLMNOPQRSTUVWXYZ<CR>",
{ desc = "Show all assigned global marks" }
)