From 5eda7770be54f222e27e87190a95847e6d0e2c8c Mon Sep 17 00:00:00 2001 From: Michal Hanus Date: Mon, 29 Dec 2025 19:02:55 +0100 Subject: nvim setup --- .config/nvim/lua/colorschemes.lua | 83 +++++ .config/nvim/lua/config/indent-blankline.lua | 36 ++ .config/nvim/lua/config/nvim-tree.lua | 108 ++++++ .config/nvim/lua/config/statusline.lua | 197 +++++++++++ .config/nvim/lua/custom-autocmd.lua | 105 ++++++ .config/nvim/lua/mappings.lua | 231 ++++++++++++ .config/nvim/lua/plugin_specs.lua | 503 +++++++++++++++++++++++++++ 7 files changed, 1263 insertions(+) create mode 100644 .config/nvim/lua/colorschemes.lua create mode 100644 .config/nvim/lua/config/indent-blankline.lua create mode 100644 .config/nvim/lua/config/nvim-tree.lua create mode 100644 .config/nvim/lua/config/statusline.lua create mode 100644 .config/nvim/lua/custom-autocmd.lua create mode 100644 .config/nvim/lua/mappings.lua create mode 100644 .config/nvim/lua/plugin_specs.lua (limited to '.config/nvim/lua') diff --git a/.config/nvim/lua/colorschemes.lua b/.config/nvim/lua/colorschemes.lua new file mode 100644 index 0000000..9618b4d --- /dev/null +++ b/.config/nvim/lua/colorschemes.lua @@ -0,0 +1,83 @@ +--- This module will load a random colorscheme on nvim startup process. + +local utils = require("utils") + +local M = {} + +-- Colorscheme to its directory name mapping, because colorscheme repo name is not necessarily +-- the same as the colorscheme name itself. +M.colorscheme_conf = { + onedark = function() + vim.cmd([[colorscheme onedark]]) + end, + edge = function() + vim.g.edge_enable_italic = 1 + vim.g.edge_better_performance = 1 + + vim.cmd([[colorscheme edge]]) + end, + sonokai = function() + vim.g.sonokai_enable_italic = 1 + vim.g.sonokai_better_performance = 1 + + vim.cmd([[colorscheme sonokai]]) + end, + gruvbox_material = function() + -- foreground option can be material, mix, or original + vim.g.gruvbox_material_foreground = "material" + --background option can be hard, medium, soft + vim.g.gruvbox_material_background = "soft" + vim.g.gruvbox_material_enable_italic = 1 + vim.g.gruvbox_material_better_performance = 1 + + vim.cmd([[colorscheme gruvbox-material]]) + end, + everforest = function() + vim.g.everforest_enable_italic = 1 + vim.g.everforest_better_performance = 1 + + vim.cmd([[colorscheme everforest]]) + end, + nightfox = function() + vim.cmd([[colorscheme nordfox]]) + end, + catppuccin = function() + -- available option: latte, frappe, macchiato, mocha + vim.g.catppuccin_flavour = "frappe" + require("catppuccin").setup() + + vim.cmd([[colorscheme catppuccin]]) + end, + onedarkpro = function() + -- set colorscheme after options + vim.cmd('colorscheme onedark_vivid') + end, + material = function() + vim.g.material_style = "oceanic" + vim.cmd('colorscheme material') + end, +} + +--- Use a random colorscheme from the pre-defined list of colorschemes. +M.rand_colorscheme = function() + local colorscheme = utils.rand_element(vim.tbl_keys(M.colorscheme_conf)) + + if not vim.tbl_contains(vim.tbl_keys(M.colorscheme_conf), colorscheme) then + local msg = "Invalid colorscheme: " .. colorscheme + vim.notify(msg, vim.log.levels.ERROR, { title = "nvim-config" }) + + return + end + + -- Load the colorscheme and its settings + M.colorscheme_conf[colorscheme]() + + if vim.g.logging_level == "debug" then + local msg = "Colorscheme: " .. colorscheme + + vim.notify(msg, vim.log.levels.DEBUG, { title = "nvim-config" }) + end +end + +-- Load a random colorscheme +M.rand_colorscheme() diff --git a/.config/nvim/lua/config/indent-blankline.lua b/.config/nvim/lua/config/indent-blankline.lua new file mode 100644 index 0000000..9b210d7 --- /dev/null +++ b/.config/nvim/lua/config/indent-blankline.lua @@ -0,0 +1,36 @@ +local api = vim.api + +local exclude_ft = { "help", "git", "markdown", "snippets", "text", "gitconfig", "alpha", "dashboard" } + +require("ibl").setup { + indent = { + -- -- U+2502 may also be a good choice, it will be on the middle of cursor. + -- -- U+250A is also a good choice + char = "▏", + }, + scope = { + show_start = false, + show_end = false, + }, + exclude = { + filetypes = exclude_ft, + buftypes = { "terminal" }, + }, +} + +local gid = api.nvim_create_augroup("indent_blankline", { clear = true }) +api.nvim_create_autocmd("InsertEnter", { + pattern = "*", + group = gid, + command = "IBLDisable", +}) + +api.nvim_create_autocmd("InsertLeave", { + pattern = "*", + group = gid, + callback = function() + if not vim.tbl_contains(exclude_ft, vim.bo.filetype) then + vim.cmd([[IBLEnable]]) + end + end, +}) diff --git a/.config/nvim/lua/config/nvim-tree.lua b/.config/nvim/lua/config/nvim-tree.lua new file mode 100644 index 0000000..6bf653d --- /dev/null +++ b/.config/nvim/lua/config/nvim-tree.lua @@ -0,0 +1,108 @@ +local keymap = vim.keymap +local nvim_tree = require("nvim-tree") + +nvim_tree.setup { + auto_reload_on_write = true, + disable_netrw = false, + hijack_netrw = true, + hijack_cursor = false, + hijack_unnamed_buffer_when_opening = false, + open_on_tab = false, + sort_by = "name", + update_cwd = false, + view = { + width = 30, + side = "left", + preserve_window_proportions = false, + number = false, + relativenumber = false, + signcolumn = "yes", + }, + renderer = { + indent_markers = { + enable = false, + icons = { + corner = "└ ", + edge = "│ ", + none = " ", + }, + }, + icons = { + webdev_colors = true, + }, + }, + hijack_directories = { + enable = true, + auto_open = true, + }, + update_focused_file = { + enable = false, + update_cwd = false, + ignore_list = {}, + }, + system_open = { + cmd = "", + args = {}, + }, + diagnostics = { + enable = false, + show_on_dirs = false, + icons = { + hint = "", + info = "", + warning = "", + error = "", + }, + }, + filters = { + dotfiles = false, + custom = {}, + exclude = {}, + }, + git = { + enable = true, + ignore = true, + timeout = 400, + }, + actions = { + use_system_clipboard = true, + change_dir = { + enable = true, + global = false, + restrict_above_cwd = false, + }, + open_file = { + quit_on_open = false, + resize_window = false, + window_picker = { + enable = true, + chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", + exclude = { + filetype = { "notify", "qf", "diff", "fugitive", "fugitiveblame" }, + buftype = { "nofile", "terminal", "help" }, + }, + }, + }, + }, + trash = { + cmd = "trash", + require_confirm = true, + }, + log = { + enable = false, + truncate = false, + types = { + all = false, + config = false, + copy_paste = false, + diagnostics = false, + git = false, + profile = false, + }, + }, +} + +keymap.set("n", "s", require("nvim-tree.api").tree.toggle, { + silent = true, + desc = "toggle nvim-tree", +}) diff --git a/.config/nvim/lua/config/statusline.lua b/.config/nvim/lua/config/statusline.lua new file mode 100644 index 0000000..0563ba6 --- /dev/null +++ b/.config/nvim/lua/config/statusline.lua @@ -0,0 +1,197 @@ +local fn = vim.fn + +local function spell() + if vim.o.spell then + return string.format("[SPELL]") + end + + return "" +end + +--- show indicator for Chinese IME +local function ime_state() + if vim.g.is_mac then + -- ref: https://github.com/vim-airline/vim-airline/blob/master/autoload/airline/extensions/xkblayout.vim#L11 + local layout = fn.libcall(vim.g.XkbSwitchLib, "Xkb_Switch_getXkbLayout", "") + + -- We can use `xkbswitch -g` on the command line to get current mode. + -- mode for macOS builtin pinyin IME: com.apple.inputmethod.SCIM.ITABC + -- mode for Rime: im.rime.inputmethod.Squirrel.Rime + local res = fn.match(layout, [[\v(Squirrel\.Rime|SCIM.ITABC)]]) + if res ~= -1 then + return "[CN]" + end + end + + return "" +end + +local function trailing_space() + if not vim.o.modifiable then + return "" + end + + local line_num = nil + + for i = 1, fn.line("$") do + local linetext = fn.getline(i) + -- To prevent invalid escape error, we wrap the regex string with `[[]]`. + local idx = fn.match(linetext, [[\v\s+$]]) + + if idx ~= -1 then + line_num = i + break + end + end + + local msg = "" + if line_num ~= nil then + msg = string.format("[%d]trailing", line_num) + end + + return msg +end + +local function mixed_indent() + if not vim.o.modifiable then + return "" + end + + local space_pat = [[\v^ +]] + local tab_pat = [[\v^\t+]] + local space_indent = fn.search(space_pat, "nwc") + local tab_indent = fn.search(tab_pat, "nwc") + local mixed = (space_indent > 0 and tab_indent > 0) + local mixed_same_line + if not mixed then + mixed_same_line = fn.search([[\v^(\t+ | +\t)]], "nwc") + mixed = mixed_same_line > 0 + end + if not mixed then + return "" + end + if mixed_same_line ~= nil and mixed_same_line > 0 then + return "MI:" .. mixed_same_line + end + local space_indent_cnt = fn.searchcount({ pattern = space_pat, max_count = 1e3 }).total + local tab_indent_cnt = fn.searchcount({ pattern = tab_pat, max_count = 1e3 }).total + if space_indent_cnt > tab_indent_cnt then + return "MI:" .. tab_indent + else + return "MI:" .. space_indent + end +end + +local diff = function() + local git_status = vim.b.gitsigns_status_dict + if git_status == nil then + return + end + + local modify_num = git_status.changed + local remove_num = git_status.removed + local add_num = git_status.added + + local info = { added = add_num, modified = modify_num, removed = remove_num } + -- vim.print(info) + return info +end + +local virtual_env = function() + -- only show virtual env for Python + if vim.bo.filetype ~= 'python' then + return "" + end + + local conda_env = os.getenv('CONDA_DEFAULT_ENV') + local venv_path = os.getenv('VIRTUAL_ENV') + + if venv_path == nil then + if conda_env == nil then + return "" + else + return string.format(" %s (conda)", conda_env) + end + else + local venv_name = vim.fn.fnamemodify(venv_path, ':t') + return string.format(" %s (venv)", venv_name) + end +end + +require("lualine").setup { + options = { + icons_enabled = true, + theme = "auto", + -- component_separators = { left = "", right = "" }, + -- section_separators = { left = "", right = "" }, + section_separators = "", + component_separators = "", + disabled_filetypes = {}, + always_divide_middle = true, + }, + sections = { + lualine_a = { "mode" }, + lualine_b = { + "branch", + { + "diff", + source = diff, + }, + { + virtual_env, + color = { fg = 'black', bg = "#F1CA81" } + } + }, + lualine_c = { + "filename", + { + ime_state, + color = { fg = "black", bg = "#f46868" }, + }, + { + spell, + color = { fg = "black", bg = "#a7c080" }, + }, + { + "diagnostics", + sources = { "nvim_diagnostic" }, + symbols = {error = '🆇 ', warn = '⚠️ ', info = 'ℹ️ ', hint = ' '}, + }, + }, + lualine_x = { + "encoding", + { + "fileformat", + symbols = { + unix = "unix", + dos = "win", + mac = "mac", + }, + }, + "filetype", + }, + lualine_y = { + "location", + }, + lualine_z = { + { + trailing_space, + color = "WarningMsg", + }, + { + mixed_indent, + color = "WarningMsg", + }, + }, + }, + inactive_sections = { + lualine_a = {}, + lualine_b = {}, + lualine_c = { "filename" }, + lualine_x = { "location" }, + lualine_y = {}, + lualine_z = {}, + }, + tabline = {}, + extensions = { "quickfix", "fugitive", "nvim-tree" }, +} diff --git a/.config/nvim/lua/custom-autocmd.lua b/.config/nvim/lua/custom-autocmd.lua new file mode 100644 index 0000000..21fa15c --- /dev/null +++ b/.config/nvim/lua/custom-autocmd.lua @@ -0,0 +1,105 @@ +local fn = vim.fn +local api = vim.api + +local utils = require("utils") + +-- Display a message when the current file is not in utf-8 format. +-- Note that we need to use `unsilent` command here because of this issue: +-- https://github.com/vim/vim/issues/4379 +api.nvim_create_autocmd({ "BufRead" }, { + pattern = "*", + group = api.nvim_create_augroup("non_utf8_file", { clear = true }), + callback = function() + if vim.bo.fileencoding ~= "utf-8" then + vim.notify("File not in UTF-8 format!", vim.log.levels.WARN, { title = "nvim-config" }) + end + end, +}) + +-- highlight yanked region, see `:h lua-highlight` +local yank_group = api.nvim_create_augroup("highlight_yank", { clear = true }) +api.nvim_create_autocmd({ "TextYankPost" }, { + pattern = "*", + group = yank_group, + callback = function() + vim.highlight.on_yank { higroup = "YankColor", timeout = 300 } + end, +}) + +api.nvim_create_autocmd({ "CursorMoved" }, { + pattern = "*", + group = yank_group, + callback = function() + vim.g.current_cursor_pos = vim.fn.getcurpos() + end, +}) + +api.nvim_create_autocmd("TextYankPost", { + pattern = "*", + group = yank_group, + callback = function(ev) + if vim.v.event.operator == 'y' then + vim.fn.setpos('.', vim.g.current_cursor_pos) + end + end, +}) + +-- Auto-create dir when saving a file, in case some intermediate directory does not exist +api.nvim_create_autocmd({ "BufWritePre" }, { + pattern = "*", + group = api.nvim_create_augroup("auto_create_dir", { clear = true }), + callback = function(ctx) + local dir = fn.fnamemodify(ctx.file, ":p:h") + utils.may_create_dir(dir) + end, +}) + +-- Automatically reload the file if it is changed outside of Nvim, see https://unix.stackexchange.com/a/383044/221410. +-- It seems that `checktime` does not work in command line. We need to check if we are in command +-- line before executing this command, see also https://vi.stackexchange.com/a/20397/15292 . +api.nvim_create_augroup("auto_read", { clear = true }) + +api.nvim_create_autocmd({ "FileChangedShellPost" }, { + pattern = "*", + group = "auto_read", + callback = function() + vim.notify("File changed on disk. Buffer reloaded!", vim.log.levels.WARN, { title = "nvim-config" }) + end, +}) + +api.nvim_create_autocmd({ "FocusGained", "CursorHold" }, { + pattern = "*", + group = "auto_read", + callback = function() + if fn.getcmdwintype() == "" then + vim.cmd("checktime") + end + end, +}) + +-- Resize all windows when we resize the terminal +api.nvim_create_autocmd("VimResized", { + group = api.nvim_create_augroup("win_autoresize", { clear = true }), + desc = "autoresize windows on resizing operation", + command = "wincmd =", +}) + +local function open_nvim_tree(data) + -- check if buffer is a directory + local directory = vim.fn.isdirectory(data.file) == 1 + + if not directory then + return + end + + -- create a new, empty buffer + vim.cmd.enew() + + -- wipe the directory buffer + vim.cmd.bw(data.buf) + + -- open the tree + require("nvim-tree.api").tree.open() +end + +vim.api.nvim_create_autocmd({ "VimEnter" }, { callback = open_nvim_tree }) diff --git a/.config/nvim/lua/mappings.lua b/.config/nvim/lua/mappings.lua new file mode 100644 index 0000000..2837650 --- /dev/null +++ b/.config/nvim/lua/mappings.lua @@ -0,0 +1,231 @@ +local keymap = vim.keymap +local api = vim.api +local uv = vim.loop + +-- Save key strokes (now we do not need to press shift to enter command mode). +keymap.set({ "n", "x" }, ";", ":") + +-- Turn the word under cursor to upper case +keymap.set("i", "", "viwUea") + +-- Turn the current word into title case +keymap.set("i", "", "b~lea") + +-- Paste non-linewise text above or below current line, see https://stackoverflow.com/a/1346777/6064933 +keymap.set("n", "p", "m`op``", { desc = "paste below current line" }) +keymap.set("n", "P", "m`Op``", { desc = "paste above current line" }) + +-- Shortcut for faster save and quit +keymap.set("n", "w", "update", { silent = true, desc = "save buffer" }) + +-- Saves the file if modified and quit +keymap.set("n", "q", "x", { silent = true, desc = "quit current window" }) + +-- Quit all opened buffers +keymap.set("n", "Q", "qa!", { silent = true, desc = "quit nvim" }) + +-- Navigation in the location and quickfix list +keymap.set("n", "[l", "lpreviouszv", { silent = true, desc = "previous location item" }) +keymap.set("n", "]l", "lnextzv", { silent = true, desc = "next location item" }) + +keymap.set("n", "[L", "lfirstzv", { silent = true, desc = "first location item" }) +keymap.set("n", "]L", "llastzv", { silent = true, desc = "last location item" }) + +keymap.set("n", "[q", "cpreviouszv", { silent = true, desc = "previous qf item" }) +keymap.set("n", "]q", "cnextzv", { silent = true, desc = "next qf item" }) + +keymap.set("n", "[Q", "cfirstzv", { silent = true, desc = "first qf item" }) +keymap.set("n", "]Q", "clastzv", { silent = true, desc = "last qf item" }) + +-- Close location list or quickfix list if they are present, see https://superuser.com/q/355325/736190 +keymap.set("n", [[\x]], "windo lclose cclose ", { + silent = true, + desc = "close qf and location list", +}) + +-- Delete a buffer, without closing the window, see https://stackoverflow.com/q/4465095/6064933 +keymap.set("n", [[\d]], "bprevious bdelete #", { + silent = true, + desc = "delete buffer", +}) + +-- Insert a blank line below or above current line (do not move the cursor), +-- see https://stackoverflow.com/a/16136133/6064933 +keymap.set("n", "o", "printf('m`%so``', v:count1)", { + expr = true, + desc = "insert line below", +}) + +keymap.set("n", "O", "printf('m`%sO``', v:count1)", { + expr = true, + desc = "insert line above", +}) + +-- Move the cursor based on physical lines, not the actual lines. +keymap.set("n", "j", "v:count == 0 ? 'gj' : 'j'", { expr = true }) +keymap.set("n", "k", "v:count == 0 ? 'gk' : 'k'", { expr = true }) +keymap.set("n", "^", "g^") +keymap.set("n", "0", "g0") + +-- Do not include white space characters when using $ in visual mode, +-- see https://vi.stackexchange.com/q/12607/15292 +keymap.set("x", "$", "g_") + +-- Go to start or end of line easier +keymap.set({ "n", "x" }, "H", "^") +keymap.set({ "n", "x" }, "L", "g_") + +-- Continuous visual shifting (does not exit Visual mode), `gv` means +-- to reselect previous visual area, see https://superuser.com/q/310417/736190 +keymap.set("x", "<", "", ">gv") + +-- Edit and reload nvim config file quickly +keymap.set("n", "ev", "tabnew $MYVIMRC tcd %:h", { + silent = true, + desc = "open init.lua", +}) + +keymap.set("n", "sv", function() + vim.cmd([[ + update $MYVIMRC + source $MYVIMRC + ]]) + vim.notify("Nvim config successfully reloaded!", vim.log.levels.INFO, { title = "nvim-config" }) +end, { + silent = true, + desc = "reload init.lua", +}) + +-- Reselect the text that has just been pasted, see also https://stackoverflow.com/a/4317090/6064933. +keymap.set("n", "v", "printf('`[%s`]', getregtype()[0])", { + expr = true, + desc = "reselect last pasted area", +}) + +-- Always use very magic mode for searching +keymap.set("n", "/", [[/\v]]) + +-- Search in selected region +-- xnoremap / :call feedkeys('/\%>'.(line("'<")-1).'l\%<'.(line("'>")+1)."l") + +-- Change current working directory locally and print cwd after that, +-- see https://vim.fandom.com/wiki/Set_working_directory_to_the_current_file +keymap.set("n", "cd", "lcd %:p:hpwd", { desc = "change cwd" }) + +-- Use Esc to quit builtin terminal +keymap.set("t", "", [[]]) + +-- Toggle spell checking +keymap.set("n", "", "set spell!", { desc = "toggle spell" }) +keymap.set("i", "", "set spell!", { desc = "toggle spell" }) + +-- Change text without putting it into the vim register, +-- see https://stackoverflow.com/q/54255/6064933 +keymap.set("n", "c", '"_c') +keymap.set("n", "C", '"_C') +keymap.set("n", "cc", '"_cc') +keymap.set("x", "c", '"_c') + +-- Remove trailing whitespace characters +keymap.set("n", "", "StripTrailingWhitespace", { desc = "remove trailing space" }) + +-- check the syntax group of current cursor position +keymap.set("n", "st", "call utils#SynGroup()", { desc = "check syntax group" }) + +-- Copy entire buffer. +keymap.set("n", "y", "%yank", { desc = "yank entire buffer" }) + +-- Toggle cursor column +keymap.set("n", "cl", "call utils#ToggleCursorCol()", { desc = "toggle cursor column" }) + +-- Move current line up and down +keymap.set("n", "", 'call utils#SwitchLine(line("."), "up")', { desc = "move line up" }) +keymap.set("n", "", 'call utils#SwitchLine(line("."), "down")', { desc = "move line down" }) + +-- Move current visual-line selection up and down +keymap.set("x", "", 'call utils#MoveSelection("up")', { desc = "move selection up" }) + +keymap.set("x", "", 'call utils#MoveSelection("down")', { desc = "move selection down" }) + +-- Replace visual selection with text in register, but not contaminate the register, +-- see also https://stackoverflow.com/q/10723700/6064933. +keymap.set("x", "p", '"_cp') + +-- Go to a certain buffer +keymap.set("n", "gb", 'call buf_utils#GoToBuffer(v:count, "forward")', { + desc = "go to buffer (forward)", +}) +keymap.set("n", "gB", 'call buf_utils#GoToBuffer(v:count, "backward")', { + desc = "go to buffer (backward)", +}) + +-- Switch windows +keymap.set("n", "", "h") +keymap.set("n", "", "l") +keymap.set("n", "", "k") +keymap.set("n", "", "j") + +-- Text objects for URL +keymap.set({ "x", "o" }, "iu", "call text_obj#URL()", { desc = "URL text object" }) + +-- Text objects for entire buffer +keymap.set({ "x", "o" }, "iB", ":call text_obj#Buffer()", { desc = "buffer text object" }) + +-- Do not move my cursor when joining lines. +keymap.set("n", "J", function() + vim.cmd([[ + normal! mzJ`z + delmarks z + ]]) +end, { + desc = "join lines without moving cursor", +}) + +keymap.set("n", "gJ", function() + -- we must use `normal!`, otherwise it will trigger recursive mapping + vim.cmd([[ + normal! mzgJ`z + delmarks z + ]]) +end, { + desc = "join lines without moving cursor", +}) + +-- Break inserted text into smaller undo units when we insert some punctuation chars. +local undo_ch = { ",", ".", "!", "?", ";", ":" } +for _, ch in ipairs(undo_ch) do + keymap.set("i", ch, ch .. "u") +end + +-- insert semicolon in the end +keymap.set("i", "", "miA;`ii") + +-- Go to the beginning and end of current line in insert mode quickly +keymap.set("i", "", "") +keymap.set("i", "", "") + +-- Go to beginning of command in command-line mode +keymap.set("c", "", "") + +-- Delete the character to the right of the cursor +keymap.set("i", "", "") + +keymap.set("n", "cb", function() + local cnt = 0 + local blink_times = 7 + local timer = uv.new_timer() + + timer:start(0, 100, vim.schedule_wrap(function() + vim.cmd[[ + set cursorcolumn! + set cursorline! + ]] + + if cnt == blink_times then + timer:close() + end + + cnt = cnt + 1 + end)) +end) diff --git a/.config/nvim/lua/plugin_specs.lua b/.config/nvim/lua/plugin_specs.lua new file mode 100644 index 0000000..a585ee1 --- /dev/null +++ b/.config/nvim/lua/plugin_specs.lua @@ -0,0 +1,503 @@ +local utils = require("utils") + +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" + +if not vim.loop.fs_stat(lazypath) then + vim.fn.system { + "git", + "clone", + "--filter=blob:none", + "https://github.com/folke/lazy.nvim.git", + "--branch=stable", -- latest stable release + lazypath, + } +end +vim.opt.rtp:prepend(lazypath) + +-- check if firenvim is active +local firenvim_not_active = function() + return not vim.g.started_by_firenvim +end + +local plugin_specs = { + -- auto-completion engine + { + "hrsh7th/nvim-cmp", + -- event = 'InsertEnter', + event = "VeryLazy", + dependencies = { + "hrsh7th/cmp-nvim-lsp", + "onsails/lspkind-nvim", + "hrsh7th/cmp-path", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-omni", + "hrsh7th/cmp-emoji", + "quangnguyen30192/cmp-nvim-ultisnips", + }, + config = function() + require("config.nvim-cmp") + end, + }, + + { + "neovim/nvim-lspconfig", + event = { "BufRead", "BufNewFile" }, + config = function() + require("config.lsp") + end, + }, + + { + "nvim-treesitter/nvim-treesitter", + enabled = function() + if vim.g.is_mac then + return true + end + return false + end, + event = "VeryLazy", + build = ":TSUpdate", + config = function() + require("config.treesitter") + end, + }, + + -- Python indent (follows the PEP8 style) + { "Vimjas/vim-python-pep8-indent", ft = { "python" } }, + + -- Python-related text object + { "jeetsukumaran/vim-pythonsense", ft = { "python" } }, + + { "machakann/vim-swap", event = "VeryLazy" }, + + -- IDE for Lisp + -- 'kovisoft/slimv' + { + "vlime/vlime", + enabled = function() + if utils.executable("sbcl") then + return true + end + return false + end, + config = function(plugin) + vim.opt.rtp:append(plugin.dir .. "/vim") + end, + ft = { "lisp" }, + }, + + -- Super fast buffer jump + { + "smoka7/hop.nvim", + event = "VeryLazy", + config = function() + require("config.nvim_hop") + end, + }, + + -- Show match number and index for searching + { + "kevinhwang91/nvim-hlslens", + branch = "main", + keys = { "*", "#", "n", "N" }, + config = function() + require("config.hlslens") + end, + }, + { + "Yggdroot/LeaderF", + cmd = "Leaderf", + build = function() + if not vim.g.is_win then + vim.cmd(":LeaderfInstallCExtension") + end + end, + }, + "nvim-lua/plenary.nvim", + { + "nvim-telescope/telescope.nvim", + cmd = "Telescope", + dependencies = { + "nvim-telescope/telescope-symbols.nvim", + }, + }, + { + "lukas-reineke/headlines.nvim", + dependencies = "nvim-treesitter/nvim-treesitter", + config = true, -- or `opts = {}` + }, + -- A list of colorscheme plugin you may want to try. Find what suits you. + { "navarasu/onedark.nvim", lazy = true }, + { "sainnhe/edge", lazy = true }, + { "sainnhe/sonokai", lazy = true }, + { "sainnhe/gruvbox-material", lazy = true }, + { "sainnhe/everforest", lazy = true }, + { "EdenEast/nightfox.nvim", lazy = true }, + { "catppuccin/nvim", name = "catppuccin", lazy = true }, + { "olimorris/onedarkpro.nvim", lazy = true }, + { "marko-cerovac/material.nvim", lazy = true }, + + { "nvim-tree/nvim-web-devicons", event = "VeryLazy" }, + + { + "nvim-lualine/lualine.nvim", + event = "VeryLazy", + cond = firenvim_not_active, + config = function() + require("config.statusline") + end, + }, + + { + "akinsho/bufferline.nvim", + event = { "BufEnter" }, + cond = firenvim_not_active, + config = function() + require("config.bufferline") + end, + }, + + -- fancy start screen + { + "nvimdev/dashboard-nvim", + cond = firenvim_not_active, + config = function() + require("config.dashboard-nvim") + end, + }, + + { + "lukas-reineke/indent-blankline.nvim", + event = "VeryLazy", + main = 'ibl', + config = function() + require("config.indent-blankline") + end, + }, + + -- Highlight URLs inside vim + { "itchyny/vim-highlighturl", event = "VeryLazy" }, + + -- notification plugin + { + "rcarriga/nvim-notify", + event = "VeryLazy", + config = function() + require("config.nvim-notify") + end, + }, + + -- For Windows and Mac, we can open an URL in the browser. For Linux, it may + -- not be possible since we maybe in a server which disables GUI. + { + "tyru/open-browser.vim", + enabled = function() + if vim.g.is_win or vim.g.is_mac then + return true + else + return false + end + end, + event = "VeryLazy", + }, + + -- Only install these plugins if ctags are installed on the system + -- show file tags in vim window + { + "liuchengxu/vista.vim", + enabled = function() + if utils.executable("ctags") then + return true + else + return false + end + end, + cmd = "Vista", + }, + + -- Snippet engine and snippet template + { "SirVer/ultisnips", dependencies = { + "honza/vim-snippets", + }, event = "InsertEnter" }, + + -- Automatic insertion and deletion of a pair of characters + { "Raimondi/delimitMate", event = "InsertEnter" }, + + -- Comment plugin + { "tpope/vim-commentary", event = "VeryLazy" }, + + -- Multiple cursor plugin like Sublime Text? + -- 'mg979/vim-visual-multi' + + -- Autosave files on certain events + { "907th/vim-auto-save", event = "InsertEnter" }, + + -- Show undo history visually + { "simnalamburt/vim-mundo", cmd = { "MundoToggle", "MundoShow" } }, + + -- better UI for some nvim actions + { "stevearc/dressing.nvim" }, + + -- Manage your yank history + { + "gbprod/yanky.nvim", + cmd = { "YankyRingHistory" }, + config = function() + require("config.yanky") + end, + }, + + -- Handy unix command inside Vim (Rename, Move etc.) + { "tpope/vim-eunuch", cmd = { "Rename", "Delete" } }, + + -- Repeat vim motions + { "tpope/vim-repeat", event = "VeryLazy" }, + + { "nvim-zh/better-escape.vim", event = { "InsertEnter" } }, + + { + "lyokha/vim-xkbswitch", + enabled = function() + if vim.g.is_mac and utils.executable("xkbswitch") then + return true + end + return false + end, + event = { "InsertEnter" }, + }, + + { + "Neur1n/neuims", + enabled = function() + if vim.g.is_win then + return true + end + return false + end, + event = { "InsertEnter" }, + }, + + -- Auto format tools + { "sbdchd/neoformat", cmd = { "Neoformat" } }, + + -- Git command inside vim + { + "tpope/vim-fugitive", + event = "User InGitRepo", + config = function() + require("config.fugitive") + end, + }, + + -- Better git log display + { "rbong/vim-flog", cmd = { "Flog" } }, + { "akinsho/git-conflict.nvim", version = "*", config = true }, + { + "ruifm/gitlinker.nvim", + event = "User InGitRepo", + config = function() + require("config.git-linker") + end, + }, + + -- Show git change (change, delete, add) signs in vim sign column + { + "lewis6991/gitsigns.nvim", + config = function() + require("config.gitsigns") + end, + }, + + -- Better git commit experience + { "rhysd/committia.vim", lazy = true }, + + { + "sindrets/diffview.nvim" + }, + + { + "kevinhwang91/nvim-bqf", + ft = "qf", + config = function() + require("config.bqf") + end, + }, + + -- Another markdown plugin + { "preservim/vim-markdown", ft = { "markdown" } }, + + -- Faster footnote generation + { "vim-pandoc/vim-markdownfootnotes", ft = { "markdown" } }, + + -- Vim tabular plugin for manipulate tabular, required by markdown plugins + { "godlygeek/tabular", cmd = { "Tabularize" } }, + + -- Markdown previewing (only for Mac and Windows) + { + "iamcco/markdown-preview.nvim", + enabled = function() + if vim.g.is_win or vim.g.is_mac then + return true + end + return false + end, + build = "cd app && npm install", + ft = { "markdown" }, + }, + + { + "folke/zen-mode.nvim", + cmd = "ZenMode", + config = function() + require("config.zen-mode") + end, + }, + + { + "rhysd/vim-grammarous", + enabled = function() + if vim.g.is_mac then + return true + end + return false + end, + ft = { "markdown" }, + }, + + { "chrisbra/unicode.vim", event = "VeryLazy" }, + + -- Additional powerful text object for vim, this plugin should be studied + -- carefully to use its full power + { "wellle/targets.vim", event = "VeryLazy" }, + + -- Plugin to manipulate character pairs quickly + { "machakann/vim-sandwich", event = "VeryLazy" }, + + -- Add indent object for vim (useful for languages like Python) + { "michaeljsmith/vim-indent-object", event = "VeryLazy" }, + + -- Only use these plugin on Windows and Mac and when LaTeX is installed + { + "lervag/vimtex", + enabled = function() + if utils.executable("latex") then + return true + end + return false + end, + ft = { "tex" }, + }, + + -- Since tmux is only available on Linux and Mac, we only enable these plugins + -- for Linux and Mac + -- .tmux.conf syntax highlighting and setting check + { + "tmux-plugins/vim-tmux", + enabled = function() + if utils.executable("tmux") then + return true + end + return false + end, + ft = { "tmux" }, + }, + + -- Modern matchit implementation + { "andymass/vim-matchup", event = "BufRead" }, + { "tpope/vim-scriptease", cmd = { "Scriptnames", "Message", "Verbose" } }, + + -- Asynchronous command execution + { "skywind3000/asyncrun.vim", lazy = true, cmd = { "AsyncRun" } }, + { "cespare/vim-toml", ft = { "toml" }, branch = "main" }, + + -- Edit text area in browser using nvim + { + "glacambre/firenvim", + enabled = function() + if vim.g.is_win or vim.g.is_mac then + return true + end + return false + end, + build = function() + vim.fn["firenvim#install"](0) + end, + lazy = true, + }, + + -- Debugger plugin + { + "sakhnik/nvim-gdb", + enabled = function() + if vim.g.is_win or vim.g.is_linux then + return true + end + return false + end, + build = { "bash install.sh" }, + lazy = true, + }, + + -- Session management plugin + { "tpope/vim-obsession", cmd = "Obsession" }, + + { + "ojroques/vim-oscyank", + enabled = function() + if vim.g.is_linux then + return true + end + return false + end, + cmd = { "OSCYank", "OSCYankReg" }, + }, + + -- The missing auto-completion for cmdline! + { + "gelguy/wilder.nvim", + build = ":UpdateRemotePlugins", + }, + + -- showing keybindings + { + "folke/which-key.nvim", + event = "VeryLazy", + config = function() + require("config.which-key") + end, + }, + + -- show and trim trailing whitespaces + { "jdhao/whitespace.nvim", event = "VeryLazy" }, + + -- file explorer + { + "nvim-tree/nvim-tree.lua", + keys = { "s" }, + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + require("config.nvim-tree") + end, + }, + + { "ii14/emmylua-nvim", ft = "lua" }, + { + "j-hui/fidget.nvim", + event = "VeryLazy", + tag = "legacy", + config = function() + require("config.fidget-nvim") + end, + }, +} + +-- configuration for lazy itself. +local lazy_opts = { + ui = { + border = "rounded", + title = "Plugin Manager", + title_pos = "center", + }, +} + +require("lazy").setup(plugin_specs, lazy_opts) -- cgit v1.2.3