diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2025-12-24 13:54:03 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2025-12-24 13:54:03 +0900 |
| commit | 28e8bdf7f8286bd431b7f3b709e79f3827b31469 (patch) | |
| tree | 85b44eff6da4d8443198fb6e04dfb6ee55244588 /debian/.config/TheSiahxyz/lua | |
| parent | 8470ff001befcfd0f626dea69a9e76d43aee0511 (diff) | |
updates
Diffstat (limited to 'debian/.config/TheSiahxyz/lua')
72 files changed, 13561 insertions, 0 deletions
diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/autocmds.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/autocmds.lua new file mode 100644 index 0000000..3bd702a --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/autocmds.lua @@ -0,0 +1,388 @@ +local function augroup(name) + return vim.api.nvim_create_augroup("TheSiahxyz_" .. name, { clear = true }) +end + +local autocmd = vim.api.nvim_create_autocmd +local home = os.getenv("HOME") + +-- Change the color of symlink files to distinguish between directory and symlink files +autocmd("FileType", { + group = augroup("highlight_linked_files"), + pattern = "netrw", + callback = function() + vim.cmd("highlight NetrwSymlink guifg=#689D6A ctermfg=214") + end, +}) + +-- Check if we need to reload the file when it changed +autocmd({ "FocusGained", "TermClose", "TermLeave" }, { + group = augroup("check_time"), + callback = function() + if vim.o.buftype ~= "nofile" then + vim.cmd("checktime") + end + end, +}) + +-- Highlight on yank +autocmd("TextYankPost", { + group = augroup("highlight_yank"), + callback = function() + vim.highlight.on_yank() + end, +}) + +-- Resize splits if window got resized +autocmd({ "VimResized" }, { + group = augroup("window_config"), + callback = function() + local current_tab = vim.fn.tabpagenr() + vim.cmd("tabdo wincmd =") + vim.cmd("tabnext " .. current_tab) + end, +}) + +-- Go to last loc when opening a buffer +autocmd("BufReadPost", { + group = augroup("last_loc"), + callback = function(event) + local exclude = { "gitcommit" } + local buf = event.buf + if vim.tbl_contains(exclude, vim.bo[buf].filetype) or vim.b[buf].TheSiahxyz_last_loc then + return + end + vim.b[buf].TheSiahxyz_last_loc = true + local mark = vim.api.nvim_buf_get_mark(buf, '"') + local lcount = vim.api.nvim_buf_line_count(buf) + if mark[1] > 0 and mark[1] <= lcount then + pcall(vim.api.nvim_win_set_cursor, 0, mark) + end + end, +}) + +-- Close some filetypes with <q> +autocmd("FileType", { + group = augroup("close_with_q"), + pattern = { + "checkhealth", + "dbout", + "gitsigns-blame", + "grug-far", + "help", + "lspinfo", + "Lazy", + "neotest-output", + "neotest-output-panel", + "neotest-summary", + "notify", + "PlenaryTestPopup", + "qf", + "query", + "spectre_panel", + "startuptime", + "terminal", + "tsplayground", + }, + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", "<Cmd>close<cr>", { buffer = event.buf, silent = true }) + end, +}) +autocmd("FileType", { + group = augroup("q_as_bd"), + pattern = "netrw", + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", function() + vim.cmd("bd") + end, { buffer = event.buf, silent = true }) + end, +}) + +-- Make it easier to close man-files when opened inline +autocmd("FileType", { + group = augroup("man_close"), + pattern = { "man" }, + callback = function(event) + vim.bo[event.buf].buflisted = false + end, +}) + +-- Fix conceallevel for json files +autocmd({ "FileType" }, { + group = augroup("json_config"), + pattern = { "json", "jsonc", "json5" }, + callback = function() + vim.opt_local.conceallevel = 0 + end, +}) + +-- Auto create dir when saving a file, in case some intermediate directory does not exist +autocmd({ "BufWritePre" }, { + group = augroup("create_dir"), + callback = function(event) + if event.match:match("^%w%w+:[\\/][\\/]") then + return + end + local file = vim.uv.fs_realpath(event.match) or event.match + vim.fn.mkdir(vim.fn.fnamemodify(file, ":p:h"), "p") + end, +}) + +-- Automatically delete all trailing whitespace and newlines at end of file on save +local file_save = augroup("file_save") +autocmd("BufWritePre", { + group = file_save, + pattern = "*", + callback = function() + local cursor_pos = vim.api.nvim_win_get_cursor(0) + vim.cmd([[ %s/\s\+$//e ]]) -- Remove trailing spaces + vim.cmd([[ %s/\n\+\%$//e ]]) -- Remove trailing newlines + local line_count = vim.api.nvim_buf_line_count(0) + local line = math.min(cursor_pos[1], line_count) + local col = cursor_pos[2] + -- Optional: clamp column if line got shorter + local line_text = vim.api.nvim_buf_get_lines(0, line - 1, line, false)[1] or "" + col = math.min(col, #line_text) + vim.api.nvim_win_set_cursor(0, { line, col }) + end, +}) + +-- Add a trailing newline for C files +autocmd("BufWritePre", { + group = file_save, + pattern = "*.[ch]", + callback = function() + vim.cmd([[ %s/\%$/\r/e ]]) + end, +}) + +-- Go to insert mode in terminal +local win_enter = augroup("win_enter") +autocmd("WinEnter", { + group = win_enter, + callback = function() + if vim.bo.buftype == "terminal" then + vim.cmd("startinsert") + end + end, +}) + +-- Correct email signature delimiter in neomutt files +autocmd("BufWritePre", { + group = file_save, + pattern = "*neomutt*", + callback = function() + vim.cmd([[ %s/^--$/-- /e ]]) + end, +}) + +local function organize_imports() + local params = { + command = "pyright.organizeimports", + arguments = { vim.uri_from_bufnr(0) }, + } + local clients = vim.lsp.get_clients({ bufnr = 0 }) + for _, client in ipairs(clients) do + client:exec_cmd(params, { bufnr = 0 }) + end +end + +autocmd("LspAttach", { + group = augroup("lsp_attach"), + callback = function(e) + local client = vim.lsp.get_client_by_id(e.data.client_id) + if client and client.name == "pyright" then + vim.api.nvim_create_user_command( + "PyrightOrganizeImports", + organize_imports, + { desc = "Organize imports (lsp)" } + ) + end + vim.keymap.set("n", "gD", function() + vim.lsp.buf.definition() + end, { buffer = e.buf, desc = "Go to definition (lsp)" }) + vim.keymap.set("n", "K", function() + vim.lsp.buf.hover() + end, { buffer = e.buf, desc = "Go to keywords (lsp)" }) + vim.keymap.set("n", "<leader>ls", function() + vim.lsp.buf.workspace_symbol() + end, { buffer = e.buf, desc = "Workspace symbol (lsp)" }) + vim.keymap.set("n", "<leader>lo", function() + vim.diagnostic.open_float() + end, { buffer = e.buf, desc = "Open diagnostic" }) + vim.keymap.set("n", "<leader>lc", function() + vim.lsp.buf.code_action() + end, { buffer = e.buf, desc = "Code action (lsp)" }) + vim.keymap.set("n", "<leader>lr", function() + vim.lsp.buf.references() + end, { buffer = e.buf, desc = "References (lsp)" }) + vim.keymap.set("n", "<leader>ln", function() + vim.lsp.buf.rename() + end, { buffer = e.buf, desc = "Rename (lsp)" }) + vim.keymap.set("n", "<leader>lh", function() + vim.lsp.buf.signature_help() + end, { buffer = e.buf, desc = "Signature help (lsp)" }) + vim.keymap.set("n", "]d", function() + vim.diagnostic.goto_next() + end, { buffer = e.buf, desc = "Next diagnostic" }) + vim.keymap.set("n", "[d", function() + vim.diagnostic.goto_prev() + end, { buffer = e.buf, desc = "Previous diagnostic" }) + end, +}) + +-- Save file as sudo on files that require root permission +vim.api.nvim_create_user_command("SudoWrite", function() + vim.cmd([[ + write !sudo tee % 2>/dev/null + edit! + ]]) +end, {}) +vim.api.nvim_create_user_command("SudoWritequit", function() + vim.cmd([[ + write !sudo tee % 2>/dev/null + edit! + quit! + ]]) +end, {}) + +-- Markdown for specific files and directories +autocmd({ "BufRead", "BufNewFile" }, { + pattern = { "/tmp/calcurse*", "~/.calcurse/notes/*" }, + command = "set filetype=markdown", +}) + +-- Groff for specific file extensions +autocmd({ "BufRead", "BufNewFile" }, { + pattern = { "*.ms", "*.me", "*.mom", "*.man" }, + callback = function() + vim.cmd([[ + set columns=90 + set filetype=groff + set linebreak + set textwidth=0 + set wrap + set wrapmargin=0 + ]]) + end, +}) + +-- TeX for .tex files +autocmd({ "BufRead", "BufNewFile" }, { + pattern = { "*.tex" }, + command = "set filetype=tex", +}) + +-- When shortcut files are updated, renew bash and lf configs with new material: +autocmd("BufWritePost", { + group = augroup("bookmarks"), + pattern = { "bm-files", "bm-dirs" }, + callback = function() + -- Execute the 'shortcuts' shell command + local result = vim.fn.system("shortcuts") + -- Display an error message only if the 'shortcuts' command fails + if vim.v.shell_error ~= 0 then + -- Display an error message if the 'shortcuts' command fails + vim.api.nvim_echo({ { "failed to update shortcuts: " .. result, "ErrorMsg" } }, true, {}) + end + end, +}) + +-- Source lfrc if it's edited +local lf_config = augroup("lf_config") +autocmd("BufWritePost", { + group = lf_config, + pattern = { "lfrc" }, + callback = function() + vim.cmd("silent !source ~/.config/lf/lfrc") + end, +}) + +-- Set vimwiki's index filetype to vimwiki instead of markdown +local vimwiki_config = augroup("vimwiki_config") +autocmd({ "BufRead", "BufNewFile" }, { + group = vimwiki_config, + pattern = vim.fn.expand("~/.local/share/vimwiki") .. "/**/*.md", + callback = function(args) + vim.bo[args.buf].filetype = "vimwiki" + end, +}) + +-- Run xrdb whenever Xdefaults or Xresources are updated. +local x_config = augroup("x_config") +autocmd({ "BufRead", "BufNewFile" }, { + group = x_config, + pattern = { "Xresources", "Xdefaults", "xresources", "xdefaults" }, + callback = function() + vim.bo.filetype = "xdefaults" + end, +}) +autocmd("BufWritePost", { + group = x_config, + pattern = { "Xresources", "Xdefaults", "xresources", "xdefaults" }, + callback = function() + vim.cmd("silent !xrdb %") + end, +}) + +-- Recompile suckless programs on config edit. +local suckless_config = vim.api.nvim_create_augroup("suckless_config", { clear = true }) +autocmd("BufWritePost", { + group = suckless_config, + pattern = home .. "/.local/src/suckless/dmenu/config.def.h", + callback = function() + vim.cmd("silent !cd " .. home .. "/.local/src/suckless/dmenu/ && sudo make clean install && rm -f config.h") + end, +}) + +autocmd("BufWritePost", { + group = suckless_config, + pattern = home .. "/.local/src/suckless/dwmblocks/config.def.h", + callback = function() + vim.cmd( + "silent !cd " + .. home + .. "/.local/src/suckless/dwmblocks/ && sudo make clean install && rm -f config.h && { killall -q dwmblocks; setsid -f dwmblocks; }" + ) + end, +}) + +autocmd("BufWritePost", { + group = suckless_config, + pattern = home .. "/.local/src/suckless/slock/config.def.h", + callback = function() + vim.cmd("silent !cd " .. home .. "/.local/src/suckless/slock/ && sudo make clean install && rm -f config.h") + end, +}) + +local suckless_keys = augroup("suckless_keys") +autocmd("BufWritePost", { + group = suckless_keys, + pattern = { home .. "/.local/src/suckless/dwm/config.def.h", home .. "/.local/src/suckless/st/config.def.h" }, + callback = function() + local choice = vim.fn.confirm("Extract key bindings?", "&Yes\n&No", 2) + if choice == 1 then + vim.cmd("silent !" .. home .. "/.local/bin/extractkeys") + end + end, +}) + +autocmd("BufWritePost", { + group = augroup("suckless_doc"), + pattern = home .. "/.local/src/suckless/dwm/thesiah-default.mom", + callback = function() + vim.cmd("silent !cd " .. home .. "/.local/src/suckless/dwm/ && rm -f thesiah.mom") + end, +}) + +autocmd({ "BufRead", "BufEnter" }, { + pattern = { "*.c", "*.cpp", "*.h", "*.hpp" }, + callback = function() + local suckless_path = vim.fn.expand("~/.local/src/suckless"):gsub("/+$", "") + local file_path = vim.fn.expand("%:p"):gsub("/+$", "") + if file_path:sub(1, #suckless_path) == suckless_path then + vim.b.autoformat = false + end + end, +}) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/keymaps.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/keymaps.lua new file mode 100644 index 0000000..7de0645 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/keymaps.lua @@ -0,0 +1,807 @@ +-- Ascii +vim.keymap.set("n", "<leader>a1", ":.!toilet -w 200 -f bfraktur<cr>", { desc = "Ascii art bfraktur" }) +vim.keymap.set("n", "<leader>a2", ":.!toilet -w 200 -f emboss<cr>", { desc = "Ascii art emboss" }) +vim.keymap.set("n", "<leader>a3", ":.!toilet -w 200 -f emboss2<cr>", { desc = "Ascii art emboss2" }) +vim.keymap.set("n", "<leader>a4", ":.!toilet -w 200 -f future<cr>", { desc = "Ascii art future" }) +vim.keymap.set("n", "<leader>a5", ":.!toilet -w 200 -f pagga<cr>", { desc = "Ascii art pagga" }) +vim.keymap.set("n", "<leader>a6", ":.!toilet -w 200 -f wideterm<cr>", { desc = "Ascii art wideterm" }) +vim.keymap.set("n", "<leader>a7", ":.!figlet -w 200 -f standard<cr>", { desc = "Ascii art standard" }) +vim.keymap.set("n", "<leader>a8", ":.!figlet -w 200 -f slant<cr>", { desc = "Ascii art slant" }) +vim.keymap.set("n", "<leader>a9", ":.!figlet -w 200 -f big<cr>", { desc = "Ascii art big" }) +vim.keymap.set("n", "<leader>a0", ":.!figlet -w 200 -f shadow<cr>", { desc = "Ascii art shadow" }) + +-- Buffers +vim.keymap.set({ "n", "v", "x", "t" }, "<A-x>", "<Cmd>bd!<cr>", { desc = "Delete buffer" }) +vim.keymap.set({ "i", "n", "t" }, "<C-p>", "<Cmd>bprevious<cr>", { desc = "Previous buffer" }) +vim.keymap.set({ "i", "n", "t" }, "<C-n>", "<Cmd>bnext<cr>", { desc = "Next buffer" }) +vim.keymap.set("n", "<leader><leader>", "<Cmd>e #<cr>", { desc = "Switch to last buffer" }) +vim.keymap.set({ "n", "v", "x", "t" }, "<leader>bd", "<Cmd>:bd<cr>", { desc = "Close buffer" }) +vim.keymap.set({ "n", "v", "x", "t" }, "<leader>BD", "<Cmd>:bd!<cr>", { desc = "Force close buffer" }) +vim.keymap.set("n", "<leader>bn", "<Cmd>enew<cr>", { desc = "Open new buffer" }) +vim.keymap.set({ "n", "i" }, "<C-z>", function() + if not vim.bo.modified then + return + end + local choice = vim.fn.confirm("Discard changes and reload file?", "&Yes\n&No", 2) + if choice == 1 then + vim.cmd("e!") + end +end, { desc = "Confirm and reload file" }) +vim.keymap.set({ "i", "x", "n", "s" }, "<C-s>", "<Cmd>w<cr><esc>", { desc = "Save current buffer" }) +vim.keymap.set({ "n", "v" }, "<leader>ZZ", "<Cmd>wq<cr>", { desc = "Save current buffer and quit" }) +vim.keymap.set({ "n", "v" }, "<leader>ZA", "<Cmd>wqa<cr>", { desc = "Save all buffers and quit" }) +vim.keymap.set({ "n", "v" }, "<leader>qq", "<Cmd>q!<cr>", { desc = "Force quit" }) +vim.keymap.set({ "n", "v" }, "<leader>QQ", "<Cmd>qa!<cr>", { desc = "Force quit all" }) +vim.keymap.set("n", "<leader>rnf", function() + local current_name = vim.fn.expand("%:p") -- Get the full path of the current file + local directory = vim.fn.expand("%:p:h") -- Get the directory of the current file + local new_name = vim.fn.input("New filename: ", directory .. "/") -- Prompt for the new name + if new_name == "" or new_name == current_name then + return -- Do nothing if no input or name hasn't changed + end + vim.cmd("silent !mv " .. vim.fn.shellescape(current_name) .. " " .. vim.fn.shellescape(new_name)) + vim.cmd("edit " .. vim.fn.fnameescape(new_name)) + vim.cmd("bdelete " .. vim.fn.bufnr(current_name)) +end, { noremap = true, silent = true, desc = "Rename file" }) +vim.keymap.set("n", "<leader>ms", function() + vim.cmd("new | put=execute('messages') | setlocal buftype=nofile") + local buf = vim.api.nvim_get_current_buf() + local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false) + local filtered_lines = {} + for _, line in ipairs(lines) do + local trimmed_line = line:match("^%s*(.-)%s*$") -- Remove leading and trailing whitespace + if trimmed_line ~= "" then + table.insert(filtered_lines, trimmed_line) -- Only add non-empty lines + end + end + vim.fn.setreg('"', table.concat(filtered_lines, "\n")) + vim.api.nvim_buf_set_lines(buf, 0, -1, false, filtered_lines) + vim.keymap.set("n", "q", function() + vim.api.nvim_buf_delete(buf, { force = true }) + end, { buffer = buf, desc = "Close message buffer" }) +end, { desc = "Open messages, trim, and copy content" }) + +-- Cd +vim.keymap.set("n", "gcd", ":cd %:p:h<cr>:pwd<cr>", { desc = "Go to current file path" }) +vim.keymap.set("n", "gcD", function() + local realpath = vim.fn.systemlist("readlink -f " .. vim.fn.shellescape(vim.fn.expand("%:p")))[1] + vim.cmd("cd " .. vim.fn.fnameescape(vim.fn.fnamemodify(realpath, ":h"))) + vim.cmd("pwd") +end, { desc = "Go to real path of current file" }) +vim.keymap.set("n", "gc.", ":cd ..<cr>:pwd<cr>", { desc = "Go to parent file path" }) + +-- Check health +vim.keymap.set("n", "<leader>ch", ":checkhealth<cr>", { desc = "Check neovim health" }) + +-- Clear search with <esc> +vim.keymap.set({ "i", "n" }, "<esc>", "<Cmd>noh<cr><esc>", { desc = "Clear search highlights" }) + +-- Clear search / diff update / redraw +vim.keymap.set( + "n", + "<leader>R", + "<Cmd>nohlsearch<bar>diffupdate<bar>normal! <C-l><cr>", + { desc = "Redraw / Clear hlsearch / Diff Update" } +) + +-- Copy +vim.keymap.set("n", "<leader>cp", function() + local filepath = vim.fn.expand("%") -- Get the current filepath + local filename = vim.fn.expand("%:t") -- Get the current filename + local file_root = vim.fn.expand("%:r") -- Get the file root (without extension) + local file_ext = vim.fn.expand("%:e") -- Get the file extension + local new_filename = file_root .. "_copied" -- Start with the base for new filename + local num = 1 + while vim.fn.filereadable(new_filename .. "." .. file_ext) == 1 do + new_filename = file_root .. "_copied_" .. num + num = num + 1 + end + new_filename = new_filename .. "." .. file_ext + local cmd = "cp " .. filepath .. " " .. new_filename + + -- Wrap input in pcall to handle Ctrl-c interruptions + local ok, confirm = pcall(vim.fn.input, 'Do you want to copy "' .. filename .. '"? (y/n): ') + + -- If interrupted (Ctrl-c), return silently + if not ok or confirm == nil or confirm == "" then + return + end + + -- Handle positive confirmation + if confirm:lower() == "y" or confirm:lower() == "yes" then + vim.cmd("silent !" .. cmd) + vim.cmd("silent edit " .. new_filename) + end +end, { silent = true, desc = "Copy current file" }) +vim.keymap.set( + "n", + "<leader>cP", + ':let @+ = expand("%:p")<cr>:lua print("Copied path to: " .. vim.fn.expand("%:p"))<cr>', + { desc = "Copy current file name and path" } +) + +-- Cut, Yank & Paste +vim.keymap.set({ "n", "v" }, "<leader>y", [["+y]], { desc = "Yank to clipboard" }) +vim.keymap.set("n", "<leader>Y", [["+Y]], { desc = "Yank line to clipboard" }) +vim.keymap.set({ "n", "v" }, "<leader><C-y>", ":%y<cr>", { desc = "Yank current file to clipboard" }) +vim.keymap.set({ "n", "v", "x" }, "<leader>pp", [["+p]], { desc = "Paste from clipboard after cursor" }) +vim.keymap.set({ "n", "v", "x" }, "<leader>PP", [["+P]], { desc = "Paste from clipboard before cursor" }) +vim.keymap.set({ "n", "v", "x" }, "<leader>pP", [["_dP]], { desc = "Paste over and preserve clipboard" }) +vim.keymap.set({ "n", "v" }, "<leader>dd", [["+d]], { desc = "Delete and yank to clipboard" }) +vim.keymap.set({ "n", "v" }, "<leader>DD", [["_d]], { desc = "Delete without storing in clipboard" }) +vim.keymap.set("n", "<leader><C-d>", ":%d_<cr>", { desc = "Delete all lines to black hole register" }) + +-- Diagnostic +local diagnostic_goto = function(next, severity) + local go = next and vim.diagnostic.goto_next or vim.diagnostic.goto_prev + severity = severity and vim.diagnostic.severity[severity] or nil + return function() + go({ severity = severity }) + end +end +-- vim.keymap.set("n", "[d", diagnostic_goto(false), { desc = "Previous diagnostic" }) +-- vim.keymap.set("n", "]d", diagnostic_goto(true), { desc = "Next diagnostic" }) +vim.keymap.set("n", "<leader>[e", diagnostic_goto(false, "ERROR"), { desc = "Previous error" }) +vim.keymap.set("n", "<leader>]e", diagnostic_goto(true, "ERROR"), { desc = "Next error" }) +vim.keymap.set("n", "<leader>[w", diagnostic_goto(false, "WARN"), { desc = "Previous warning" }) +vim.keymap.set("n", "<leader>]w", diagnostic_goto(true, "WARN"), { desc = "Next warning" }) +vim.keymap.set("n", "<leader>od", vim.diagnostic.open_float, { desc = "Open diagnostic message" }) +vim.keymap.set("n", "<leader>la", vim.diagnostic.setloclist, { desc = "Add diagnostics to location list" }) + +-- Disable +vim.keymap.set("n", "Q", "<nop>", { desc = "Disable q command" }) + +-- Explore +vim.keymap.set("n", "<leader>ex", vim.cmd.Ex, { desc = "Open explorer" }) +vim.keymap.set("n", "<leader>es", vim.cmd.Sex, { desc = "Open explorer (horizontal split)" }) +vim.keymap.set("n", "<leader>ev", vim.cmd.Vex, { desc = "Open explorer (vertical split)" }) +vim.keymap.set("n", "<leader>qe", function() + if vim.bo.filetype == "netrw" then + vim.cmd("bd") + end +end, { desc = "Close explorer (netrw)" }) + +-- Fix List & Trouble +vim.keymap.set("n", "[o", "<Cmd>lprev<cr>zz", { desc = "Previous location" }) +vim.keymap.set("n", "]o", "<Cmd>lnext<cr>zz", { desc = "Next location" }) +vim.keymap.set("n", "[q", "<Cmd>cprev<cr>zz", { desc = "Previous quickfix" }) +vim.keymap.set("n", "]q", "<Cmd>cnext<cr>zz", { desc = "Next quickfix" }) +vim.keymap.set( + "n", + "<leader>rw", + [[:%s/\<<C-r><C-w>\>/<C-r><C-w>/gI<Left><Left><Left>]], + { desc = "Search and replace word under cursor" } +) +vim.keymap.set("n", "<leader>oo", "<Cmd>lopen<cr>", { desc = "Open location list" }) +vim.keymap.set("n", "<leader>oq", "<Cmd>copen<cr>", { desc = "Open quickfix list" }) + +-- Formats +vim.keymap.set("n", "<leader>cF", vim.lsp.buf.format, { desc = "Format buffer by default lsp" }) + +-- Full path +vim.keymap.set("n", "<leader>zf", function() + local word = vim.fn.expand("<cWORD>") -- Get full text under the cursor (handles paths with slashes) + if word:match("%$") then + local expanded_path = vim.fn.expand(word) + if expanded_path ~= word then + vim.cmd("normal! ciW" .. expanded_path) -- Replace entire word under cursor + end + end +end, { desc = "Expand and replace path under cursor" }) + +-- Git +-- create repository +vim.keymap.set("n", "<leader>gR", function() + -- Check if GitHub CLI is installed + local gh_installed = vim.fn.system("command -v gh") + if gh_installed == "" then + print("GitHub CLI is not installed. Please install it using 'brew install gh'.") + return + end + -- Get the current working directory and extract the repository name + local cwd = vim.fn.getcwd() + local repo_name = vim.fn.fnamemodify(cwd, ":t") + if repo_name == "" then + print("Failed to extract repository name from the current directory.") + return + end + -- Display the message and ask for confirmation + local confirmation = vim.fn.input('The name of the repo will be: "' .. repo_name .. '"\nType "yes" to continue: ') + if confirmation:lower() ~= "yes" then + print("Operation canceled.") + return + end + -- Check if the repository already exists on GitHub + local check_repo_command = + string.format("gh repo view %s/%s", vim.fn.system("gh api user --jq '.login'"):gsub("%s+", ""), repo_name) + local check_repo_result = vim.fn.systemlist(check_repo_command) + if not string.find(table.concat(check_repo_result), "Could not resolve to a Repository") then + print("Repository '" .. repo_name .. "' already exists on GitHub.") + return + end + -- Prompt for repository type + local repo_type = vim.fn.input("Enter the repository type (private/public): "):lower() + if repo_type ~= "private" and repo_type ~= "public" then + print("Invalid repository type. Please enter 'private' or 'public'.") + return + end + -- Set the repository type flag + local repo_type_flag = repo_type == "private" and "--private" or "--public" + -- Initialize the git repository and create the GitHub repository + local init_command = string.format("cd %s && git init", vim.fn.shellescape(cwd)) + vim.fn.system(init_command) + local create_command = + string.format("cd %s && gh repo create %s %s --source=.", vim.fn.shellescape(cwd), repo_name, repo_type_flag) + local create_result = vim.fn.system(create_command) + -- Print the result of the repository creation command + if string.find(create_result, "https://github.com") then + print("Repository '" .. repo_name .. "' created successfully.") + else + print("Failed to create the repository: " .. create_result) + end +end, { desc = "Create GitHub repository" }) +-- open repository +local function open_github_link(use_root) + -- Get the full path of the current file + local file_path = vim.fn.expand("%:p") + if file_path == "" then + print("No file is currently open") + return + end + + -- Get the Git repository root + local git_root = vim.fn.systemlist("git rev-parse --show-toplevel")[1] + if not git_root or git_root == "" then + print("Could not determine the root directory for the GitHub repository") + return + end + + -- Get the origin URL of the repository + local origin_url = vim.fn.systemlist("git config --get remote.origin.url")[1] + if not origin_url or origin_url == "" then + print("Could not determine the origin URL for the GitHub repository") + return + end + + -- Get the current branch name + local branch_name = vim.fn.systemlist("git rev-parse --abbrev-ref HEAD")[1] + if not branch_name or branch_name == "" then + print("Could not determine the current branch name") + return + end + + -- Convert the origin URL to a GitHub HTTPS URL + local repo_url = origin_url:gsub("git@github.com:", "https://github.com/"):gsub("%.git$", "") + + local github_url + if use_root then + -- Use the root repository URL + github_url = repo_url + else + -- Generate the link for the current file + local relative_path = file_path:sub(#git_root + 2) -- Extract the relative path + github_url = repo_url .. "/blob/" .. branch_name .. "/" .. relative_path + end + + -- Open the URL in the default browser + local command = "xdg-open " .. vim.fn.shellescape(github_url) + vim.fn.system(command) + + -- Print the opened URL + print("Opened GitHub link: " .. github_url) +end + +-- Keybinding for opening the current file link +vim.keymap.set("n", "<leader>go", function() + open_github_link(false) -- Use the current file link +end, { desc = "Open GitHub link for the current file" }) + +-- Keybinding for opening the repository root link +vim.keymap.set("n", "<leader>gO", function() + open_github_link(true) -- Use the root repository URL +end, { desc = "Open GitHub repository root" }) + +-- paste a github link and add it in this format +vim.keymap.set({ "n", "v", "i" }, "<M-;>", function() + -- Insert the text in the desired format + vim.cmd('normal! a[](){:target="_blank"} ') + vim.cmd("normal! F(pv2F/lyF[p") + -- Leave me in normal mode or command mode + vim.cmd("stopinsert") +end, { desc = "Paste github link" }) + +-- Health +vim.keymap.set("n", "<leader>ch", ":checkhealth<cr>", { desc = "Check neovim health" }) + +-- Highlights under cursor +vim.keymap.set("n", "<leader>ip", vim.show_pos, { desc = "Inspect position" }) + +-- Keywordprg +vim.keymap.set("n", "<leader>K", "<Cmd>norm! K<cr>", { desc = "Look up keyword" }) + +-- Lines +-- vim.keymap.set("n", "<A-,>", "<Cmd>m .-2<cr>==", { desc = "Move line up" }) +-- vim.keymap.set("n", "<A-.>", "<Cmd>m .+1<cr>==", { desc = "Move line down" }) +vim.keymap.set( + "i", + "<A-,>", + "<esc><Cmd>m .-2<cr>==gi", + { noremap = true, silent = true, desc = "Move line up in insert mode" } +) +vim.keymap.set( + "i", + "<A-.>", + "<esc><Cmd>m .+1<cr>==gi", + { noremap = true, silent = true, desc = "Move line down in insert mode" } +) +vim.keymap.set("v", "<C-,>", ":m '<-2<cr>gv=gv", { desc = "Move selected lines up" }) +vim.keymap.set("v", "<C-.>", ":m '>+1<cr>gv=gv", { desc = "Move selected lines down" }) + +-- Markdown +vim.keymap.set({ "n", "v" }, "gk", function() + -- `?` - Start a search backwards from the current cursor position. + -- `^` - Match the beginning of a line. + -- `##` - Match 2 ## symbols + -- `\\+` - Match one or more occurrences of prev element (#) + -- `\\s` - Match exactly one whitespace character following the hashes + -- `.*` - Match any characters (except newline) following the space + -- `$` - Match extends to end of line + vim.cmd("silent! ?^##\\+\\s.*$") + -- Clear the search highlight + vim.cmd("nohlsearch") +end, { desc = "Go to previous markdown header" }) +vim.keymap.set({ "n", "v" }, "gj", function() + -- `/` - Start a search forwards from the current cursor position. + -- `^` - Match the beginning of a line. + -- `##` - Match 2 ## symbols + -- `\\+` - Match one or more occurrences of prev element (#) + -- `\\s` - Match exactly one whitespace character following the hashes + -- `.*` - Match any characters (except newline) following the space + -- `$` - Match extends to end of line + vim.cmd("silent! /^##\\+\\s.*$") + -- Clear the search highlight + vim.cmd("nohlsearch") +end, { desc = "Go to next markdown header" }) + +-- Marks +vim.keymap.set("n", "<leader>mD", function() + -- Delete all marks in the current buffer + vim.cmd("delmarks!") + print("All marks deleted.") +end, { desc = "Delete all marks" }) + +-- Ownerships +vim.keymap.set("n", "<leader>zx", "<Cmd>!chmod +x %<cr>", { silent = true, desc = "Make file executable" }) + +-- Remap Default +vim.keymap.set("i", "jk", "<esc>", { noremap = true, silent = true, desc = "Escape to normal mode" }) +vim.keymap.set("n", "<C-c>", ":", { noremap = true, desc = "Enter command mode" }) +vim.keymap.set("n", "J", "mzJ`z", { noremap = true, desc = "Join lines and keep cursor position" }) +vim.keymap.set("n", "n", "'Nn'[v:searchforward].'zv'", { expr = true, desc = "Next search result and center" }) +vim.keymap.set("x", "n", "'Nn'[v:searchforward]", { expr = true, desc = "Next search result in visual mode" }) +vim.keymap.set("o", "n", "'Nn'[v:searchforward]", { expr = true, desc = "Next search result in operator-pending mode" }) +vim.keymap.set("n", "N", "'nN'[v:searchforward].'zv'", { expr = true, desc = "Previous search result and center" }) +vim.keymap.set("x", "N", "'nN'[v:searchforward]", { expr = true, desc = "Previous search result in visual mode" }) +vim.keymap.set( + "o", + "N", + "'nN'[v:searchforward]", + { expr = true, desc = "Previous search result in operator-pending mode" } +) +vim.keymap.set("n", "x", '"_x', { desc = "Delete character without yanking" }) +local scroll_percentage = 0.50 +vim.keymap.set("n", "<C-d>", function() + local lines = math.floor(vim.api.nvim_win_get_height(0) * scroll_percentage) + vim.cmd("normal! " .. lines .. "jzz") +end, { noremap = true, silent = true, desc = "Scroll down and center" }) +vim.keymap.set("n", "<C-u>", function() + local lines = math.floor(vim.api.nvim_win_get_height(0) * scroll_percentage) + vim.cmd("normal! " .. lines .. "kzz") +end, { noremap = true, silent = true, desc = "Scroll up and center" }) +-- vim.keymap.set("n", "<C-d>", "<C-d>zz", { noremap = true, silent = true, desc = "Scroll down and center" }) +-- vim.keymap.set("n", "<C-u>", "<C-u>zz", { noremap = true, silent = true, desc = "Scroll up and center" }) +-- vim.keymap.set("n", "<C-b>", "<C-b>zz", { noremap = true, silent = true, desc = "Page up and center" }) +-- vim.keymap.set("n", "<C-f>", "<C-f>zz", { noremap = true, silent = true, desc = "Page down and center" }) +vim.keymap.set("n", "{", "{zz", { noremap = true, silent = true, desc = "Move to previous paragraph and center" }) +vim.keymap.set("n", "}", "}zz", { noremap = true, silent = true, desc = "Move to next paragraph and center" }) +vim.keymap.set("n", "G", "Gzz", { noremap = true, silent = true, desc = "Go to bottom of file and center" }) +vim.keymap.set("n", "gg", "ggzz", { noremap = true, silent = true, desc = "Go to top of file and center" }) +vim.keymap.set("n", "gd", "gdzz", { noremap = true, silent = true, desc = "Go to definition and center" }) +vim.keymap.set("n", "<C-i>", "<C-i>zz", { noremap = true, silent = true, desc = "Jump forward in jumplist and center" }) +vim.keymap.set( + "n", + "<C-o>", + "<C-o>zz", + { noremap = true, silent = true, desc = "Jump backward in jumplist and center" } +) +vim.keymap.set( + "n", + "%", + "%zz", + { noremap = true, silent = true, desc = "Jump to matching pair (e.g. brackets) and center" } +) +vim.keymap.set( + "n", + "*", + "*zz", + { noremap = true, silent = true, desc = "Search for next occurrence of word under cursor and center" } +) +vim.keymap.set( + "n", + "#", + "#zz", + { noremap = true, silent = true, desc = "Search for previous occurrence of word under cursor and center" } +) + +vim.keymap.set( + { "n", "x" }, + "j", + "v:count == 0 ? 'gj' : 'j'", + { expr = true, silent = true, desc = "Move down (visual line)" } +) +vim.keymap.set( + { "n", "x" }, + "<down>", + "v:count == 0 ? 'gj' : 'j'", + { expr = true, silent = true, desc = "Move down (visual line)" } +) +vim.keymap.set( + { "n", "x" }, + "k", + "v:count == 0 ? 'gk' : 'k'", + { expr = true, silent = true, desc = "Move up (visual line)" } +) +vim.keymap.set( + { "n", "x" }, + "<up>", + "v:count == 0 ? 'gk' : 'k'", + { expr = true, silent = true, desc = "Move up (visual line)" } +) +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("v", "J", ":m '>+1<cr>gv=gv", { desc = "Move line down in visual mode" }) +vim.keymap.set("v", "K", ":m '<-2<cr>gv=gv", { desc = "Move line up in visual mode" }) +vim.keymap.set("n", "sl", "vg_", { desc = "Select to end of line" }) +vim.keymap.set("n", "sp", "ggVGp", { desc = "Select all and paste" }) +vim.keymap.set("n", "sv", "ggVG", { desc = "Select all" }) +vim.keymap.set("n", "gp", "`[v`]", { desc = "Select pasted text" }) +vim.keymap.set("n", "ss", ":s/\\v", { desc = "Search and replace on line" }) +vim.keymap.set("n", "SS", ":%s/\\v", { desc = "Search and replace in file" }) +vim.keymap.set("v", "<leader><C-s>", ":s/\\%V", { desc = "Search only in visual selection using %V atom" }) +vim.keymap.set("v", "<C-r>", '"hy:%s/\\v<C-r>h//g<left><left>', { desc = "Change selection" }) + +-- Remove +local function delete_current_file() + local filepath = vim.fn.expand("%:p") + local filename = vim.fn.expand("%:t") -- Get the current filename + if filepath and filepath ~= "" then + -- Check if trash utility is installed + if vim.fn.executable("trash") == 0 then + vim.api.nvim_echo({ + { "- Trash utility not installed. Make sure to install it first\n", "ErrorMsg" }, + { "- Install `trash-cli`\n", nil }, + }, false, {}) + return + end + -- Prompt for confirmation before deleting the file + vim.ui.input({ + prompt = 'Do you want to delete "' .. filename .. '"? (y/n): ', + }, function(input) + if input == nil then + return + end + + if input:lower() == "y" or input:lower() == "yes" then + -- Delete the file using trash app + local success, _ = pcall(function() + vim.fn.system({ "trash", vim.fn.fnameescape(filepath) }) + end) + if success then + vim.api.nvim_echo({ + { "File deleted from disk:\n", "Normal" }, + { filepath, "Normal" }, + }, false, {}) + -- Close the buffer after deleting the file + vim.cmd("bd!") + else + vim.api.nvim_echo({ + { "Failed to delete file:\n", "ErrorMsg" }, + { filepath, "ErrorMsg" }, + }, false, {}) + end + else + vim.api.nvim_echo({ + { "File deletion canceled.", "Normal" }, + }, false, {}) + end + end) + else + vim.api.nvim_echo({ + { "No file to delete", "WarningMsg" }, + }, false, {}) + end +end + +vim.keymap.set("n", "<leader>rm", function() + delete_current_file() +end, { desc = "Remove current file" }) + +-- Scripts +vim.keymap.set("n", "<leader>rr", function() + vim.cmd("w") + local file = vim.fn.shellescape(vim.fn.expand("%:p")) + vim.cmd("split | resize 10 | terminal compiler " .. file) +end, { noremap = true, silent = true, desc = "Run compiler interactively" }) +vim.api.nvim_set_keymap( + "n", + "<leader>RR", + ":!opout <C-r>%<cr><cr>", + { noremap = true, silent = true, desc = "Docs viewer" } +) + +-- Source +-- source nvim config +vim.keymap.set("n", "<leader>SO", function() + vim.cmd("so") +end, { desc = "Source current file" }) +-- reload zsh configuration by sourcing ~/.config/zsh/.zshrc in a separate shell +vim.keymap.set("n", "<leader>SZ", function() + -- Define the command to source zshrc + local command = "source ~/.config/zsh/.zshrc" + -- Execute the command in a new Zsh shell + local full_command = "zsh -c '" .. command .. "'" + -- Run the command and capture the output + local output = vim.fn.system(full_command) + -- Check the exit status of the command + local exit_code = vim.v.shell_error + if exit_code == 0 then + vim.api.nvim_echo({ { "Successfully sourced ~/.config/zsh/.zshrc", "NormalMsg" } }, false, {}) + else + vim.api.nvim_echo({ + { "Failed to source ~/.config/zsh/.zshrc:", "ErrorMsg" }, + { output, "ErrorMsg" }, + }, false, {}) + end +end, { desc = "Source zshrc" }) +-- source shortcuts from bm-files and bm-folders +local shortcuts_file = vim.fn.expand("~/.config/nvim/shortcuts.lua") +local file = io.open(shortcuts_file, "r") +if file then + file:close() + vim.cmd("silent! source " .. shortcuts_file) +end + +-- Spell +vim.keymap.set("n", "zp", function() + vim.opt.spelllang = { "en", "ko", "cjk" } + vim.cmd("echo 'Spell language set to English, Korean, and CJK'") +end, { desc = "Spelling language English, Korean, and CJK" }) +-- repeat the replacement done by |z=| for all matches with the replaced word in the current window. +vim.keymap.set("n", "z.", function() + vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes(":spellr\n", true, false, true), "m", true) +end, { desc = "Spelling repeat" }) + +-- Sudo +vim.keymap.set("n", "<leader>SW", "<Cmd>SudoWrite<cr><cr>", { silent = true, desc = "Save file with sudo" }) +vim.keymap.set("n", "<leader>SWQ", "<Cmd>SudoWritequit<cr>", { silent = true, desc = "Save and quit with sudo" }) + +-- Surround +vim.keymap.set("n", "sau", function() + local line = vim.api.nvim_get_current_line() + local col = vim.api.nvim_win_get_cursor(0)[2] + 1 -- Adjust for 0-index in Lua + -- This makes the `s` optional so it matches both http and https + local pattern = "https?://[^ ,;'\"<>%s)]*" + -- Find the starting and ending positions of the URL + local s, e = string.find(line, pattern) + while s and e do + if s <= col and e >= col then + -- When the cursor is within the URL + local url = string.sub(line, s, e) + -- Update the line with backticks around the URL + local new_line = string.sub(line, 1, s - 1) .. "`" .. url .. "`" .. string.sub(line, e + 1) + vim.api.nvim_set_current_line(new_line) + vim.cmd("silent write") + return + end + -- Find the next URL in the line + s, e = string.find(line, pattern, e + 1) + -- Save the file to update trouble list + end + print("No URL found under cursor") +end, { desc = "Add surrounding to URL" }) +vim.keymap.set("v", "<leader>bl", function() + -- Get the selected text range + local start_row, start_col = unpack(vim.fn.getpos("'<"), 2, 3) + local end_row, end_col = unpack(vim.fn.getpos("'>"), 2, 3) + -- Get the selected lines + local lines = vim.api.nvim_buf_get_lines(0, start_row - 1, end_row, false) + local selected_text = table.concat(lines, "\n"):sub(start_col, #lines == 1 and end_col or -1) + if selected_text:match("^%*%*.*%*%*$") then + vim.notify("Text already bold", vim.log.levels.INFO) + else + vim.cmd("normal 2gsa*") + end +end, { desc = "Bold current selection" }) +vim.keymap.set("n", "gbd", function() + local cursor_pos = vim.api.nvim_win_get_cursor(0) + local current_buffer = vim.api.nvim_get_current_buf() + local start_row = cursor_pos[1] - 1 + local col = cursor_pos[2] + -- Get the current line + local line = vim.api.nvim_buf_get_lines(current_buffer, start_row, start_row + 1, false)[1] + -- Check if the cursor is on an asterisk + if line:sub(col + 1, col + 1):match("%*") then + vim.notify("Cursor is on an asterisk, run inside the bold text", vim.log.levels.WARN) + return + end + -- Search for '**' to the left of the cursor position + local left_text = line:sub(1, col) + local bold_start = left_text:reverse():find("%*%*") + if bold_start then + bold_start = col - bold_start + end + -- Search for '**' to the right of the cursor position and in following lines + local right_text = line:sub(col + 1) + local bold_end = right_text:find("%*%*") + local end_row = start_row + while not bold_end and end_row < vim.api.nvim_buf_line_count(current_buffer) - 1 do + end_row = end_row + 1 + local next_line = vim.api.nvim_buf_get_lines(current_buffer, end_row, end_row + 1, false)[1] + if next_line == "" then + break + end + right_text = right_text .. "\n" .. next_line + bold_end = right_text:find("%*%*") + end + if bold_end then + bold_end = col + bold_end + end + -- Remove '**' markers if found, otherwise bold the word + if bold_start and bold_end then + -- Extract lines + local text_lines = vim.api.nvim_buf_get_lines(current_buffer, start_row, end_row + 1, false) + local text = table.concat(text_lines, "\n") + -- Calculate positions to correctly remove '**' + -- vim.notify("bold_start: " .. bold_start .. ", bold_end: " .. bold_end) + local new_text = text:sub(1, bold_start - 1) .. text:sub(bold_start + 2, bold_end - 1) .. text:sub(bold_end + 2) + local new_lines = vim.split(new_text, "\n") + -- Set new lines in buffer + vim.api.nvim_buf_set_lines(current_buffer, start_row, end_row + 1, false, new_lines) + -- vim.notify("Unbolded text", vim.log.levels.INFO) + else + -- Bold the word at the cursor position if no bold markers are found + local before = line:sub(1, col) + local after = line:sub(col + 1) + local inside_surround = before:match("%*%*[^%*]*$") and after:match("^[^%*]*%*%*") + if inside_surround then + vim.cmd("normal gsd*.") + else + vim.cmd("normal viw") + vim.cmd("normal 2gsa*") + end + vim.notify("Bolded current word", vim.log.levels.INFO) + end +end, { desc = "Toggle bold" }) + +-- Tab +vim.keymap.set("n", "<leader><tab>l", "<Cmd>tablast<cr>", { desc = "Last Tab" }) +vim.keymap.set("n", "]]<tab>", "<Cmd>tablast<cr>", { desc = "Last Tab" }) +vim.keymap.set("n", "<leader><tab>o", "<Cmd>tabonly<cr>", { desc = "Close Other Tabs" }) +vim.keymap.set("n", "<leader><tab>f", "<Cmd>tabfirst<cr>", { desc = "First Tab" }) +vim.keymap.set("n", "[[<tab>", "<Cmd>tabfirst<cr>", { desc = "First Tab" }) +vim.keymap.set("n", "<leader><tab><tab>", "<Cmd>tabnew<cr>", { desc = "New Tab" }) +vim.keymap.set("n", "<leader><tab>n", "<Cmd>tabnext<cr>", { desc = "Next Tab" }) +vim.keymap.set("n", "]<tab>", "<Cmd>tabnext<cr>", { desc = "Next Tab" }) +vim.keymap.set("n", "<leader><tab>d", "<Cmd>tabclose<cr>", { desc = "Close Tab" }) +vim.keymap.set("n", "<leader><tab>p", "<Cmd>tabprevious<cr>", { desc = "Previous Tab" }) +vim.keymap.set("n", "[<tab>", "<Cmd>tabprevious<cr>", { desc = "Previous Tab" }) + +-- Terminal +vim.keymap.set("n", "<leader>te", "<Cmd>term<cr>", { desc = "Open terminal" }) +vim.keymap.set("n", "<leader>t-", "<Cmd>sp term://zsh | startinsert<cr>", { desc = "Split terminal (horizontal)" }) +vim.keymap.set("n", "<leader>t|", "<Cmd>vsp term://zsh | startinsert<cr>", { desc = "Split terminal (vertical)" }) +vim.keymap.set("t", "<esc><esc>", "<C-\\><C-n>", { desc = "Escape terminal mode" }) +vim.keymap.set("t", "<C-h>", "<Cmd>wincmd h<cr>", { desc = "Move to left window" }) +vim.keymap.set("t", "<C-j>", "<Cmd>wincmd j<cr>", { desc = "Move to window below" }) +vim.keymap.set("t", "<C-k>", "<Cmd>wincmd k<cr>", { desc = "Move to window above" }) +vim.keymap.set("t", "<C-l>", "<Cmd>wincmd l<cr>", { desc = "Move to right window" }) +vim.keymap.set("t", "<C-Space>l", "clear<cr>", { silent = true, desc = "Clear terminal" }) +vim.keymap.set("t", "<C-\\>", "<C-\\><C-n>iexit<cr>", { desc = "Close terminal" }) +vim.keymap.set("t", "<C-/>", "<Cmd>close<cr>", { desc = "Close terminal" }) +vim.keymap.set("t", "<C-_>", "<Cmd>close<cr>", { desc = "Close terminal" }) + +-- Tmux +if vim.env.TMUX then + vim.keymap.set( + "n", + "<leader>tm", + "<Cmd>silent !~/.config/tmux/plugins/tmux-fzf/scripts/session.sh<cr>", + { desc = "Find tmux session" } + ) + vim.keymap.set("n", "<leader>RS", function() + vim.fn.system("restartnvim") + end, { noremap = true, silent = true, desc = "Restart nvim (tmux)" }) +end + +-- Todo +-- detect todos and toggle between ":" and ";", or show a message if not found +-- this is to "mark them as done" +vim.keymap.set("n", "<leader>td", function() + -- Get the current line + local current_line = vim.fn.getline(".") + -- Get the current line number + local line_number = vim.fn.line(".") + if string.find(current_line, "TODO:") then + -- Replace the first occurrence of ":" with ";" + local new_line = current_line:gsub("TODO:", "TODO;") + -- Set the modified line + vim.fn.setline(line_number, new_line) + elseif string.find(current_line, "TODO;") then + -- Replace the first occurrence of ";" with ":" + local new_line = current_line:gsub("TODO;", "TODO:") + -- Set the modified line + vim.fn.setline(line_number, new_line) + else + vim.cmd("echo 'todo item not detected'") + end +end, { desc = "Toggle TODO item done or not" }) + +-- Windows +vim.keymap.set("n", "<C-h>", "<C-w><C-h>", { desc = "Move to left window" }) +vim.keymap.set("n", "<C-j>", "<C-w><C-j>", { desc = "Move to window below" }) +vim.keymap.set("n", "<C-k>", "<C-w><C-k>", { desc = "Move to window above" }) +vim.keymap.set("n", "<C-l>", "<C-w><C-l>", { desc = "Move to right window" }) +-- vim.keymap.set("n", "<C-up>", "<Cmd>resize +2<cr>", { desc = "Increase window height" }) +-- vim.keymap.set("n", "<C-down>", "<Cmd>resize -2<cr>", { desc = "Decrease window height" }) +-- vim.keymap.set("n", "<C-left>", "<Cmd>vertical resize -2<cr>", { desc = "Decrease window width" }) +-- vim.keymap.set("n", "<C-right>", "<Cmd>vertical resize +2<cr>", { desc = "Increase window width" }) + +function WordDefinition(input) + -- Function to run the dict command and return its output + local function get_output(word) + local escaped_word = vim.fn.shellescape(word) + return vim.fn.system("dict " .. escaped_word) + end + + -- Function to process the word for singular/plural handling + local function get_definition(word) + -- Attempt to derive the singular form + local singular = word + if word:sub(-2) == "es" then + singular = word:sub(1, -3) -- Remove 'es' + elseif word:sub(-1) == "s" then + singular = word:sub(1, -2) -- Remove 's' + end + + -- Fetch output for both singular and original word + local singular_output = get_output(singular) + local original_output = get_output(word) + + -- Determine which output to prioritize + if singular ~= word and not vim.startswith(singular_output, "No definitions found") then + return singular_output -- Use singular if valid and different + else + return original_output -- Otherwise, use the original word + end + end + + -- Get the definition and output for the word + local output = get_definition(input) + + -- Create a new buffer and display the result + local bufnr = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_current_buf(bufnr) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.split(output, "\n")) +end +vim.api.nvim_set_keymap( + "n", + "<leader>k", + ":lua WordDefinition(vim.fn.expand('<cword>'))<cr>", + { noremap = true, silent = true, desc = "Word definition" } +) + +-- Lazy +vim.keymap.set("n", "<leader>L", "<Cmd>Lazy<cr>", { desc = "Open lazy plugin manager" }) + +-- Mason +vim.keymap.set("n", "<leader>M", "<Cmd>Mason<cr>", { desc = "Open mason" }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/lazy.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/lazy.lua new file mode 100644 index 0000000..802a3a5 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/lazy.lua @@ -0,0 +1,257 @@ +-- Bootstrap lazy.nvim +local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim" +if not (vim.uv or vim.loop).fs_stat(lazypath) then + local lazyrepo = "https://github.com/folke/lazy.nvim.git" + local out = vim.fn.system({ "git", "clone", "--filter=blob:none", "--branch=stable", lazyrepo, lazypath }) + if vim.v.shell_error ~= 0 then + vim.api.nvim_echo({ + { "Failed to clone lazy.nvim:\n", "ErrorMsg" }, + { out, "WarningMsg" }, + { "\nPress any key to exit..." }, + }, true, {}) + vim.fn.getchar() + os.exit(1) + end +end +vim.opt.rtp:prepend(lazypath) + +-- Make sure to setup `mapleader` and `maplocalleader` before +-- loading lazy.nvim so that mappings are correct. +-- This is also a good place to setup other settings (vim.opt) +-- vim.g.mapleader = " " +-- vim.g.maplocalleader = "\\" + +-- Setup lazy.nvim +require("lazy").setup({ + root = vim.fn.stdpath("data") .. "/lazy", -- directory where plugins will be installed + defaults = { + -- Set this to `true` to have all your plugins lazy-loaded by default. + -- Only do this if you know what you are doing, as it can lead to unexpected behavior. + lazy = false, -- should plugins be lazy-loaded? + -- It's recommended to leave version=false for now, since a lot the plugin that support versioning, + -- have outdated releases, which may break your Neovim install. + version = nil, -- always use the latest git commit + -- version = "*", -- try installing the latest stable version for plugins that support semver + -- default `cond` you can use to globally disable a lot of plugins + -- when running inside vscode for example + cond = nil, ---@type boolean|fun(self:LazyPlugin):boolean|nil + }, + -- leave nil when passing the spec as the first argument to setup() + -- highlight-start + spec = { + -- import your plugins + { import = "TheSiahxyz.plugins" }, + }, + local_spec = true, -- load project specific .lazy.lua spec files. They will be added at the end of the spec. + lockfile = vim.fn.stdpath("config") .. "/lazy-lock.json", -- lockfile generated after running update. + ---@type number? limit the maximum amount of concurrent tasks + concurrency = jit.os:find("Windows") and (vim.uv.available_parallelism() * 2) or nil, + git = { + -- defaults for the `Lazy log` command + -- log = { "--since=3 days ago" }, -- show commits from the last 3 days + log = { "-8" }, -- show the last 8 commits + timeout = 120, -- kill processes that take more than 2 minutes + url_format = "https://github.com/%s.git", + -- lazy.nvim requires git >=2.19.0. If you really want to use lazy with an older version, + -- then set the below to false. This should work, but is NOT supported and will + -- increase downloads a lot. + filter = true, + -- rate of network related git operations (clone, fetch, checkout) + throttle = { + enabled = false, -- not enabled by default + -- max 2 ops every 5 seconds + rate = 2, + duration = 5 * 1000, -- in ms + }, + -- Time in seconds to wait before running fetch again for a plugin. + -- Repeated update/check operations will not run again until this + -- cooldown period has passed. + cooldown = 0, + }, + pkg = { + enabled = true, + cache = vim.fn.stdpath("state") .. "/lazy/pkg-cache.lua", + -- the first package source that is found for a plugin will be used. + sources = { + "lazy", + "rockspec", -- will only be used when rocks.enabled is true + "packspec", + }, + }, + rocks = { + enabled = true, + root = vim.fn.stdpath("data") .. "/lazy-rocks", + server = "https://lumen-oss.github.io/rocks-binaries/", + -- use hererocks to install luarocks? + -- set to `nil` to use hererocks when luarocks is not found + -- set to `true` to always use hererocks + -- set to `false` to always use luarocks + hererocks = nil, + }, + dev = { + -- Directory where you store your local plugin projects. If a function is used, + -- the plugin directory (e.g. `~/projects/plugin-name`) must be returned. + ---@type string | fun(plugin: LazyPlugin): string + path = "~/projects", + ---@type string[] plugins that match these patterns will use your local versions instead of being fetched from GitHub + patterns = {}, -- For example {"folke"} + fallback = false, -- Fallback to git when local plugin doesn't exist + }, + install = { + -- install missing plugins on startup. This doesn't increase startup time. + missing = true, + -- try to load one of these colorschemes when starting an installation during startup + colorscheme = { "catppuccin" }, + }, + ui = { + -- a number <1 is a percentage., >1 is a fixed size + size = { width = 0.8, height = 0.8 }, + wrap = true, -- wrap the lines in the ui + -- The border to use for the UI window. Accepts same border values as |nvim_open_win()|. + border = "none", + -- The backdrop opacity. 0 is fully opaque, 100 is fully transparent. + backdrop = 60, + title = nil, ---@type string only works when border is not "none" + title_pos = "center", ---@type "center" | "left" | "right" + -- Show pills on top of the Lazy window + pills = true, ---@type boolean + icons = { + cmd = " ", + config = "", + debug = "● ", + event = " ", + favorite = " ", + ft = " ", + init = " ", + import = " ", + keys = " ", + lazy = " ", + loaded = "●", + not_loaded = "○", + plugin = " ", + runtime = " ", + require = " ", + source = " ", + start = " ", + task = "✔ ", + list = { + "●", + "➜", + "★", + "‒", + }, + }, + -- leave nil, to automatically select a browser depending on your OS. + -- If you want to use a specific browser, you can define it here + browser = nil, ---@type string? + throttle = 1000 / 30, -- how frequently should the ui process render events + custom_keys = { + -- You can define custom key maps here. If present, the description will + -- be shown in the help menu. + -- To disable one of the defaults, set it to false. + + ["<leader>gL"] = { + function(plugin) + require("lazy.util").float_term({ "lazygit", "log" }, { + cwd = plugin.dir, + }) + end, + desc = "Open lazygit log", + }, + + ["<leader>is"] = { + function(plugin) + Util.notify(vim.inspect(plugin), { + title = "Inspect " .. plugin.name, + lang = "lua", + }) + end, + desc = "Inspect Plugin", + }, + + ["<leader><C-p>"] = { + function(plugin) + require("lazy.util").float_term(nil, { + cwd = plugin.dir, + }) + end, + desc = "Open terminal in plugin dir", + }, + }, + }, + -- Output options for headless mode + headless = { + -- show the output from process commands like git + process = true, + -- show log messages + log = true, + -- show task start/end + task = true, + -- use ansi colors + colors = true, + }, + diff = { + -- diff command <d> can be one of: + -- * browser: opens the github compare view. Note that this is always mapped to <K> as well, + -- so you can have a different command for diff <d> + -- * git: will run git diff and open a buffer with filetype git + -- * terminal_git: will open a pseudo terminal with git diff + -- * diffview.nvim: will open Diffview to show the diff + cmd = "git", + }, + checker = { + -- automatically check for plugin updates + enabled = false, + concurrency = nil, ---@type number? set to 1 to check for updates very slowly + notify = true, -- get a notification when new updates are found + frequency = 3600, -- check for updates every hour + check_pinned = false, -- check for pinned packages that can't be updated + }, + change_detection = { + -- automatically check for config file changes and reload the ui + enabled = false, + notify = false, -- get a notification when changes are found + }, + performance = { + cache = { + enabled = true, + }, + reset_packpath = true, -- reset the package path to improve startup time + rtp = { + reset = true, -- reset the runtime path to $VIMRUNTIME and your config directory + ---@type string[] + paths = {}, -- add any custom paths here that you want to includes in the rtp + ---@type string[] list any plugins you want to disable here + disabled_plugins = { + -- "gzip", + -- "matchit", + -- "matchparen", + -- "netrwPlugin", + -- "tarPlugin", + -- "tohtml", + -- "tutor", + -- "zipPlugin", + }, + }, + }, + -- lazy can generate helptags from the headings in markdown readme files, + -- so :help works even for plugins that don't have vim docs. + -- when the readme opens with :help it will be correctly displayed as markdown + readme = { + enabled = true, + root = vim.fn.stdpath("state") .. "/lazy/readme", + files = { "README.md", "lua/**/README.md" }, + -- only generate markdown helptags for plugins that don't have docs + skip_if_doc_exists = true, + }, + state = vim.fn.stdpath("state") .. "/lazy/state.json", -- state info for checker and other things + -- Enable profiling of lazy.nvim. This will add some overhead, + -- so only enable this when you are debugging lazy.nvim + profiling = { + -- Enables extra stats on the debug tab related to the loader cache. + -- Additionally gathers stats about all package.loaders + loader = false, + -- Track each new require in the Lazy profiling tab + require = false, + }, +}) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/options.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/options.lua new file mode 100644 index 0000000..a4b373f --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/core/options.lua @@ -0,0 +1,48 @@ +vim.g.have_nerd_font = true +-- vim.g.netrw_browse_split = 0 +-- vim.g.netrw_banner = 1 +-- vim.g.netrw_browsex_viewer = "xdg-open" +-- vim.g.netrw_liststyle = 0 +-- vim.g.netrw_list_hide = "^.git" +-- vim.g.netrw_winsize = 25 +-- vim.g.loaded_netrw = 1 +-- vim.g.loaded_netrwPlugin = 1 +vim.g.mapleader = " " +vim.g.maplocalleader = "\\" +vim.o.sessionoptions = "blank,buffers,curdir,folds,help,tabpages,winsize,winpos,terminal,localoptions" +vim.opt.backup = false +vim.opt.breakindent = true +vim.opt.conceallevel = 1 +vim.opt.cursorline = true +vim.opt.encoding = "utf-8" +vim.opt.expandtab = true +vim.opt.fileencoding = "utf-8" +vim.opt.hlsearch = true +vim.opt.ignorecase = true +vim.opt.inccommand = "split" +vim.opt.incsearch = true +vim.opt.isfname:append("@-@") +vim.opt.list = true +vim.opt.listchars = { tab = " ", trail = " ", nbsp = " " } +vim.opt.mouse = "a" +vim.opt.number = true +vim.opt.relativenumber = true +vim.opt.scrolloff = 8 +vim.opt.shiftwidth = 2 +vim.opt.showmode = false +vim.opt.signcolumn = "yes" +vim.opt.smartcase = true +vim.opt.smartindent = true +vim.opt.softtabstop = 2 +vim.opt.spell = false +vim.opt.spellfile = vim.fn.stdpath("config") .. "/spell/en.utf-8.add" +vim.opt.splitbelow = true +vim.opt.splitright = true +vim.opt.swapfile = false +vim.opt.tabstop = 2 +vim.opt.termguicolors = true +vim.opt.timeoutlen = 300 +vim.opt.updatetime = 300 +vim.opt.undofile = true +vim.opt.undodir = os.getenv("HOME") .. "/.local/share/history/vim_history" +vim.opt.wrap = false diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/health.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/health.lua new file mode 100644 index 0000000..b2cbba2 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/health.lua @@ -0,0 +1,60 @@ +local start = vim.health.start or vim.health.report_start +local ok = vim.health.ok or vim.health.report_ok +local warn = vim.health.warn or vim.health.report_warn +local error = vim.health.error or vim.health.report_error + +local check_version = function() + local version = vim.version() + local verstr = ("%d.%d.%d"):format(version.major, version.minor, version.patch) + + if not vim.version.cmp then + error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr)) + return + end + + if vim.version.cmp(vim.version(), { 0, 10, 0 }) >= 0 then + ok(string.format("Neovim version is: '%s'", verstr)) + else + error(string.format("Neovim out of date: '%s'. Upgrade to latest stable or nightly", verstr)) + end +end + +local check_external_reqs = function() + for _, cmd in ipairs({ "git", "make", "unzip", "rg", { "fd", "fdfind" }, "lazygit", "fzf", "curl" }) do + local name = type(cmd) == "string" and cmd or vim.inspect(cmd) + local commands = type(cmd) == "string" and { cmd } or cmd + ---@cast commands string[] + local found = false + + for _, c in ipairs(commands) do + if vim.fn.executable(c) == 1 then + name = c + found = true + end + end + + if found then + ok(("`%s` is installed"):format(name)) + else + warn(("`%s` is not installed"):format(name)) + end + end +end + +return { + check = function() + start("TheSiahxyz") + + vim.health.info([[NOTE: Not every warning is a 'must-fix' in `:checkhealth` + + Fix only warnings for plugins and languages you intend to use. + Mason will give warnings for languages that are not installed. + You do not need to install, unless you want to use those languages!]]) + + local uv = vim.uv or vim.loop + vim.health.info("System Information: " .. vim.inspect(uv.os_uname())) + + check_version() + check_external_reqs() + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/init.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/init.lua new file mode 100644 index 0000000..58a3470 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/init.lua @@ -0,0 +1,15 @@ +-- Core +require("TheSiahxyz.core.options") +require("TheSiahxyz.core.keymaps") +require("TheSiahxyz.core.autocmds") +require("TheSiahxyz.core.lazy") + +-- Custom +for _, file in ipairs(vim.fn.readdir(vim.fn.stdpath("config") .. "/lua/TheSiahxyz/utils", [[v:val =~ '\.lua$']])) do + require("TheSiahxyz.utils." .. file:gsub("%.lua$", "")) +end + +-- Plenary +function R(name) + require("plenary.reload").reload_module(name) +end diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua new file mode 100644 index 0000000..6ff4ac6 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua @@ -0,0 +1,901 @@ +return { + { + "ravitemer/mcphub.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + }, + build = "npm install -g mcp-hub@latest", -- Installs `mcp-hub` node binary globally + config = function() + local mcphub = require("mcphub") + mcphub.setup({ + --- `mcp-hub` binary related options------------------- + config = vim.fn.expand("~/.config/mcphub/servers.json"), -- Absolute path to MCP Servers config file (will create if not exists) + port = 37373, -- The port `mcp-hub` server listens to + shutdown_delay = 5 * 60 * 000, -- Delay in ms before shutting down the server when last instance closes (default: 5 minutes) + use_bundled_binary = false, -- Use local `mcp-hub` binary (set this to true when using build = "bundled_build.lua") + mcp_request_timeout = 60000, --Max time allowed for a MCP tool or resource to execute in milliseconds, set longer for long running tasks + global_env = {}, -- Global environment variables available to all MCP servers (can be a table or a function returning a table) + workspace = { + enabled = true, -- Enable project-local configuration files + look_for = { ".mcphub/servers.json", ".vscode/mcp.json", ".cursor/mcp.json" }, -- Files to look for when detecting project boundaries (VS Code format supported) + reload_on_dir_changed = true, -- Automatically switch hubs on DirChanged event + port_range = { min = 40000, max = 41000 }, -- Port range for generating unique workspace ports + get_port = nil, -- Optional function returning custom port number. Called when generating ports to allow custom port assignment logic + }, + + ---Chat-plugin related options----------------- + auto_approve = function(params) + -- Auto-approve GitHub issue reading + if params.server_name == "github" and params.tool_name == "get_issue" then + return true -- Auto approve + end + + -- Block access to private repos + if params.arguments.repo == "private" then + return "You can't access my private repo" -- Error message + end + + -- Auto-approve safe file operations in current project + if params.tool_name == "read_file" then + local path = params.arguments.path or "" + if path:match("^" .. vim.fn.getcwd()) then + return true -- Auto approve + end + end + + -- Check if tool is configured for auto-approval in servers.json + if params.is_auto_approved_in_server then + return true -- Respect servers.json configuration + end + + return false -- Show confirmation prompt + end, -- Auto approve mcp tool calls + auto_toggle_mcp_servers = true, -- Let LLMs start and stop MCP servers automatically + extensions = { + avante = { + make_slash_commands = true, -- make /slash commands from MCP server prompts + }, + }, + + --- Plugin specific options------------------- + native_servers = {}, -- add your custom lua native servers here + builtin_tools = { + edit_file = { + parser = { + track_issues = true, + extract_inline_content = true, + }, + locator = { + fuzzy_threshold = 0.8, + enable_fuzzy_matching = true, + }, + ui = { + go_to_origin_on_complete = true, + keybindings = { + accept = ".", + reject = ",", + next = "n", + prev = "p", + accept_all = "ga", + reject_all = "gr", + }, + }, + }, + }, + ui = { + window = { + width = 0.8, -- 0-1 (ratio); "50%" (percentage); 50 (raw number) + height = 0.8, -- 0-1 (ratio); "50%" (percentage); 50 (raw number) + align = "center", -- "center", "top-left", "top-right", "bottom-left", "bottom-right", "top", "bottom", "left", "right" + relative = "editor", + zindex = 50, + border = "rounded", -- "none", "single", "double", "rounded", "solid", "shadow" + }, + wo = { -- window-scoped options (vim.wo) + winhl = "Normal:MCPHubNormal,FloatBorder:MCPHubBorder", + }, + }, + json_decode = nil, -- Custom JSON parser function (e.g., require('json5').parse for JSON5 support) + on_ready = function(hub) + -- Called when hub is ready + end, + on_error = function(err) + -- Called on errors + end, + log = { + level = vim.log.levels.WARN, + to_file = false, + file_path = nil, + prefix = "MCPHub", + }, + }) + + -- LSP diagnostics as a resource + mcphub.add_resource("neovim", { + name = "Diagnostics: Current File", + description = "Get diagnostics for the current file", + uri = "neovim://diagnostics/current", + mimeType = "text/plain", + handler = function(req, res) + -- Get active buffer + local buf_info = req.editor_info.last_active + if not buf_info then + return res:error("No active buffer") + end + + -- Get diagnostics + local diagnostics = vim.diagnostic.get(buf_info.bufnr) + + -- Format header + local text = string.format("Diagnostics for: %s\n%s\n", buf_info.filename, string.rep("-", 40)) + + -- Format diagnostics + for _, diag in ipairs(diagnostics) do + local severity = vim.diagnostic.severity[diag.severity] + text = text + .. string.format( + "\n%s: %s\nLine %d: %s\n", + severity, + diag.source or "unknown", + diag.lnum + 1, + diag.message + ) + end + + return res:text(text):send() + end, + }) + + mcphub.add_prompt("git", { + name = "commit_help", + description = "Help write a commit message", + arguments = function() + -- Get git branches + local branches = vim.fn.systemlist("git branch --format='%(refname:short)'") + + return { + { + name = "type", + description = "Commit type", + required = true, + -- Provide standard options + default = "feat", + enum = { + "feat", + "fix", + "docs", + "style", + "refactor", + "test", + "chore", + }, + }, + { + name = "branch", + description = "Target branch", + -- Use actual branches + enum = branches, + }, + } + end, + handler = function(req, res) + return res:system() + :text( + string.format("Help write a %s commit for branch: %s", req.params.type, req.params.branch) + ) + :send() + end, + }) + + mcphub.add_prompt("editor", { + name = "review_code", + arguments = { + { + name = "style", + description = "Review style", + enum = { "brief", "detailed" }, + }, + }, + handler = function(req, res) + -- Get current buffer + local buf = req.editor_info.last_active + if not buf then + return res:error("No active buffer") + end + + -- Generate code overview + local overview = generate_overview(buf) + + return res + -- Set review context + :system() + :text("You are a code reviewer.\n" .. "Style: " .. req.params.style) + -- Add code visualization + :image(overview, "image/png") + :text("Above is a visualization of the code structure.") + -- Add relevant resources + :resource({ + uri = "neovim://diagnostics/current", + mimeType = "text/plain", + }) + :text("Above are the current diagnostics.") + -- Send prompt + :send() + end, + }) + + mcphub.add_prompt("context", { + name = "explain_code", + handler = function(req, res) + -- Start with base behavior + res:system():text("You are a code explanation assistant.") + + -- Add context based on caller + if req.caller.type == "codecompanion" then + -- Add CodeCompanion chat context + local chat = req.caller.codecompanion.chat + res:text("\nPrevious discussion:\n" .. chat.history) + elseif req.caller.type == "avante" then + -- Add Avante code context + local code = req.caller.avante.code + res:text("\nSelected code:\n" .. code) + end + + -- Add example interactions + res:user():text("Explain this code"):llm():text("I'll explain the code in detail...") + + return res:send() + end, + }) + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>mc", group = "MCP" }, + }) + end, + keys = { + { "<leader>mcp", ":MCPHub<CR>", desc = "MCP Hub" }, + }, + }, + { + "kkrampis/codex.nvim", + lazy = true, + cmd = { "Codex", "CodexToggle" }, -- Optional: Load only on command execution + keys = { + { + "<leader>cd", -- Change this to your preferred keybinding + function() + require("codex").toggle() + end, + desc = "Toggle Codex popup or side-panel", + mode = { "n", "t" }, + }, + }, + opts = { + keymaps = { + toggle = nil, -- Keybind to toggle Codex window (Disabled by default, watch out for conflicts) + quit = "<C-q>", -- Keybind to close the Codex window (default: Ctrl + q) + }, -- Disable internal default keymap (<leader>cc -> :CodexToggle) + border = "rounded", -- Options: 'single', 'double', or 'rounded' + width = 0.8, -- Width of the floating window (0.0 to 1.0) + height = 0.8, -- Height of the floating window (0.0 to 1.0) + model = nil, -- Optional: pass a string to use a specific model (e.g., 'o3-mini') + autoinstall = true, -- Automatically install the Codex CLI if not found + panel = false, -- Open Codex in a side-panel (vertical split) instead of floating window + use_buffer = false, -- Capture Codex stdout into a normal buffer instead of a terminal buffer + }, + }, + { + "yetone/avante.nvim", + -- if you want to build from source then do `make BUILD_FROM_SOURCE=true` + -- ⚠️ must add this setting! ! ! + build = vim.fn.has("win32") ~= 0 + and "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false" + or "make", + event = "VeryLazy", + version = false, -- Never set this value to "*"! Never! + dependencies = { + "ravitemer/mcphub.nvim", + "nvim-lua/plenary.nvim", + "MunifTanjim/nui.nvim", + --- The below dependencies are optional, + -- "echasnovski/mini.pick", -- for file_selector provider mini.pick + -- "nvim-telescope/telescope.nvim", -- for file_selector provider telescope + -- "hrsh7th/nvim-cmp", -- autocompletion for avante commands and mentions + -- "ibhagwan/fzf-lua", -- for file_selector provider fzf + -- "stevearc/dressing.nvim", -- for input provider dressing + -- "folke/snacks.nvim", -- for input provider snacks + -- "nvim-tree/nvim-web-devicons", -- or echasnovski/mini.icons + -- "zbirenbaum/copilot.lua", -- for providers='copilot' + { + -- support for image pasting + "HakonHarnes/img-clip.nvim", + event = "VeryLazy", + opts = { + -- recommended settings + default = { + embed_image_as_base64 = false, + prompt_for_file_name = false, + drag_and_drop = { + insert_mode = true, + }, + -- required for Windows users + use_absolute_path = true, + }, + }, + }, + { + -- Make sure to set this up properly if you have lazy=true + "MeanderingProgrammer/render-markdown.nvim", + opts = { + file_types = { "markdown", "Avante" }, + }, + ft = { "markdown", "Avante" }, + }, + }, + config = function() + require("avante").setup({ + instructions_file = "avante.md", + ---@alias Provider "claude" | "openai" | "azure" | "gemini" | "cohere" | "copilot" | string + ---@type Provider + provider = "openai", -- The provider used in Aider mode or in the planning phase of Cursor Planning Mode + ---@alias Mode "agentic" | "legacy" + ---@type Mode + mode = "agentic", -- The default mode for interaction. "agentic" uses tools to automatically generate code, "legacy" uses the old planning method to generate code. + -- WARNING: Since auto-suggestions are a high-frequency operation and therefore expensive, + -- currently designating it as `copilot` provider is dangerous because: https://github.com/yetone/avante.nvim/issues/1048 + -- Of course, you can reduce the request frequency by increasing `suggestion.debounce`. + auto_suggestions_provider = "claude", + providers = { + claude = { + endpoint = "https://api.anthropic.com", + model = "claude-sonnet-4-20250514", + timeout = 30000, -- Timeout in milliseconds + extra_request_body = { + temperature = 0.75, + max_tokens = 20480, + }, + }, + openai = { + endpoint = "https://api.openai.com/v1", -- The LLM API endpoint + model = "gpt-5", + timeout = 30000, + extra = { + temperature = 0.7, + max_tokens = 20480, + }, + }, + moonshot = { + endpoint = "https://api.moonshot.ai/v1", + model = "kimi-k2-0711-preview", + timeout = 30000, -- Timeout in milliseconds + extra_request_body = { + temperature = 0.75, + max_tokens = 32768, + }, + }, + }, + acp_providers = { + ["gemini-cli"] = { + command = "gemini", + args = { "--experimental-acp" }, + env = { + NODE_NO_WARNINGS = "1", + GEMINI_API_KEY = os.getenv("GEMINI_API_KEY"), + }, + }, + ["claude-code"] = { + command = "npx", + args = { "@zed-industries/claude-code-acp" }, + env = { + NODE_NO_WARNINGS = "1", + ANTHROPIC_API_KEY = os.getenv("ANTHROPIC_API_KEY"), + }, + }, + ["goose"] = { + command = "goose", + args = { "acp" }, + }, + ["codex"] = { + command = "codex-acp", + env = { + NODE_NO_WARNINGS = "1", + OPENAI_API_KEY = os.getenv("OPENAI_API_KEY"), + }, + }, + }, + ---Specify the special dual_boost mode + ---1. enabled: Whether to enable dual_boost mode. Default to false. + ---2. first_provider: The first provider to generate response. Default to "openai". + ---3. second_provider: The second provider to generate response. Default to "claude". + ---4. prompt: The prompt to generate response based on the two reference outputs. + ---5. timeout: Timeout in milliseconds. Default to 60000. + ---How it works: + --- When dual_boost is enabled, avante will generate two responses from the first_provider and second_provider respectively. Then use the response from the first_provider as provider1_output and the response from the second_provider as provider2_output. Finally, avante will generate a response based on the prompt and the two reference outputs, with the default Provider as normal. + ---Note: This is an experimental feature and may not work as expected. + dual_boost = { + enabled = false, + first_provider = "openai", + second_provider = "claude", + prompt = "Based on the two reference outputs below, generate a response that incorporates elements from both but reflects your own judgment and unique perspective. Do not provide any explanation, just give the response directly. Reference Output 1: [{{provider1_output}}], Reference Output 2: [{{provider2_output}}]", + timeout = 60000, -- Timeout in milliseconds + }, + behaviour = { + auto_suggestions = false, -- Experimental stage + auto_set_highlight_group = true, + auto_set_keymaps = true, + auto_apply_diff_after_generation = false, + support_paste_from_clipboard = false, + minimize_diff = true, -- Whether to remove unchanged lines when applying a code block + enable_token_counting = true, -- Whether to enable token counting. Default to true. + auto_approve_tool_permissions = false, -- Default: show permission prompts for all tools + -- Examples: + -- auto_approve_tool_permissions = true, -- Auto-approve all tools (no prompts) + -- auto_approve_tool_permissions = {"bash", "replace_in_file"}, -- Auto-approve specific tools only + }, + prompt_logger = { -- logs prompts to disk (timestamped, for replay/debugging) + enabled = true, -- toggle logging entirely + log_dir = vim.fn.stdpath("cache") .. "/avante_prompts", -- directory where logs are saved + fortune_cookie_on_success = false, -- shows a random fortune after each logged prompt (requires `fortune` installed) + next_prompt = { + normal = "<C-n>", -- load the next (newer) prompt log in normal mode + insert = "<C-n>", + }, + prev_prompt = { + normal = "<C-p>", -- load the previous (older) prompt log in normal mode + insert = "<C-p>", + }, + }, + mappings = { + --- @class AvanteConflictMappings + diff = { + ours = "co", + theirs = "ct", + all_theirs = "ca", + both = "cb", + cursor = "cc", + next = "]x", + prev = "[x", + }, + suggestion = { + accept = "<M-l>", + next = "<M-]>", + prev = "<M-[>", + dismiss = "<C-]>", + }, + jump = { + next = "]]", + prev = "[[", + }, + submit = { + normal = "<CR>", + insert = "<C-s>", + }, + cancel = { + normal = { "<C-c>", "<Esc>", "q" }, + insert = { "<C-c>" }, + }, + sidebar = { + apply_all = "A", + apply_cursor = "a", + retry_user_request = "r", + edit_user_request = "e", + switch_windows = "<Tab>", + reverse_switch_windows = "<S-Tab>", + remove_file = "d", + add_file = "@", + close = { "<Esc>", "q" }, + close_from_input = nil, -- e.g., { normal = "<Esc>", insert = "<C-d>" } + }, + }, + selection = { + enabled = true, + hint_display = "delayed", + }, + windows = { + ---@type "right" | "left" | "top" | "bottom" + position = "right", -- the position of the sidebar + wrap = true, -- similar to vim.o.wrap + width = 30, -- default % based on available width + sidebar_header = { + enabled = true, -- true, false to enable/disable the header + align = "center", -- left, center, right for title + rounded = true, + }, + spinner = { + editing = { + "⡀", + "⠄", + "⠂", + "⠁", + "⠈", + "⠐", + "⠠", + "⢀", + "⣀", + "⢄", + "⢂", + "⢁", + "⢈", + "⢐", + "⢠", + "⣠", + "⢤", + "⢢", + "⢡", + "⢨", + "⢰", + "⣰", + "⢴", + "⢲", + "⢱", + "⢸", + "⣸", + "⢼", + "⢺", + "⢹", + "⣹", + "⢽", + "⢻", + "⣻", + "⢿", + "⣿", + }, + generating = { "·", "✢", "✳", "∗", "✻", "✽" }, -- Spinner characters for the 'generating' state + thinking = { "🤯", "🙄" }, -- Spinner characters for the 'thinking' state + }, + input = { + prefix = "> ", + height = 8, -- Height of the input window in vertical layout + }, + edit = { + border = "rounded", + start_insert = true, -- Start insert mode when opening the edit window + }, + ask = { + floating = false, -- Open the 'AvanteAsk' prompt in a floating window + start_insert = true, -- Start insert mode when opening the ask window + border = "rounded", + ---@type "ours" | "theirs" + focus_on_apply = "ours", -- which diff to focus after applying + }, + }, + highlights = { + ---@type AvanteConflictHighlights + diff = { + current = "DiffText", + incoming = "DiffAdd", + }, + }, + --- @class AvanteConflictUserConfig + diff = { + autojump = true, + ---@type string | fun(): any + list_opener = "copen", + --- Override the 'timeoutlen' setting while hovering over a diff (see :help timeoutlen). + --- Helps to avoid entering operator-pending mode with diff mappings starting with `c`. + --- Disable by setting to -1. + override_timeoutlen = 500, + }, + suggestion = { + debounce = 600, + throttle = 600, + }, + system_prompt = function() + local hub = require("mcphub").get_hub_instance() + return hub and hub:get_active_servers_prompt() or "" + end, + -- Using function prevents requiring mcphub before it's loaded + custom_tools = function() + return { + require("mcphub.extensions.avante").mcp_tool(), + } + end, + }) + end, + keys = { + { + "<leader>ae", + function() + require("avante.api").edit() + end, + desc = "avante: edit", + mode = { "n", "v" }, + }, + { + "<leader>ai", + function() + return vim.bo.filetype == "AvanteInput" and require("avante.clipboard").paste_image() + or require("img-clip").paste_image() + end, + desc = "clip: paste image", + }, + }, + }, + -- { + -- "robitx/gp.nvim", + -- init = function() + -- local wk = require("which-key") + -- wk.add({ + -- mode = { "n", "v", "x" }, + -- { "<leader>G", group = "GPT" }, + -- { "<leader>Gg", group = "Gp" }, + -- { "<leader>GW", group = "Whisper" }, + -- }) + -- end, + -- config = function() + -- local function keymapOptions(desc) + -- return { + -- noremap = true, + -- silent = true, + -- nowait = true, + -- desc = desc, + -- } + -- end + -- + -- local conf = { + -- -- For customization, refer to Install > Configuration in the Documentation/Readme + -- -- openai_api_key = { "pass", "show", "api/chatGPT/nvim" }, + -- openai_api_key = { "pass", "show", "api/chatGPT/nvim" }, + -- providers = { + -- openai = { + -- disable = false, + -- endpoint = "https://api.openai.com/v1/chat/completions", + -- -- secret = { "pass", "show", "api/chatGPT/nvim" }, + -- }, + -- }, + -- hooks = { + -- -- GpInspectPlugin provides a detailed inspection of the plugin state + -- InspectPlugin = function(plugin, params) + -- local bufnr = vim.api.nvim_create_buf(false, true) + -- local copy = vim.deepcopy(plugin) + -- local key = copy.config.openai_api_key or "" + -- copy.config.openai_api_key = key:sub(1, 3) .. string.rep("*", #key - 6) .. key:sub(-3) + -- local plugin_info = string.format("Plugin structure:\n%s", vim.inspect(copy)) + -- local params_info = string.format("Command params:\n%s", vim.inspect(params)) + -- local lines = vim.split(plugin_info .. "\n" .. params_info, "\n") + -- vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) + -- vim.api.nvim_win_set_buf(0, bufnr) + -- end, + -- + -- -- GpInspectLog for checking the log file + -- InspectLog = function(plugin, params) + -- local log_file = plugin.config.log_file + -- local buffer = plugin.helpers.get_buffer(log_file) + -- if not buffer then + -- vim.cmd("e " .. log_file) + -- else + -- vim.cmd("buffer " .. buffer) + -- end + -- end, + -- + -- -- GpImplement rewrites the provided selection/range based on comments in it + -- Implement = function(gp, params) + -- local template = "Having following from {{filename}}:\n\n" + -- .. "```{{filetype}}\n{{selection}}\n```\n\n" + -- .. "Please rewrite this according to the contained instructions." + -- .. "\n\nRespond exclusively with the snippet that should replace the selection above." + -- + -- local agent = gp.get_command_agent() + -- gp.logger.info("Implementing selection with agent: " .. agent.name) + -- + -- gp.Prompt( + -- params, + -- gp.Target.rewrite, + -- agent, + -- template, + -- nil, -- command will run directly without any prompting for user input + -- nil -- no predefined instructions (e.g. speech-to-text from Whisper) + -- ) + -- end, + -- + -- -- your own functions can go here, see README for more examples like + -- -- :GpExplain, :GpUnitTests.., :GpTranslator etc. + -- + -- -- example of making :%GpChatNew a dedicated command which + -- -- opens new chat with the entire current buffer as a context + -- BufferChatNew = function(gp, _) + -- -- call GpChatNew command in range mode on whole buffer + -- vim.api.nvim_command("%" .. gp.config.cmd_prefix .. "ChatNew") + -- end, + -- + -- -- example of adding command which opens new chat dedicated for translation + -- Translator = function(gp, params) + -- local chat_system_prompt = "You are a Translator, please translate between English and Korean." + -- gp.cmd.ChatNew(params, chat_system_prompt) + -- + -- -- -- you can also create a chat with a specific fixed agent like this: + -- -- local agent = gp.get_chat_agent("ChatGPT4o") + -- -- gp.cmd.ChatNew(params, chat_system_prompt, agent) + -- end, + -- + -- -- example of adding command which writes unit tests for the selected code + -- UnitTests = function(gp, params) + -- local template = "I have the following code from {{filename}}:\n\n" + -- .. "```{{filetype}}\n{{selection}}\n```\n\n" + -- .. "Please respond by writing table driven unit tests for the code above." + -- local agent = gp.get_command_agent() + -- gp.Prompt(params, gp.Target.enew, agent, template) + -- end, + -- + -- -- example of adding command which explains the selected code + -- Explain = function(gp, params) + -- local template = "I have the following code from {{filename}}:\n\n" + -- .. "```{{filetype}}\n{{selection}}\n```\n\n" + -- .. "Please respond by explaining the code above." + -- local agent = gp.get_chat_agent() + -- gp.Prompt(params, gp.Target.popup, agent, template) + -- end, + -- + -- -- example of usig enew as a function specifying type for the new buffer + -- CodeReview = function(gp, params) + -- local template = "I have the following code from {{filename}}:\n\n" + -- .. "```{{filetype}}\n{{selection}}\n```\n\n" + -- .. "Please analyze for code smells and suggest improvements." + -- local agent = gp.get_chat_agent() + -- gp.Prompt(params, gp.Target.enew("markdown"), agent, template) + -- end, + -- }, + -- } + -- require("gp").setup(conf) + -- + -- -- Setup shortcuts here (see Usage > Shortcuts in the Documentation/Readme) + -- vim.keymap.set("n", "<leader>Gc", "<Cmd>GpChatNew<cr>", keymapOptions("New chat")) + -- vim.keymap.set("n", "<leader>Gb", "<Cmd>GpBufferChatNew<cr>", keymapOptions("New buffer chat")) + -- vim.keymap.set("n", "<leader>Gt", "<Cmd>GpChatToggle<cr>", keymapOptions("Toggle chat")) + -- vim.keymap.set("n", "<leader>Gf", "<Cmd>GpChatFinder<cr>", keymapOptions("Chat finder")) + -- + -- vim.keymap.set("v", "<leader>Gc", ":<C-u>'<,'>GpChatNew<cr>", keymapOptions("Chat new")) + -- vim.keymap.set("v", "<leader>Gb", ":<C-u>'<,'>GpBufferChatNew<cr>", keymapOptions("Buffer chat new")) + -- vim.keymap.set("v", "<leader>Gp", ":<C-u>'<,'>GpChatPaste<cr>", keymapOptions("Chat paste")) + -- vim.keymap.set("v", "<leader>Gt", ":<C-u>'<,'>GpChatToggle<cr>", keymapOptions("Toggle chat")) + -- + -- vim.keymap.set("n", "<leader>Gh", "<Cmd>gpchatnew split<cr>", keymapOptions("New chat split")) + -- vim.keymap.set("n", "<leader>Gv", "<Cmd>gpchatnew vsplit<cr>", keymapOptions("New chat vsplit")) + -- vim.keymap.set("n", "<leader>Gn", "<Cmd>gpchatnew tabnew<cr>", keymapOptions("New chat tabnew")) + -- + -- vim.keymap.set("v", "<leader>Gh", ":<C-u>'<,'>GpChatNew split<cr>", keymapOptions("Chat new split")) + -- vim.keymap.set("v", "<leader>Gv", ":<C-u>'<,'>GpChatNew vsplit<cr>", keymapOptions("Chat new vsplit")) + -- vim.keymap.set("v", "<leader>Gn", ":<C-u>'<,'>GpChatNew tabnew<cr>", keymapOptions("Chat new tabnew")) + -- + -- -- Prompt commands + -- vim.keymap.set("n", "<leader>Gw", "<Cmd>GpRewrite<cr>", keymapOptions("Inline rewrite")) + -- vim.keymap.set("n", "<leader>Gr", "<Cmd>GpCodeReview<cr>", keymapOptions("Code review")) + -- vim.keymap.set("n", "<leader>G]", "<Cmd>GpAppend<cr>", keymapOptions("Append (after)")) + -- vim.keymap.set("n", "<leader>G[", "<Cmd>GpPrepend<cr>", keymapOptions("Prepend (before)")) + -- + -- vim.keymap.set("v", "<leader>Gw", ":<C-u>'<,'>GpRewrite<cr>", keymapOptions("Rewrite")) + -- vim.keymap.set("v", "<leader>Gr", ":<C-u>'<,'>GpCodeReview<cr>", keymapOptions("Code review")) + -- vim.keymap.set("v", "<leader>G]", ":<C-u>'<,'>GpAppend<cr>", keymapOptions("Append (after)")) + -- vim.keymap.set("v", "<leader>G[", ":<C-u>'<,'>GpPrepend<cr>", keymapOptions("Prepend (before)")) + -- vim.keymap.set("v", "<leader>Gi", ":<C-u>'<,'>GpImplement<cr>", keymapOptions("Implement selection")) + -- + -- vim.keymap.set("n", "<leader>Ggp", "<Cmd>GpPopup<cr>", keymapOptions("Popup")) + -- vim.keymap.set("n", "<leader>Gge", "<Cmd>GpEnew<cr>", keymapOptions("GpEnew")) + -- vim.keymap.set("n", "<leader>Ggc", "<Cmd>GpNew<cr>", keymapOptions("GpNew")) + -- vim.keymap.set("n", "<leader>Ggv", "<Cmd>GpVnew<cr>", keymapOptions("GpVnew")) + -- vim.keymap.set("n", "<leader>Ggn", "<Cmd>GpTabnew<cr>", keymapOptions("GpTabnew")) + -- + -- vim.keymap.set("v", "<leader>Ggp", ":<C-u>'<,'>GpPopup<cr>", keymapOptions("Popup")) + -- vim.keymap.set("v", "<leader>Gge", ":<C-u>'<,'>GpEnew<cr>", keymapOptions("GpEnew")) + -- vim.keymap.set("v", "<leader>Ggc", ":<C-u>'<,'>GpNew<cr>", keymapOptions("GpNew")) + -- vim.keymap.set("v", "<leader>Ggv", ":<C-u>'<,'>GpVnew<cr>", keymapOptions("GpVnew")) + -- vim.keymap.set("v", "<leader>Ggn", ":<C-u>'<,'>GpTabnew<cr>", keymapOptions("GpTabnew")) + -- + -- vim.keymap.set("n", "<leader>Gx", "<Cmd>GpContext<cr>", keymapOptions("Toggle context")) + -- vim.keymap.set("v", "<leader>Gx", ":<C-u>'<,'>GpContext<cr>", keymapOptions("Toggle context")) + -- + -- vim.keymap.set({ "n", "v", "x" }, "<leader>Ggs", "<Cmd>GpStop<cr>", keymapOptions("Stop")) + -- vim.keymap.set({ "n", "v", "x" }, "<leader>Gg]", "<Cmd>GpNextAgent<cr>", keymapOptions("Next agent")) + -- + -- -- optional Whisper commands with prefix <C-g>w + -- vim.keymap.set("n", "<leader>GWw", "<Cmd>GpWhisper<cr>", keymapOptions("Whisper")) + -- vim.keymap.set("v", "<leader>GWw", ":<C-u>'<,'>GpWhisper<cr>", keymapOptions("Whisper")) + -- + -- vim.keymap.set("n", "<leader>GWr", "<Cmd>GpWhisperRewrite<cr>", keymapOptions("Inline rewrite")) + -- vim.keymap.set("n", "<leader>GW]", "<Cmd>GpWhisperAppend<cr>", keymapOptions("Append (after)")) + -- vim.keymap.set("n", "<leader>GW[", "<Cmd>GpWhisperPrepend<cr>", keymapOptions("Prepend (before) ")) + -- + -- vim.keymap.set("v", "<leader>GWr", ":<C-u>'<,'>GpWhisperRewrite<cr>", keymapOptions("Rewrite")) + -- vim.keymap.set("v", "<leader>GW]", ":<C-u>'<,'>GpWhisperAppend<cr>", keymapOptions("Append (after)")) + -- vim.keymap.set("v", "<leader>GW[", ":<C-u>'<,'>GpWhisperPrepend<cr>", keymapOptions("Prepend (before)")) + -- + -- vim.keymap.set("n", "<leader>GWp", "<Cmd>GpWhisperPopup<cr>", keymapOptions("Popup")) + -- vim.keymap.set("n", "<leader>GWe", "<Cmd>GpWhisperEnew<cr>", keymapOptions("Enew")) + -- vim.keymap.set("n", "<leader>GWc", "<Cmd>GpWhisperNew<cr>", keymapOptions("New")) + -- vim.keymap.set("n", "<leader>GWv", "<Cmd>GpWhisperVnew<cr>", keymapOptions("Vnew")) + -- vim.keymap.set("n", "<leader>GWn", "<Cmd>GpWhisperTabnew<cr>", keymapOptions("Tabnew")) + -- + -- vim.keymap.set("v", "<leader>GWp", ":<C-u>'<,'>GpWhisperPopup<cr>", keymapOptions("Popup")) + -- vim.keymap.set("v", "<leader>GWe", ":<C-u>'<,'>GpWhisperEnew<cr>", keymapOptions("Enew")) + -- vim.keymap.set("v", "<leader>GWc", ":<C-u>'<,'>GpWhisperNew<cr>", keymapOptions("New")) + -- vim.keymap.set("v", "<leader>GWv", ":<C-u>'<,'>GpWhisperVnew<cr>", keymapOptions("Vnew")) + -- vim.keymap.set("v", "<leader>GWn", ":<C-u>'<,'>GpWhisperTabnew<cr>", keymapOptions("Tabnew")) + -- end, + -- }, + -- { + -- "zbirenbaum/copilot.lua", + -- cmd = "Copilot", + -- build = ":Copilot auth", + -- event = "InsertEnter", + -- dependencies = { + -- "hrsh7th/nvim-cmp", + -- { "AndreM222/copilot-lualine" }, + -- { + -- "zbirenbaum/copilot-cmp", + -- config = function() + -- require("copilot_cmp").setup() + -- end, + -- }, + -- }, + -- config = function() + -- require("copilot").setup({ + -- panel = { + -- enabled = true, + -- auto_refresh = true, + -- keymap = { + -- jump_prev = "[a", + -- jump_next = "]a", + -- accept = "<CR>", + -- refresh = "gr", + -- open = "<C-CR>", + -- }, + -- layout = { + -- position = "right", -- | top | left | right + -- ratio = 0.4, + -- }, + -- }, + -- suggestion = { + -- enabled = true, + -- auto_trigger = true, + -- hide_during_completion = true, + -- debounce = 75, + -- keymap = { + -- accept = "<C-q>", + -- accept_word = false, + -- accept_line = false, + -- next = "<C-n>", + -- prev = "<C-p>", + -- dismiss = "<C-\\>", + -- }, + -- }, + -- filetypes = { + -- cvs = false, + -- gitcommit = false, + -- gitrebase = false, + -- help = true, + -- hgcommit = false, + -- markdown = true, + -- sh = function() + -- if string.match(vim.fs.basename(vim.api.nvim_buf_get_name(0)), "^%.env.*") then + -- -- disable for .env files + -- return false + -- end + -- return true + -- end, + -- svn = false, + -- yaml = false, + -- ["."] = false, + -- ["*"] = true, + -- }, + -- copilot_node_command = "node", -- Node.js version must be > 18.x + -- server_opts_overrides = {}, + -- }) + -- + -- local cmp = require("cmp") + -- cmp.event:on("menu_opened", function() + -- vim.b.copilot_suggestion_hidden = true + -- end) + -- + -- cmp.event:on("menu_closed", function() + -- vim.b.copilot_suggestion_hidden = false + -- end) + -- end, + -- + -- vim.keymap.set("n", "<leader>ct", function() + -- require("copilot.suggestion").toggle_auto_trigger() + -- end, { noremap = true, silent = true, desc = "Toggle copilot" }), + -- }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cloak.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cloak.lua new file mode 100644 index 0000000..29c94c0 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cloak.lua @@ -0,0 +1,42 @@ +return { + "laytan/cloak.nvim", + lazy = false, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>c", group = "Cloak" }, + }) + end, + config = function() + require("cloak").setup({ + enabled = true, + cloak_character = "*", + -- The applied highlight group (colors) on the cloaking, see `:h highlight`. + highlight_group = "Comment", + patterns = { + { + -- Match any file starting with ".env". + -- This can be a table to match multiple file patterns. + file_pattern = { + ".env*", + "wrangler.toml", + ".dev.vars", + "address*", + "*api*", + }, + -- Match an equals sign and any character after it. + -- This can also be a table of patterns to cloak, + -- example: cloak_pattern = { ":.+", "-.+" } for yaml files. + cloak_pattern = { "=.+", ":.+", "-.+" }, + }, + }, + }) + end, + keys = { + { "<leader>ce", "<Cmd>CloakEnable<cr>", desc = "Enable cloak" }, + { "<leader>cx", "<Cmd>CloakDisable<cr>", desc = "Disable cloak" }, + { "<leader>cl", "<Cmd>CloakPreviewLine<cr>", desc = "Preview line cloak" }, + { "<leader>zC", "<Cmd>CloakToggle<cr>", desc = "Toggle cloak" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cmp.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cmp.lua new file mode 100644 index 0000000..2dd46f3 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/cmp.lua @@ -0,0 +1,331 @@ +local trigger_text = ";" + +return { + { + "hrsh7th/nvim-cmp", + event = "InsertEnter", + dependencies = { + "hrsh7th/cmp-buffer", -- source for text in buffer + "hrsh7th/cmp-path", -- source for file system paths + "hrsh7th/cmp-cmdline", -- source for cmd + "hrsh7th/cmp-vsnip", + "hrsh7th/vim-vsnip", + { + "L3MON4D3/LuaSnip", + version = "v2.*", -- Replace <CurrentMajor> by the latest released major (first number of latest release) + build = "make install_jsregexp", + }, + "saadparwaiz1/cmp_luasnip", -- for autocompletion + "rafamadriz/friendly-snippets", -- useful snippets + "onsails/lspkind.nvim", -- vs-code like pictograms + "uga-rosa/cmp-dictionary", -- dictionary & spell + }, + config = function() + local cmp = require("cmp") + local luasnip = require("luasnip") + local has_words_before = function() + unpack = unpack or table.unpack + local line, col = unpack(vim.api.nvim_win_get_cursor(0)) + return col ~= 0 + and vim.api.nvim_buf_get_lines(0, line - 1, line, true)[1]:sub(col, col):match("%s") == nil + end + + require("luasnip.loaders.from_vscode").lazy_load() + + cmp.setup({ + completion = { + completeopt = "menu,menuone,preview,noselect", + }, + snippet = { -- configure how nvim-cmp interacts with snippet engine + expand = function(args) + require("luasnip").lsp_expand(args.body) + end, + }, + mapping = cmp.mapping.preset.insert({ + ["<C-p>"] = cmp.mapping.select_prev_item(), -- previous suggestion + ["<C-n>"] = cmp.mapping.select_next_item(), -- next suggestion + ["<C-d>"] = cmp.mapping.scroll_docs(-4), + ["<C-u>"] = cmp.mapping.scroll_docs(4), + ["<C-Space>"] = cmp.mapping.complete(), -- show completion suggestions + ["<C-x>"] = cmp.mapping.abort(), -- close completion window + ["<C-c>"] = cmp.mapping.close(), + ["<CR>"] = cmp.mapping.confirm({ + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }), + ["<Tab>"] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + -- You could replace the expand_or_jumpable() calls with expand_or_locally_jumpable() + -- this way you will only jump inside the snippet region + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + elseif has_words_before() then + cmp.complete() + else + fallback() + end + end, { "i", "s" }), + ["<S-Tab>"] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }), + -- sources for autocompletion + sources = cmp.config.sources({ + { name = "buffer" }, -- text within current buffer + { name = "crates" }, + { name = "copilot" }, + { name = "dictionary", keyword_length = 2 }, + { name = "emoji" }, + { name = "luasnip" }, -- snippets + { name = "nvim_lsp" }, + { name = "nvim_lua", priority = 100 }, + { name = "path" }, -- file system paths + { name = "projects", priority = 100 }, + { name = "snippets" }, + { name = "vim-dadbod-completion" }, -- Enable dadbod completion source + { name = "vsnip" }, + }), + + -- configure lspkind for vs-code like pictograms in completion menu + formatting = { + expandable_indicator = true, + fields = { + "abbr", + "kind", + "menu", + }, + format = require("lspkind").cmp_format({ + mode = "symbol_text", + maxwidth = 50, + ellipsis_char = "...", + menu = { + buffer = "[Buffer]", + luasnip = "[LuaSnip]", + nvim_lsp = "[LSP]", + nvim_lua = "[Lua]", + projects = "[Projects]", + emoji = "[Emoji]", + vsnip = "[Snippet]", + }, + }), + }, + }) + + -- Use buffer source for `/` and `?` (if you enabled `native_menu`, this won't work anymore). + cmp.setup.cmdline({ "/", "?" }, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = "buffer" }, + }, + }) + + -- Use cmdline & path source for ':' (if you enabled `native_menu`, this won't work anymore). + cmp.setup.cmdline(":", { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = "path" }, + }, { + { name = "cmdline" }, + }), + matching = { disallow_symbol_nonprefix_matching = false }, + }) + + -- sql + cmp.setup.filetype({ "sql" }, { + sources = { + { name = "vim-dadbod-completion" }, + { name = "buffer" }, + }, + }) + + local lspkind = require("lspkind") + lspkind.init({ + symbol_map = { + Copilot = "", + }, + }) + + vim.api.nvim_set_hl(0, "CmpItemKindCopilot", { fg = "#6CC644" }) + + require("cmp_dictionary").setup({ + paths = { "/usr/share/dict/words" }, + exact_length = 2, + first_case_insensitive = true, + document = { + enable = true, + command = { "wn", "${label}", "-over" }, + }, + }) + end, + }, + -- { + -- "saghen/blink.cmp", + -- version = "*", + -- -- build = "cargo build --release", + -- opts_extend = { + -- "sources.completion.enabled_providers", + -- "sources.compat", + -- "sources.default", + -- }, + -- enabled = true, + -- dependencies = { + -- { + -- "L3MON4D3/LuaSnip", + -- version = "v2.*", + -- build = "make install_jsregexp", + -- }, + -- "rafamadriz/friendly-snippets", + -- { + -- "saghen/blink.compat", + -- optional = true, -- make optional so it's only enabled if any extras need it + -- opts = {}, + -- version = "*", + -- }, + -- "kristjanhusak/vim-dadbod-completion", + -- "giuxtaposition/blink-cmp-copilot", + -- }, + -- event = "InsertEnter", + -- opts = function(_, opts) + -- opts.sources = vim.tbl_deep_extend("force", opts.sources or {}, { + -- default = { "lsp", "path", "snippets", "buffer", "copilot", "luasnip", "dadbod" }, + -- providers = { + -- lsp = { + -- name = "lsp", + -- enabled = true, + -- module = "blink.cmp.sources.lsp", + -- fallbacks = { "snippets", "luasnip", "buffer" }, + -- score_offset = 90, -- the higher the number, the higher the priority + -- }, + -- luasnip = { + -- name = "luasnip", + -- enabled = true, + -- module = "blink.cmp.sources.luasnip", + -- min_keyword_length = 2, + -- fallbacks = { "snippets" }, + -- score_offset = 85, + -- max_items = 8, + -- }, + -- path = { + -- name = "Path", + -- module = "blink.cmp.sources.path", + -- score_offset = 3, + -- -- When typing a path, I would get snippets and text in the + -- -- suggestions, I want those to show only if there are no path + -- -- suggestions + -- fallbacks = { "snippets", "luasnip", "buffer" }, + -- opts = { + -- trailing_slash = false, + -- label_trailing_slash = true, + -- get_cwd = function(context) + -- return vim.fn.expand(("#%d:p:h"):format(context.bufnr)) + -- end, + -- show_hidden_files_by_default = true, + -- }, + -- }, + -- buffer = { + -- name = "Buffer", + -- enabled = true, + -- max_items = 3, + -- module = "blink.cmp.sources.buffer", + -- min_keyword_length = 4, + -- }, + -- snippets = { + -- name = "Snippets", + -- enabled = true, + -- max_items = 3, + -- module = "blink.cmp.sources.snippets", + -- min_keyword_length = 4, + -- score_offset = 80, -- the higher the number, the higher the priority + -- }, + -- -- Example on how to configure dadbod found in the main repo + -- -- https://github.com/kristijanhusak/vim-dadbod-completion + -- dadbod = { + -- name = "Dadbod", + -- module = "vim_dadbod_completion.blink", + -- score_offset = 85, -- the higher the number, the higher the priority + -- }, + -- -- Third class citizen mf always talking shit + -- copilot = { + -- name = "Copilot", + -- enabled = true, + -- module = "blink-cmp-copilot", + -- min_keyword_length = 6, + -- score_offset = -100, -- the higher the number, the higher the priority + -- async = true, + -- }, + -- }, + -- -- command line completion, thanks to dpetka2001 in reddit + -- -- https://www.reddit.com/r/neovim/comments/1hjjf21/comment/m37fe4d/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button + -- cmdline = function() + -- local type = vim.fn.getcmdtype() + -- if type == "/" or type == "?" then + -- return { "buffer" } + -- end + -- if type == ":" then + -- return { "cmdline" } + -- end + -- return {} + -- end, + -- }) + -- + -- -- This comes from the luasnip extra, if you don't add it, won't be able to + -- -- jump forward or backward in luasnip snippets + -- opts.snippets = { + -- expand = function(snippet) + -- require("luasnip").lsp_expand(snippet) + -- end, + -- active = function(filter) + -- if filter and filter.direction then + -- return require("luasnip").jumpable(filter.direction) + -- end + -- return require("luasnip").in_snippet() + -- end, + -- jump = function(direction) + -- require("luasnip").jump(direction) + -- end, + -- } + -- + -- opts.appearance = { + -- -- sets the fallback highlight groups to nvim-cmp's highlight groups + -- -- useful for when your theme doesn't support blink.cmp + -- -- will be removed in a future release, assuming themes add support + -- use_nvim_cmp_as_default = false, + -- -- set to 'mono' for 'Nerd Font Mono' or 'normal' for 'Nerd Font' + -- -- adjusts spacing to ensure icons are aligned + -- nerd_font_variant = "mono", + -- } + -- + -- opts.completion = { + -- accept = { + -- -- experimental auto-brackets support + -- auto_brackets = { + -- enabled = true, + -- }, + -- }, + -- menu = { + -- draw = { + -- treesitter = { "lsp" }, + -- }, + -- }, + -- documentation = { + -- auto_show = true, + -- auto_show_delay_ms = 200, + -- }, + -- ghost_text = { enabled = true }, + -- } + -- + -- opts.keymap = { + -- preset = "super-tab", + -- } + -- + -- return opts + -- end, + -- }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorizer.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorizer.lua new file mode 100644 index 0000000..7356619 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorizer.lua @@ -0,0 +1,76 @@ +return { + "catgoose/nvim-colorizer.lua", + event = "BufReadPre", + opts = { -- set to setup table + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>zh", group = "Colorizer" }, + }) + end, + config = function() + require("colorizer").setup({ + filetypes = { "*" }, -- Filetype options. Accepts table like `user_default_options` + buftypes = {}, -- Buftype options. Accepts table like `user_default_options` + -- Boolean | List of usercommands to enable. See User commands section. + user_commands = true, -- Enable all or some usercommands + lazy_load = false, -- Lazily schedule buffer highlighting setup function + user_default_options = { + names = false, -- "Name" codes like Blue or red. Added from `vim.api.nvim_get_color_map()` + names_opts = { -- options for mutating/filtering names. + lowercase = true, -- name:lower(), highlight `blue` and `red` + camelcase = true, -- name, highlight `Blue` and `Red` + uppercase = true, -- name:upper(), highlight `BLUE` and `RED` + strip_digits = false, -- ignore names with digits, + -- highlight `blue` and `red`, but not `blue3` and `red4` + }, + -- Expects a table of color name to #RRGGBB value pairs. # is optional + -- Example: { cool = "#107dac", ["notcool"] = "#ee9240" } + -- Set to false to disable, for example when setting filetype options + names_custom = false, -- Custom names to be highlighted: table|function|false + RGB = true, -- #RGB hex codes + RGBA = true, -- #RGBA hex codes + RRGGBB = true, -- #RRGGBB hex codes + RRGGBBAA = true, -- #RRGGBBAA hex codes + AARRGGBB = false, -- 0xAARRGGBB hex codes + rgb_fn = true, -- CSS rgb() and rgba() functions + hsl_fn = true, -- CSS hsl() and hsla() functions + css = true, -- Enable all CSS *features*: + -- names, RGB, RGBA, RRGGBB, RRGGBBAA, AARRGGBB, rgb_fn, hsl_fn + css_fn = false, -- Enable all CSS *functions*: rgb_fn, hsl_fn + -- Tailwind colors. boolean|'normal'|'lsp'|'both'. True sets to 'normal' + tailwind = true, -- Enable tailwind colors + tailwind_opts = { -- Options for highlighting tailwind names + update_names = false, -- When using tailwind = 'both', update tailwind names from LSP results. See tailwind section + }, + -- parsers can contain values used in `user_default_options` + sass = { enable = false, parsers = { "css" } }, -- Enable sass colors + -- Highlighting mode. 'background'|'foreground'|'virtualtext' + mode = "background", -- Set the display mode + -- Virtualtext character to use + virtualtext = "■", + -- Display virtualtext inline with color. boolean|'before'|'after'. True sets to 'after' + virtualtext_inline = false, + -- Virtualtext highlight mode: 'background'|'foreground' + virtualtext_mode = "foreground", + -- update color values even if buffer is not focused + -- example use: cmp_menu, cmp_docs + always_update = false, + -- hooks to invert control of colorizer + hooks = { + -- called before line parsing. Accepts boolean or function that returns boolean + -- see hooks section below + disable_line_highlight = false, + }, + }, + }) + end, + keys = { + { "<leader>zha", "<Cmd>ColorizerAttachToBuffer<CR>", desc = "Attach colorizer" }, + { "<leader>zhd", "<Cmd>ColorizerDetachFromBuffer<CR>", desc = "Detach colorizer" }, + { "<leader>zhr", "<Cmd>ColorizerReloadAllBuffers<CR>", desc = "Refresh colorizer" }, + { "<leader>zht", "<Cmd>ColorizerToggle<CR>", desc = "Toggle colorizer" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorschemes.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorschemes.lua new file mode 100644 index 0000000..8fce515 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/colorschemes.lua @@ -0,0 +1,350 @@ +function ColorMyPencils(color) + color = color or "catppuccin" + vim.cmd.colorscheme(color) + local set = vim.api.nvim_set_hl + set(0, "Normal", { bg = "NONE" }) + set(0, "NormalFloat", { bg = "NONE" }) + set(0, "@comment.todo", { bg = "NONE" }) + set(0, "@comment.note", { bg = "NONE" }) + set(0, "@comment.warning", { bg = "NONE" }) + set(0, "@comment.error", { bg = "NONE" }) + set(0, "@number", { bg = "NONE" }) + set(0, "@string.special.url", { bg = "NONE" }) +end + +return { + { "junegunn/seoul256.vim" }, + { + "catppuccin/nvim", + name = "catppuccin", + config = function() + require("catppuccin").setup({ + flavour = "auto", -- latte, frappe, macchiato, mocha + background = { -- :h background + light = "latte", + dark = "mocha", + }, + transparent_background = true, -- disables setting the background color. + show_end_of_buffer = false, -- shows the '~' characters after the end of buffers + term_colors = false, -- sets terminal colors (e.g. `g:terminal_color_0`) + dim_inactive = { + enabled = true, -- dims the background color of inactive window + shade = "dark", + percentage = 0.15, -- percentage of the shade to apply to the inactive window + }, + no_italic = false, -- Force no italic + no_bold = false, -- Force no bold + no_underline = false, -- Force no underline + styles = { -- Handles the styles of general hi groups (see `:h highlight-args`): + comments = { "italic" }, -- Change the style of comments + conditionals = { "italic" }, + loops = {}, + functions = {}, + keywords = {}, + strings = {}, + variables = {}, + numbers = {}, + booleans = {}, + properties = {}, + types = {}, + operators = {}, + -- miscs = {}, -- Uncomment to turn off hard-coded styles + }, + color_overrides = {}, + custom_highlights = {}, + default_integrations = true, + integrations = { + aerial = true, + alpha = true, + blink_cmp = true, + cmp = true, + dashboard = true, + flash = true, + gitsigns = true, + headlines = true, + illuminate = true, + indent_blankline = { enabled = true, scope_color = "peach", colored_indent_levels = true }, + leap = true, + lsp_trouble = true, + mason = true, + markdown = true, + mini = true, + native_lsp = { + enabled = true, + underlines = { + errors = { "undercurl" }, + hints = { "undercurl" }, + warnings = { "undercurl" }, + information = { "undercurl" }, + }, + }, + navic = { enabled = true, custom_bg = "NONE" }, + neotest = true, + neotree = true, + noice = true, + notify = true, + semantic_tokens = true, + telescope = true, + treesitter = true, + treesitter_context = true, + which_key = true, + }, + highlight_overrides = { + mocha = function(mocha) + return { + LineNr = { fg = mocha.overlay2 }, + CursorLineNr = { fg = mocha.sky }, + Normal = { bg = "NONE" }, -- normal text + NormalNC = { bg = "NONE" }, + } + end, + }, + }) + + ColorMyPencils() + end, + }, + { + "ellisonleao/gruvbox.nvim", + priority = 1000, + -- opts = ..., + config = function() + require("gruvbox").setup({ + terminal_colors = true, -- add neovim terminal colors + undercurl = true, + underline = true, + bold = true, + italic = { + strings = true, + emphasis = true, + comments = true, + operators = false, + folds = true, + }, + strikethrough = true, + invert_selection = false, + invert_signs = false, + invert_tabline = false, + invert_intend_guides = false, + inverse = true, -- invert background for search, diffs, statuslines and errors + contrast = "", -- can be "hard", "soft" or empty string + palette_overrides = { + dark1 = "NONE", + }, + overrides = {}, + dim_inactive = true, + transparent_mode = true, + }) + end, + }, + { + "rose-pine/neovim", + name = "rose-pine", + config = function() + require("rose-pine").setup({ + variant = "auto", -- auto, main, moon, or dawn + dark_variant = "main", -- main, moon, or dawn + dim_inactive_windows = false, + extend_background_behind_borders = true, + enable = { + terminal = true, + legacy_highlights = true, -- Improve compatibility for previous versions of Neovim + migrations = true, -- Handle deprecated options automatically + }, + styles = { + bold = true, + italic = false, + transparency = true, + }, + groups = { + border = "muted", + link = "iris", + panel = "surface", + + error = "love", + hint = "iris", + info = "foam", + note = "pine", + todo = "rose", + warn = "gold", + + git_add = "foam", + git_change = "rose", + git_delete = "love", + git_dirty = "rose", + git_ignore = "muted", + git_merge = "iris", + git_rename = "pine", + git_stage = "iris", + git_text = "rose", + git_untracked = "subtle", + + h1 = "iris", + h2 = "foam", + h3 = "rose", + h4 = "gold", + h5 = "pine", + h6 = "foam", + }, + palette = { + -- Override the builtin palette per variant + -- moon = { + -- base = '#18191a', + -- overlay = '#363738', + -- }, + }, + highlight_groups = { + -- Comment = { fg = "foam" }, + -- VertSplit = { fg = "muted", bg = "muted" }, + }, + before_highlight = function(group, highlight, palette) + -- Disable all undercurls + -- if highlight.undercurl then + -- highlight.undercurl = false + -- end + -- + -- Change palette colour + -- if highlight.fg == palette.pine then + -- highlight.fg = palette.foam + -- end + end, + }) + -- vim.cmd("colorscheme rose-pine") + -- vim.cmd("colorscheme rose-pine-main") + -- vim.cmd("colorscheme rose-pine-moon") + -- vim.cmd("colorscheme rose-pine-dawn") + end, + }, + { + "Mofiqul/dracula.nvim", + config = function() + local dracula = require("dracula") + dracula.setup({ + -- customize dracula color palette + colors = { + bg = "#282A36", + fg = "#F8F8F2", + selection = "#44475A", + comment = "#6272A4", + red = "#FF5555", + orange = "#FFB86C", + yellow = "#F1FA8C", + green = "#50fa7b", + purple = "#BD93F9", + cyan = "#8BE9FD", + pink = "#FF79C6", + bright_red = "#FF6E6E", + bright_green = "#69FF94", + bright_yellow = "#FFFFA5", + bright_blue = "#D6ACFF", + bright_magenta = "#FF92DF", + bright_cyan = "#A4FFFF", + bright_white = "#FFFFFF", + menu = "#21222C", + visual = "#3E4452", + gutter_fg = "#4B5263", + nontext = "#3B4048", + white = "#ABB2BF", + black = "#191A21", + }, + -- show the '~' characters after the end of buffers + show_end_of_buffer = true, -- default false + -- use transparent background + transparent_bg = true, -- default false + -- set custom lualine background color + lualine_bg_color = "#44475a", -- default nil + -- set italic comment + italic_comment = true, -- default false + -- overrides the default highlights with table see `:h synIDattr` + overrides = {}, + -- You can use overrides as table like this + -- overrides = { + -- NonText = { fg = "white" }, -- set NonText fg to white + -- NvimTreeIndentMarker = { link = "NonText" }, -- link to NonText highlight + -- Nothing = {} -- clear highlight of Nothing + -- }, + -- Or you can also use it like a function to get color from theme + -- overrides = function (colors) + -- return { + -- NonText = { fg = colors.white }, -- set NonText fg to white of theme + -- } + -- end, + }) + end, + }, + { + "neanias/everforest-nvim", + priority = 1000, -- make sure to load this before all the other start plugins + -- Optional; default configuration will be used if setup isn't called. + config = function() + require("everforest").setup({ + ---Controls the "hardness" of the background. Options are "soft", "medium" or "hard". + ---Default is "medium". + background = "hard", + ---How much of the background should be transparent. 2 will have more UI + ---components be transparent (e.g. status line background) + transparent_background_level = 2, + ---Whether italics should be used for keywords and more. + italics = false, + ---Disable italic fonts for comments. Comments are in italics by default, set + ---this to `true` to make them _not_ italic! + disable_italic_comments = false, + ---By default, the colour of the sign column background is the same as the as normal text + ---background, but you can use a grey background by setting this to `"grey"`. + sign_column_background = "none", + ---The contrast of line numbers, indent lines, etc. Options are `"high"` or + ---`"low"` (default). + ui_contrast = "low", + ---Dim inactive windows. Only works in Neovim. Can look a bit weird with Telescope. + --- + ---When this option is used in conjunction with show_eob set to `false`, the + ---end of the buffer will only be hidden inside the active window. Inside + ---inactive windows, the end of buffer filler characters will be visible in + ---dimmed symbols. This is due to the way Vim and Neovim handle `EndOfBuffer`. + dim_inactive_windows = false, + ---Some plugins support highlighting error/warning/info/hint texts, by + ---default these texts are only underlined, but you can use this option to + ---also highlight the background of them. + diagnostic_text_highlight = false, + ---Which colour the diagnostic text should be. Options are `"grey"` or `"coloured"` (default) + diagnostic_virtual_text = "coloured", + ---Some plugins support highlighting error/warning/info/hint lines, but this + ---feature is disabled by default in this colour scheme. + diagnostic_line_highlight = false, + ---By default, this color scheme won't colour the foreground of |spell|, instead + ---colored under curls will be used. If you also want to colour the foreground, + ---set this option to `true`. + spell_foreground = false, + ---Whether to show the EndOfBuffer highlight. + show_eob = true, + ---Style used to make floating windows stand out from other windows. `"bright"` + ---makes the background of these windows lighter than |hl-Normal|, whereas + ---`"dim"` makes it darker. + --- + ---Floating windows include for instance diagnostic pop-ups, scrollable + ---documentation windows from completion engines, overlay windows from + ---installers, etc. + --- + ---NB: This is only significant for dark backgrounds as the light palettes + ---have the same colour for both values in the switch. + float_style = "bright", + ---Inlay hints are special markers that are displayed inline with the code to + ---provide you with additional information. You can use this option to customize + ---the background color of inlay hints. + --- + ---Options are `"none"` or `"dimmed"`. + inlay_hints_background = "none", + ---You can override specific highlights to use other groups or a hex colour. + ---This function will be called with the highlights and colour palette tables. + ---@param highlight_groups Highlights + ---@param palette Palette + on_highlights = function(highlight_groups, palette) end, + ---You can override colours in the palette to use different hex colours. + ---This function will be called once the base and background colours have + ---been mixed on the palette. + ---@param palette Palette + colours_override = function(palette) end, + }) + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/comment.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/comment.lua new file mode 100644 index 0000000..eb93c01 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/comment.lua @@ -0,0 +1,8 @@ +return { + "numToStr/Comment.nvim", + lazy = false, + opts = {}, + config = function() + require("Comment").setup() + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/compiler.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/compiler.lua new file mode 100644 index 0000000..9dad4f8 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/compiler.lua @@ -0,0 +1,53 @@ +return { + { -- This plugin + "Zeioth/compiler.nvim", + cmd = { "CompilerOpen", "CompilerToggleResults", "CompilerRedo" }, + dependencies = { "stevearc/overseer.nvim", "nvim-telescope/telescope.nvim" }, + opts = {}, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>r", group = "Compiler/Refactoring" }, + }) + end, + keys = { + -- Open compiler + vim.api.nvim_set_keymap( + "n", + "<leader>ro", + "<Cmd>CompilerOpen<cr>", + { noremap = true, silent = true, desc = "Open compiler" } + ), + + -- Redo last selected option + vim.api.nvim_set_keymap( + "n", + "<leader>re", + "<Cmd>CompilerStop<cr>" -- (Optional, to dispose all tasks before redo) + .. "<Cmd>CompilerRedo<cr>", + { noremap = true, silent = true, desc = "Recompile" } + ), + -- Toggle compiler results + vim.api.nvim_set_keymap( + "n", + "<leader>rt", + "<Cmd>CompilerToggleResults<cr>", + { noremap = true, silent = true, desc = "Toggle compiler" } + ), + }, + }, + { -- The task runner we use + "stevearc/overseer.nvim", + commit = "6271cab7ccc4ca840faa93f54440ffae3a3918bd", + cmd = { "CompilerOpen", "CompilerToggleResults", "CompilerRedo" }, + opts = { + task_list = { + direction = "bottom", + min_height = 25, + max_height = 25, + default_detail = 1, + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/context.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/context.lua new file mode 100644 index 0000000..e2d8d2b --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/context.lua @@ -0,0 +1,25 @@ +return { + "nvim-treesitter/nvim-treesitter-context", + cmd = { "TSContextEnable", "TSContextDisable", "TSContextToggle" }, + config = function() + require("treesitter-context").setup({ + enable = false, -- Enable this plugin (Can be enabled/disabled later via commands) + max_lines = 3, -- How many lines the window should span. Values <= 0 mean no limit. + min_window_height = 1, -- Minimum editor window height to enable context. Values <= 0 mean no limit. + line_numbers = true, + multiline_threshold = 20, -- Maximum number of lines to show for a single context + trim_scope = "outer", -- Which context lines to discard if `max_lines` is exceeded. Choices: 'inner', 'outer' + mode = "cursor", -- Line used to calculate context. Choices: 'cursor', 'topline' + -- Separator between context and content. Should be a single character string, like '-'. + -- When separator is set, the context will only show up when there are at least 2 lines above cursorline. + separator = nil, + zindex = 20, -- The Z-index of the context window + on_attach = nil, -- (fun(buf: integer): boolean) return false to disable attaching + }) + + vim.keymap.set("n", "[t", function() + require("treesitter-context").go_to_context(vim.v.count1) + end, { silent = true, desc = "Go to context" }) + vim.keymap.set({ "n", "v" }, "<leader>zc", "<Cmd>TSContextToggle<cr>", { desc = "Toggle context" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/csv.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/csv.lua new file mode 100644 index 0000000..bcf0239 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/csv.lua @@ -0,0 +1,55 @@ +return { + { + "hat0uma/csvview.nvim", + cmd = { "CsvViewEnable", "CsvViewDisable", "CsvViewToggle" }, + event = { "BufReadPre *.csv" }, -- Lazy-load the plugin when a CSV file is about to be read + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>cs", group = "csv" }, + }) + end, + config = function() + require("csvview").setup() + + vim.api.nvim_create_autocmd("BufRead", { + pattern = "*.csv", + callback = function() + vim.cmd("CsvViewEnable") + end, + }) + + vim.api.nvim_create_autocmd("FileType", { + pattern = "csv", + callback = function() + vim.keymap.set( + "n", + "<leader>zv", + "<Cmd>CsvViewToggle<cr>", + { desc = "Toggle CSV view", buffer = true } + ) + end, + }) + end, + keys = { + { + "<leader>csv", + function() + local delimiter = vim.fn.input("Delimiter (e.g., ,): ") + local quote_char = vim.fn.input("Quote char (e.g., '): ") + local comment = vim.fn.input("Comment char (e.g., #): ") + local command = string.format( + ":CsvViewToggle delimiter=%s quote_char=%s comment=%s<CR>", + delimiter, + quote_char, + comment + ) + + vim.cmd(command) + end, + desc = "Toggle CSV view", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dadbod.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dadbod.lua new file mode 100644 index 0000000..7d4fb9e --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dadbod.lua @@ -0,0 +1,56 @@ +return { + "kristijanhusak/vim-dadbod-ui", + dependencies = { + { "tpope/vim-dadbod", lazy = true }, + { "kristijanhusak/vim-dadbod-completion", ft = { "sql", "mysql", "plsql" }, lazy = true }, + }, + cmd = { + "DBUI", + "DBUIToggle", + "DBUIAddConnection", + "DBUIFindBuffer", + }, + init = function() + -- Your DBUI configuration + local home = vim.fn.expand("~") + vim.g.db_ui_use_nerd_fonts = 1 + vim.g.dbs = { + -- firefox = "sqlite://" .. home .. "/.mozilla/firefox/si.default/places.sqlite", + -- librewolf = "sqlite://" .. home .. "/.librewolf/si.default/places.sqlite", + mysql = "mariadb://ms:password@localhost:5432/mysql", + postsql = "postgresql://ps:password@localhost:5432/postgresql", + dts = "postgresql://dts:dujinDTS2@localhost:5432/evcp", + dts_aws = "postgresql://dts:dujinDTS2@127.0.0.1:15432/evcp", + -- qutebrowser = "sqlite://" .. home .. "/.local/share/qutebrowser/history.sqlite", + -- sqlite = "sqlite://" .. home .. "/.local/share/db/sqlite.db", + } + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<localleader>d", group = "DB" }, + }) + end, + config = function() + local function db_completion() + require("cmp").setup.buffer({ sources = { { name = "vim-dadbod-completion" } } }) + end + vim.api.nvim_create_autocmd("FileType", { + pattern = { + "sql", + "mysql", + "plsql", + }, + callback = function() + vim.schedule(db_completion) + end, + }) + end, + keys = { + { "<localleader>du", "<Cmd>DBUI<cr>", desc = "DB UI" }, + { "<localleader>dt", "<Cmd>DBUIToggle<cr>", desc = "Toggle DB UI" }, + { "<localleader>da", "<Cmd>DBUIAddConnection<cr>", desc = "Add connection" }, + { "<localleader>df", "<Cmd>DBUIFindBuffer<cr>", desc = "Find buffer" }, + { "<localleader>dr", "<Cmd>DBUIRenameBuffer<cr>", desc = "Rename buffer" }, + { "<localleader>di", "<Cmd>DBUILastQueryInfo<cr>", desc = "Last query info" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dap.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dap.lua new file mode 100644 index 0000000..6a4118a --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/dap.lua @@ -0,0 +1,337 @@ +local function get_args(config) + local args = type(config.args) == "function" and (config.args() or {}) or config.args or {} + config = vim.deepcopy(config) + ---@cast args string[] + config.args = function() + local new_args = vim.fn.input("Run with args: ", table.concat(args, " ")) --[[@as string]] + return vim.split(vim.fn.expand(new_args) --[[@as string]], " ") + end + return config +end + +return { + { + "mfussenegger/nvim-dap", + recommended = true, + desc = "Debugging support. Requires language specific adapters to be configured. (see lang extras)", + dependencies = { + "rcarriga/nvim-dap-ui", + -- virtual text for the debugger + { + "theHamsta/nvim-dap-virtual-text", + opts = {}, + }, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<localleader>db", group = "Debug" }, + { "<localleader>dB", group = "Debug (Python)" }, + }) + end, + config = function() + -- load mason-nvim-dap here, after all adapters have been setup + vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" }) + + local dap = require("dap") + + dap.adapters["pwa-node"] = { + type = "server", + host = "localhost", + port = "${port}", + executable = { + command = "node", + -- 💀 Make sure to update this path to point to your installation + args = { + vim.fn.stdpath("data") .. "/mason/packages/js-debug-adapter/js-debug/src/dapDebugServer.js", + "${port}", + }, + }, + } + + dap.configurations.java = { + { + type = "java", + request = "attach", + name = "Debug (Attach) - Remote", + hostName = "127.0.0.1", + port = 5005, + }, + } + + for _, language in ipairs({ "javascript", "typescript" }) do + dap.configurations[language] = { + { + type = "pwa-node", + request = "launch", + name = "Launch file", + program = "${file}", + cwd = "${workspaceFolder}", + }, + } + end + + local dap_icons = { + Stopped = { " ", "DiagnosticWarn", "DapStoppedLine" }, + Breakpoint = " ", + BreakpointCondition = " ", + BreakpointRejected = { " ", "DiagnosticError" }, + LogPoint = ".>", + } + + for name, sign in pairs(dap_icons) do + sign = type(sign) == "table" and sign or { sign } + vim.fn.sign_define( + "Dap" .. name, + { text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] } + ) + end + + -- setup dap config by VsCode launch.json file + local vscode = require("dap.ext.vscode") + local json = require("plenary.json") + vscode.json_decode = function(str) + return vim.json.decode(json.json_strip_comments(str)) + end + end, + keys = { + { + "<localleader>dbB", + function() + require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: ")) + end, + desc = "Dap breakpoint condition", + }, + { + "<localleader>dbb", + function() + require("dap").toggle_breakpoint() + end, + desc = "Dap toggle breakpoint", + }, + { + "<localleader>dbc", + function() + require("dap").continue() + end, + desc = "Dap continue", + }, + { + "<localleader>dba", + function() + require("dap").continue({ before = get_args }) + end, + desc = "Dap run with args", + }, + { + "<localleader>dbC", + function() + require("dap").run_to_cursor() + end, + desc = "Dap run to cursor", + }, + { + "<localleader>dbg", + function() + require("dap").goto_() + end, + desc = "Dap go to line (no execute)", + }, + { + "<localleader>dbi", + function() + require("dap").step_into() + end, + desc = "Dap step into", + }, + { + "<localleader>dbj", + function() + require("dap").down() + end, + desc = "Dap down", + }, + { + "<localleader>dbk", + function() + require("dap").up() + end, + desc = "Dap up", + }, + { + "<localleader>dbl", + function() + require("dap").run_last() + end, + desc = "Dap run last", + }, + { + "<localleader>dbo", + function() + require("dap").step_out() + end, + desc = "Dap step out", + }, + { + "<localleader>dbO", + function() + require("dap").step_over() + end, + desc = "Dap step over", + }, + { + "<localleader>dbp", + function() + require("dap").pause() + end, + desc = "Dap pause", + }, + { + "<localleader>dbr", + function() + require("dap").repl.toggle() + end, + desc = "Dap toggle repl", + }, + { + "<localleader>dbs", + function() + require("dap").session() + end, + desc = "Dap session", + }, + { + "<localleader>dbt", + function() + require("dap").terminate() + end, + desc = "Dap terminate", + }, + { + "<localleader>dbw", + function() + require("dap.ui.widgets").hover() + end, + desc = "Dap widgets", + }, + { + "<localleader>dbR", + "<Cmd>lua require('dapui').open({ reset = true })<cr>", + desc = "Dap UI reset", + }, + }, + }, + { + "mfussenegger/nvim-dap-python", + ft = "python", + dependencies = { "mfussenegger/nvim-dap", "rcarriga/nvim-dap-ui" }, + config = function() + local path = "~/.local/share/nvim/mason/packages/debugpy/venv/bin/python" + require("dap-python").setup(path) + end, + keys = { + { + "<localleader>dBt", + function() + require("dap-python").test_method() + end, + desc = "Dap debug method", + ft = "python", + }, + { + "<localleader>dBc", + function() + require("dap-python").test_class() + end, + desc = "Dap debug class", + ft = "python", + }, + }, + }, + { + "rcarriga/nvim-dap-ui", + dependencies = { "mfussenegger/nvim-dap", "nvim-neotest/nvim-nio" }, + config = function() + local dap = require("dap") + local dapui = require("dapui") + dapui.setup({ + icons = { expanded = "▾", collapsed = "▸", current_frame = "*" }, + controls = { + icons = { + pause = "⏸", + play = "▶", + step_into = "⏎", + step_over = "⏭", + step_out = "⏮", + step_back = "b", + run_last = "▶▶", + terminate = "⏹", + disconnect = "⏏", + }, + }, + }) + + dap.listeners.before.attach.dapui_config = function() + dapui.open() + end + dap.listeners.before.launch.dapui_config = function() + dapui.open() + end + dap.listeners.before.event_terminated.dapui_config = function() + dapui.close() + end + dap.listeners.before.event_exited.dapui_config = function() + dapui.close() + end + + dap.listeners.after.event_initialized["dapui_config"] = function() + dapui.open() + end + dap.listeners.after.event_terminated["dapui_config"] = function() + dapui.close() + end + dap.listeners.after.event_exited["dapui_config"] = function() + dapui.close() + end + end, + keys = { + { + "<localleader>dbu", + function() + require("dapui").toggle() + end, + desc = "Dap UI", + }, + { + "<localleader>dbe", + function() + require("dapui").eval() + end, + desc = "Dap eval", + }, + }, + }, + { + "jay-babu/mason-nvim-dap.nvim", + dependencies = "mason.nvim", + cmd = { "DapInstall", "DapUninstall" }, + opts = { + -- Makes a best effort to setup the various debuggers with + -- reasonable debug configurations + automatic_installation = true, + + -- You can provide additional configuration to the handlers, + -- see mason-nvim-dap README for more information + handlers = {}, + + -- You'll need to check that you have the required things installed + -- online, please don't ask me how to install them :) + ensure_installed = { + -- Update this to ensure that you have the debuggers for the langs you want + }, + }, + -- mason-nvim-dap is loaded when nvim-dap loads + config = function() end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/docker.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/docker.lua new file mode 100644 index 0000000..3244fc9 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/docker.lua @@ -0,0 +1,251 @@ +return { + "https://codeberg.org/esensar/nvim-dev-container", + dependencies = "nvim-treesitter/nvim-treesitter", + config = function() + vim.api.nvim_create_autocmd("User", { + pattern = "DevcontainerBuildProgress", + callback = function() + vim.cmd("redrawstatus") + end, + }) + require("devcontainer").setup({ + config_search_start = function() + if vim.g.devcontainer_selected_config == nil or vim.g.devcontainer_selected_config == "" then + local candidates = vim.split( + vim.fn.glob(vim.loop.cwd() .. "/.devcontainer/**/devcontainer.json"), + "\n", + { trimempty = true } + ) + if #candidates < 2 then + vim.g.devcontainer_selected_config = vim.loop.cwd() + else + local choices = { "Select devcontainer config file to use:" } + for idx, candidate in ipairs(candidates) do + table.insert(choices, idx .. ". - " .. candidate) + end + local choice_idx = vim.fn.inputlist(choices) + if choice_idx > #candidates then + choice_idx = 1 + end + vim.g.devcontainer_selected_config = + string.gsub(candidates[choice_idx], "/devcontainer.json", "") + end + end + return vim.g.devcontainer_selected_config + end, + workspace_folder_provider = function() + -- By default this function uses first workspace folder for integrated lsp if available and vim.loop.cwd() as a fallback + -- This is used to replace `${localWorkspaceFolder}` in devcontainer.json + -- Also used for creating default .devcontainer.json file + local bufdir = vim.fn.expand("%:p:h") + if bufdir ~= nil and bufdir ~= "" then + return bufdir + end + return vim.loop.cwd() or vim.fn.getcwd() or "." + end, + -- terminal_handler = function(command) + -- -- By default this function creates a terminal in a new tab using :terminal command + -- -- It also removes statusline when that tab is active, to prevent double statusline + -- -- It can be overridden to provide custom terminal handling + -- end, + -- nvim_installation_commands_provider = function(path_binaries, version_string) + -- -- Returns table - list of commands to run when adding neovim to container + -- -- Each command can either be a string or a table (list of command parts) + -- -- Takes binaries available in path on current container and version_string passed to the command or current version of neovim + -- end, + -- devcontainer_json_template = function() + -- -- Returns table - list of lines to set when creating new devcontainer.json files + -- -- As a template + -- -- Used only when using functions from commands module or created commands + -- end, + -- Can be set to false to prevent generating default commands + -- Default commands are listed below + generate_commands = true, + -- By default no autocommands are generated + -- This option can be used to configure automatic starting and cleaning of containers + autocommands = { + -- can be set to true to automatically start containers when devcontainer.json is available + init = false, + -- can be set to true to automatically remove any started containers and any built images when exiting vim + clean = false, + -- can be set to true to automatically restart containers when devcontainer.json file is updated + update = false, + }, + -- can be changed to increase or decrease logging from library + log_level = "info", + -- can be set to true to disable recursive search + -- in that case only .devcontainer.json and .devcontainer/devcontainer.json files will be checked relative + -- to the directory provided by config_search_start + disable_recursive_config_search = false, + -- can be set to false to disable image caching when adding neovim + -- by default it is set to true to make attaching to containers faster after first time + cache_images = true, + -- By default all mounts are added (config, data and state) + -- This can be changed to disable mounts or change their options + -- This can be useful to mount local configuration + -- And any other mounts when attaching to containers with this plugin + attach_mounts = { + neovim_config = { + -- enables mounting local config to /root/.config/nvim in container + enabled = true, + -- makes mount readonly in container + options = { "readonly" }, + }, + neovim_data = { + -- enables mounting local data to /root/.local/share/nvim in container + enabled = false, + -- no options by default + options = {}, + }, + -- Only useful if using neovim 0.8.0+ + neovim_state = { + -- enables mounting local state to /root/.local/state/nvim in container + enabled = false, + -- no options by default + options = {}, + }, + }, + -- This takes a list of mounts (strings) that should always be added to every run container + -- This is passed directly as --mount option to docker command + -- Or multiple --mount options if there are multiple values + always_mount = {}, + -- This takes a string (usually either "podman" or "docker") representing container runtime - "devcontainer-cli" is also partially supported + -- That is the command that will be invoked for container operations + -- If it is nil, plugin will use whatever is available (trying "podman" first) + container_runtime = "docker", + -- Similar to container runtime, but will be used if main runtime does not support an action - useful for "devcontainer-cli" + backup_runtime = nil, + -- This takes a string (usually either "podman-compose" or "docker-compose") representing compose command - "devcontainer-cli" is also partially supported + -- That is the command that will be invoked for compose operations + -- If it is nil, plugin will use whatever is available (trying "podman-compose" first) + compose_command = "docker-compose", + -- Similar to compose command, but will be used if main command does not support an action - useful for "devcontainer-cli" + backup_compose_command = nil, + }) + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>d", group = "Docker" }, + { "<leader>db", group = "Build (docker)" }, + { "<leader>dc", group = "Compose (docker)" }, + { "<leader>do", group = "Open (docker)" }, + { "<leader>dr", group = "Run (docker)" }, + }) + end, + keys = { + { + "<leader>dcu", + function() + require("devcontainer.commands").compose_up() + end, + desc = "Compose up (docker)", + }, + { + "<leader>dcd", + function() + require("devcontainer.commands").compose_down() + end, + desc = "Compose down (docker)", + }, + { + "<leader>dcD", + function() + require("devcontainer.commands").compose_rm() + end, + desc = "Compose remove (docker)", + }, + { + "<leader>dbb", + function() + require("devcontainer.commands").docker_build() + end, + desc = "Build (docker)", + }, + { + "<leader>dri", + function() + require("devcontainer.commands").docker_image_run() + end, + desc = "Image run (docker)", + }, + { + "<leader>dbr", + function() + require("devcontainer.commands").docker_build_and_run() + end, + desc = "Build & run (docker)", + }, + { + "<leader>dba", + function() + require("devcontainer.commands").docker_build_run_and_attach() + end, + desc = "Build & attach (docker)", + }, + { + "<leader>ds", + function() + require("devcontainer.commands").start_auto() + end, + desc = "Start (docker)", + }, + { + "<leader>da", + function() + require("devcontainer.commands").attach_auto() + end, + desc = "Attach (docker)", + }, + { + "<leader>drr", + function() + require("devcontainer.commands").exec("devcontainer", "ls", { on_success = function(result) end }) + end, + desc = "Execute (docker)", + }, + { + "<leader>dx", + function() + require("devcontainer.commands").stop_auto() + end, + desc = "Stop (docker)", + }, + { + "<leader>dX", + function() + require("devcontainer.commands").stop_all() + end, + desc = "Stop all (docker)", + }, + { + "<leader>dD", + function() + require("devcontainer.commands").remove_all() + end, + desc = "Remove all (docker)", + }, + { + "<leader>dol", + function() + require("devcontainer.commands").open_logs() + end, + desc = "Open logs (docker)", + }, + { + "<leader>doc", + function() + require("devcontainer.commands").open_nearest_devcontainer_config() + end, + desc = "Open nearest config (docker)", + }, + { + "<leader>de", + function() + require("devcontainer.commands").edit_devcontainer_config() + end, + desc = "Edit nearest config (docker)", + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua new file mode 100644 index 0000000..cc8b747 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua @@ -0,0 +1,229 @@ +return { + { + "moyiz/git-dev.nvim", + event = "VeryLazy", + opts = {}, + config = function() + require("git-dev").setup() + + local function copy_git_repo_url() + -- Get the Git repository root + local git_root = vim.fn.system("git rev-parse --show-toplevel"):gsub("\n", "") + if git_root == "" then + vim.notify("Not inside a Git repository", vim.log.levels.WARN) + return nil + end + + -- Get the remote URL + local remote_url = vim.fn.system("git config --get remote.origin.url"):gsub("\n", "") + if remote_url == "" then + vim.notify("No remote URL found", vim.log.levels.WARN) + return nil + end + + -- Convert SSH URL to HTTPS if needed + if remote_url:match("^git@") then + remote_url = remote_url:gsub("git@", "https://"):gsub(":", "/") + end + + -- Remove `.git` from the remote URL + remote_url = remote_url:gsub("%.git$", "") + + -- Get the relative path of the current file + local file_path = vim.fn.expand("%:~:.") + if file_path == "" then + vim.notify("No file currently open", vim.log.levels.WARN) + return nil + end + + -- Get the relative path to the repository root + local relative_path = + vim.fn.system("git ls-files --full-name " .. vim.fn.shellescape(file_path)):gsub("\n", "") + + -- Combine the remote URL with the relative file path + local full_url = remote_url .. "/" .. relative_path + + -- Copy to clipboard + vim.fn.setreg("+", full_url) + vim.notify("Copied to clipboard: " .. full_url, vim.log.levels.INFO) + + return full_url + end + + -- Keybinding to copy the Git repository URL + vim.keymap.set("n", "<leader>cg", function() + copy_git_repo_url() + end, { desc = "Copy git repository URL to clipboard" }) + + -- Function to open a repository from the clipboard + vim.keymap.set("n", "<leader>eg", function() + local url = vim.fn.getreg("+") -- Get URL from clipboard + if not url or url == "" then + vim.notify("Clipboard is empty. Copy a valid URL first.", vim.log.levels.WARN) + return + end + if url:match("^https://") then + require("git-dev").open(url) + else + vim.notify("Not a valid URL: " .. url, vim.log.levels.ERROR) + end + end, { desc = "Open Git repository from clipboard" }) + end, + }, + { + "lewis6991/gitsigns.nvim", + opts = { + signs = { + add = { text = "▎" }, + change = { text = "▎" }, + delete = { text = "" }, + topdelete = { text = "" }, + changedelete = { text = "▎" }, + untracked = { text = "▎" }, + }, + signs_staged = { + add = { text = "▎" }, + change = { text = "▎" }, + delete = { text = "" }, + topdelete = { text = "" }, + changedelete = { text = "▎" }, + }, + on_attach = function(buffer) + local gs = package.loaded.gitsigns + + local function map(mode, l, r, desc) + vim.keymap.set(mode, l, r, { buffer = buffer, desc = desc }) + end + + -- stylua: ignore start + map("n", "]h", function() + if vim.wo.diff then + vim.cmd.normal({ "]c", bang = true }) + else + gs.nav_hunk("next") + end + end, "Next hunk") + map("n", "[h", function() + if vim.wo.diff then + vim.cmd.normal({ "[c", bang = true }) + else + gs.nav_hunk("prev") + end + end, "Previous hunk") + map("n", "]H", function() gs.nav_hunk("last") end, "Last hunk") + map("n", "[H", function() gs.nav_hunk("first") end, "First hunk") + map("n", "<leader>gs", gs.stage_hunk, "Stage hunk") + map("v", "<leader>gs", function() gs.stage_hunk({ vim.fn.line('.'), vim.fn.line('v')}) end, "Stage hunk") + map("n", "<leader>gr", gs.reset_hunk, "Reset hunk") + map("v", "<leader>gr", function() gs.reset_hunk({ vim.fn.line('.'), vim.fn.line('v')}) end, "Reset hunk") + map("n", "<leader>gS", gs.stage_buffer, "Stage buffer") + map("n", "<leader>gu", gs.undo_stage_hunk, "Undo stage hunk") + map("n", "<leader>gR", gs.reset_buffer, "Reset buffer") + map("n", "<leader>gpv", gs.preview_hunk_inline, "Preview hunk inline") + map("n", "<leader>gb", function() gs.blame_line({ full = true }) end, "Blame line") + map("n", "<leader>gB", function() gs.blame() end, "Blame buffer") + map("n", "<leader>gd", gs.diffthis, "Diff this") + map("n", "<leader>gD", function() gs.diffthis("~") end, "Diff this ~") + map({ "o", "x" }, "ih", ":<C-U>Gitsigns select_hunk<CR>", "Select hunk") + map("n", "<leader>gtb", gs.toggle_current_line_blame, "Toggle line blame") + map("n", "<leader>gtd", gs.toggle_deleted, "Toggle delete") + end, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>g", group = "Git" }, + { "<leader>gt", group = "Toggle" }, + }) + end, + }, + { + "kdheepak/lazygit.nvim", + cmd = { + "LazyGit", + "LazyGitConfig", + "LazyGitCurrentFile", + "LazyGitFilter", + "LazyGitFilterCurrentFile", + }, + -- optional for floating window border decoration + dependencies = { + "nvim-lua/plenary.nvim", + }, + -- setting the keybinding for LazyGit with 'keys' is recommended in + -- order to load the plugin when the command is run for the first time + keys = { + { "<leader>gg", "<Cmd>LazyGit<cr>", desc = "Lazygit" }, + }, + }, + { + "mbbill/undotree", + config = function() + vim.keymap.set("n", "<leader>gu", vim.cmd.UndotreeToggle, { desc = "Undo tree" }) + end, + }, + { + "tpope/vim-fugitive", + config = function() + local TheSiahxyz_Fugitive = vim.api.nvim_create_augroup("TheSiahxyz_Fugitive", {}) + local autocmd = vim.api.nvim_create_autocmd + autocmd("BufWinEnter", { + group = TheSiahxyz_Fugitive, + pattern = "*", + callback = function() + if vim.bo.ft ~= "fugitive" then + return + end + + local bufnr = vim.api.nvim_get_current_buf() + vim.keymap.set("n", "<leader>P", function() + vim.cmd.Git("push") + end, { buffer = bufnr, remap = false, desc = "Git push" }) + vim.keymap.set("n", "<leader>p", function() + vim.cmd.Git({ "pull", "--rebase" }) + end, { buffer = bufnr, remap = false, desc = "Git pull" }) + vim.keymap.set( + "n", + "<leader>o", + ":Git push -u origin ", + { buffer = bufnr, remap = false, desc = "Git push origin" } + ) + vim.keymap.set( + "n", + "<leader>h", + ":Git push home ", + { buffer = bufnr, remap = false, desc = "Git push home" } + ) + end, + }) + autocmd("FileType", { + group = TheSiahxyz_Fugitive, + pattern = "fugitive", + callback = function(event) + vim.bo[event.buf].buflisted = false + vim.keymap.set("n", "q", "<Cmd>close<cr>", { buffer = event.buf, silent = true }) + end, + }) + end, + keys = { + { mode = "n", "<leader>g<leader>", ":Git ", desc = "Git" }, + { mode = "n", "<leader>gf", vim.cmd.Git, desc = "Git fugitive" }, + { mode = "n", "gm", "<Cmd>diffget //2<cr>", desc = "Git diff on my side" }, + { mode = "n", "go", "<Cmd>diffget //3<cr>", desc = "Git diff on their side" }, + }, + }, + { + "pwntester/octo.nvim", + requires = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + -- OR 'ibhagwan/fzf-lua', + -- OR 'folke/snacks.nvim', + "nvim-tree/nvim-web-devicons", + }, + config = function() + require("octo").setup() + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/goyo.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/goyo.lua new file mode 100644 index 0000000..86b9a03 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/goyo.lua @@ -0,0 +1,39 @@ +return { + "junegunn/goyo.vim", + dependencies = "junegunn/seoul256.vim", + config = function() + -- Enable Goyo by default for mutt writing + vim.api.nvim_create_autocmd({ "BufRead", "BufNewFile" }, { + group = vim.api.nvim_create_augroup("TheSiahxyz_goyo_config", { clear = true }), + pattern = "/tmp/neomutt*", + callback = function() + vim.g.goyo_width = 80 + vim.g.seoul256_background = 235 + vim.cmd([[ + Goyo + set bg=light + set linebreak + set wrap + set textwidth=0 + set wrapmargin=0 + set background=dark + colorscheme seoul256 + ]]) + vim.api.nvim_buf_set_keymap( + 0, + "n", + "<leader>gd", + ":Goyo|x!<CR>", + { noremap = true, silent = true, desc = "Goyo quit" } + ) + vim.api.nvim_buf_set_keymap( + 0, + "n", + "<leader>gq", + ":Goyo|q!<CR>", + { noremap = true, silent = true, desc = "Goyo abort" } + ) + end, + }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/grug-far.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/grug-far.lua new file mode 100644 index 0000000..ca0de7d --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/grug-far.lua @@ -0,0 +1,31 @@ +return { + "MagicDuck/grug-far.nvim", + --- Ensure existing keymaps and opts remain unaffected + config = function(_, opts) + require("grug-far").setup(opts) + vim.api.nvim_create_autocmd("FileType", { + pattern = "grug-far", + callback = function() + -- Map <Esc> to quit after ensuring we're in normal mode + vim.keymap.set({ "i", "n" }, "<Esc>", "<Cmd>stopinsert | bd!<CR>", { buffer = true }) + end, + }) + end, + keys = { + { + "<leader>rc", + function() + local grug = require("grug-far") + local ext = vim.bo.buftype == "" and vim.fn.expand("%:e") + grug.open({ + transient = true, + prefills = { + filesFilter = ext and ext ~= "" and "*." .. ext or nil, + }, + }) + end, + mode = { "n", "v" }, + desc = "Search and Replace", + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/harpoon2.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/harpoon2.lua new file mode 100644 index 0000000..1db778f --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/harpoon2.lua @@ -0,0 +1,124 @@ +return { + "ThePrimeagen/harpoon", + branch = "harpoon2", + opts = { + menu = { + width = vim.api.nvim_win_get_width(0) - 4, + }, + settings = { + save_on_toggle = true, + sync_on_ui_close = false, -- save over session + key = function() -- define how to identify list + return vim.loop.cwd() + end, + }, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>h", group = "Harpoon" }, + { "<leader>hr", group = "Replace harpoon slot" }, + { "<M-x>", group = "Harpoon list delete" }, + }) + end, + config = function(_, opts) + local harpoon = require("harpoon") + local extensions = require("harpoon.extensions") + + -- Apply the base configuration + harpoon.setup(opts) + + -- Extend functionality + harpoon:extend({ + UI_CREATE = function(cx) + vim.keymap.set("n", "<C-v>", function() + harpoon.ui:select_menu_item({ vsplit = true }) + end, { buffer = cx.bufnr }) + + vim.keymap.set("n", "<C-s>", function() + harpoon.ui:select_menu_item({ split = true }) + end, { buffer = cx.bufnr }) + + vim.keymap.set("n", "<C-t>", function() + harpoon.ui:select_menu_item({ tabedit = true }) + end, { buffer = cx.bufnr }) + end, + }) + + -- Highlight current file + harpoon:extend(extensions.builtins.highlight_current_file()) + harpoon:extend(extensions.builtins.navigate_with_number()) + end, + keys = function() + local keys = { + { + "<leader>ha", + function() + require("harpoon"):list():add() + end, + mode = { "n", "i", "v", "x" }, + desc = "Add buffer to harpoon list", + }, + { + "<leader>ht", + function() + require("harpoon"):list():prepend() + end, + mode = { "n", "i", "v", "x" }, + desc = "Prepend buffer to harpoon list", + }, + { + "<C-g>", + function() + local harpoon = require("harpoon") + harpoon.ui:toggle_quick_menu(harpoon:list()) + end, + mode = { "n", "i" }, + desc = "Open harpoon list menu", + }, + { + "<C-S-P>", + function() + require("harpoon"):list():prev({ ui_nav_wrap = false }) + end, + mode = { "n", "i", "v", "x" }, + desc = "Previous harpoon list", + }, + { + "<C-S-N>", + function() + require("harpoon"):list():next({ ui_nav_wrap = false }) + end, + mode = { "n", "i", "v", "x" }, + desc = "Next harpoon list", + }, + } + + for i = 0, 9 do + table.insert(keys, { + "<M-" .. i .. ">", + function() + require("harpoon"):list():select(i) + end, + desc = "Harpoon list " .. i, + }) + table.insert(keys, { + "<leader>h" .. i, + function() + require("harpoon"):list():select(i) + end, + desc = "Harpoon list " .. i, + }) + table.insert(keys, { + "<leader>hr" .. i, + function() + require("harpoon"):list():replace_at(i) + end, + desc = "Replace buffer at harpoon slot " .. i, + }) + end + + return keys + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/image.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/image.lua new file mode 100644 index 0000000..a4f126f --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/image.lua @@ -0,0 +1,210 @@ +return { + "HakonHarnes/img-clip.nvim", + event = "VeryLazy", + opts = { + -- add options here + -- or leave it empty to use the default settings + }, + config = function(_, opts) + require("img-clip").setup(opts) + + vim.keymap.set({ "n", "v", "i" }, "<M-i>", function() + local pasted_image = require("img-clip").paste_image() + if pasted_image then + -- "Update" saves only if the buffer has been modified since the last save + vim.cmd("silent! update") + -- Get the current line + local line = vim.api.nvim_get_current_line() + -- Move cursor to end of line + vim.api.nvim_win_set_cursor(0, { vim.api.nvim_win_get_cursor(0)[1], #line }) + -- I reload the file, otherwise I cannot view the image after pasted + vim.cmd("edit!") + end + end, { desc = "Paste image from clipboard" }) + + vim.keymap.set("n", "<leader>oi", function() + local function get_image_path() + -- Get the current line + local line = vim.api.nvim_get_current_line() + -- Patterns to match image paths + local patterns = { + "%[.-%]%((.-)%)", -- Markdown style:  + "%[%[(.-)%]%]", -- Double square brackets: [[image_path]] + } + + for _, pattern in ipairs(patterns) do + local _, _, image_path = string.find(line, pattern) + if image_path then + return image_path + end + end + + return nil -- Return nil if no pattern matches + end + + local function file_exists(filepath) + -- Check if the file exists + local f = io.open(filepath, "r") + if f then + f:close() + return true + end + return false + end + + -- Get the image path + local image_path = get_image_path() + if image_path then + -- Check if the image path starts with "http" or "https" + if string.sub(image_path, 1, 4) == "http" then + print("URL image, use 'gx' to open it in the default browser.") + else + -- Construct absolute image path + local current_file_path = vim.fn.expand("%:p:h") + local absolute_image_path = current_file_path .. "/" .. image_path + -- Check if the image exists in the current path + if not file_exists(absolute_image_path) then + -- If not found, search ../Screenshots/ + local fallback_path = vim.fn.fnamemodify(current_file_path, ":h") + .. "/Screenshots/" + .. image_path + if file_exists(fallback_path) then + absolute_image_path = fallback_path + else + print("Image not found in either current directory or ../Screenshots/") + return + end + end + -- Construct command to open image in Preview + local command = "nsxiv -aiop " .. vim.fn.shellescape(absolute_image_path) + -- Execute the command + local success = os.execute(command) + if success then + print("Opened image: " .. absolute_image_path) + else + print("Failed to open image: " .. absolute_image_path) + end + end + else + print("No image found under the cursor") + end + end, { desc = "Open image under cursor" }) + + vim.keymap.set("n", "<leader>di", function() + local function get_image_path() + local line = vim.api.nvim_get_current_line() + -- Patterns to match image paths + local patterns = { + "%[.-%]%((.-)%)", -- Markdown style:  + "%[%[(.-)%]%]", -- Double square brackets: [[image_path]] + } + + for _, pattern in ipairs(patterns) do + local _, _, image_path = string.find(line, pattern) + if image_path then + return image_path + end + end + + return nil -- Return nil if no pattern matches + end + + local function file_exists(filepath) + local f = io.open(filepath, "r") + if f then + f:close() + return true + end + return false + end + + local image_path = get_image_path() + if image_path then + if string.sub(image_path, 1, 4) == "http" then + vim.api.nvim_echo({ { "URL image cannot be deleted from disk.", "WarningMsg" } }, false, {}) + return + end + + local current_file_path = vim.fn.expand("%:p:h") + local absolute_image_path = current_file_path .. "/" .. image_path + + -- Check if file exists + if not file_exists(absolute_image_path) then + -- Search fallback directory + local fallback_path = vim.fn.fnamemodify(current_file_path, ":h") .. "/Screenshots/" .. image_path + if file_exists(fallback_path) then + absolute_image_path = fallback_path + else + print("Image not found in either current directory or ../Screenshots/") + return + end + end + + -- Verify if trash utility exists + if vim.fn.executable("trash") == 0 then + vim.api.nvim_echo({ + { "- Trash utility not installed. Install `trash-cli`.\n", "ErrorMsg" }, + }, false, {}) + return + end + + vim.ui.select({ "yes", "no" }, { prompt = "Delete image file? " }, function(choice) + if choice == "yes" then + -- Attempt to delete using trash + local command = { "trash", absolute_image_path } + local success, err = pcall(vim.fn.system, command) + + -- Debug message for troubleshooting + print("Debug: Trash command -", table.concat(command, " ")) + + if success and vim.fn.filereadable(absolute_image_path) == 0 then + vim.api.nvim_echo({ + { "Image file deleted using trash:\n", "Normal" }, + { absolute_image_path, "Normal" }, + }, false, {}) + require("image").clear() + vim.cmd("edit!") + vim.cmd("normal! dd") + else + -- If trash fails, log the error + vim.api.nvim_echo({ + { "Trash deletion failed. Error:\n", "ErrorMsg" }, + { err or "Unknown error", "ErrorMsg" }, + }, false, {}) + end + else + vim.api.nvim_echo({ { "Image deletion canceled.", "Normal" } }, false, {}) + end + end) + else + print("No image found under the cursor") + end + end, { desc = "Delete image file under cursor" }) + + -- Refresh the images in the current buffer + -- Useful if you delete an actual image file and want to see the changes + -- without having to re-open neovim + vim.keymap.set("n", "<leader>ir", function() + -- First I clear the images + require("image").clear() + -- I'm using [[ ]] to escape the special characters in a command + -- vim.cmd([[lua require("image").clear()]]) + -- Reloads the file to reflect the changes + vim.cmd("edit!") + print("Images refreshed") + end, { desc = "Refresh images" }) + + -- Set up a keymap to clear all images in the current buffer + vim.keymap.set("n", "<leader>ic", function() + -- This is the command that clears the images + require("image").clear() + -- I'm using [[ ]] to escape the special characters in a command + -- vim.cmd([[lua require("image").clear()]]) + print("Images cleared") + end, { desc = "Clear images" }) + end, + keys = { + -- suggested keymap + { "<leader>pi", "<Cmd>PasteImage<cr>", desc = "Paste image from clipboard" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/init.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/init.lua new file mode 100644 index 0000000..1a533b9 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/init.lua @@ -0,0 +1,87 @@ +return { + { "nvim-lua/plenary.nvim" }, + { + "aserowy/tmux.nvim", + config = function() + require("tmux").setup({ + copy_sync = { + -- enables copy sync. by default, all registers are synchronized. + -- to control which registers are synced, see the `sync_*` options. + enable = false, + + -- ignore specific tmux buffers e.g. buffer0 = true to ignore the + -- first buffer or named_buffer_name = true to ignore a named tmux + -- buffer with name named_buffer_name :) + ignore_buffers = { empty = false }, + + -- TMUX >= 3.2: all yanks (and deletes) will get redirected to system + -- clipboard by tmux + redirect_to_clipboard = false, + + -- offset controls where register sync starts + -- e.g. offset 2 lets registers 0 and 1 untouched + register_offset = 0, + + -- overwrites vim.g.clipboard to redirect * and + to the system + -- clipboard using tmux. If you sync your system clipboard without tmux, + -- disable this option! + sync_clipboard = true, + + -- synchronizes registers *, +, unnamed, and 0 till 9 with tmux buffers. + sync_registers = true, + + -- synchronizes registers when pressing p and P. + sync_registers_keymap_put = true, + + -- synchronizes registers when pressing (C-r) and ". + sync_registers_keymap_reg = true, + + -- syncs deletes with tmux clipboard as well, it is adviced to + -- do so. Nvim does not allow syncing registers 0 and 1 without + -- overwriting the unnamed register. Thus, ddp would not be possible. + sync_deletes = true, + + -- syncs the unnamed register with the first buffer entry from tmux. + sync_unnamed = true, + }, + navigation = { + -- cycles to opposite pane while navigating into the border + cycle_navigation = false, + + -- enables default keybindings (C-hjkl) for normal mode + enable_default_keybindings = true, + + -- prevents unzoom tmux when navigating beyond vim border + persist_zoom = true, + }, + resize = { + -- enables default keybindings (A-hjkl) for normal mode + enable_default_keybindings = false, + + -- sets resize steps for x axis + resize_step_x = 2, + + -- sets resize steps for y axis + resize_step_y = 2, + }, + }) + + vim.keymap.set("i", "<C-h>", "<cmd>lua require('tmux').move_left()<cr>", { desc = "Move to left" }) + vim.keymap.set("i", "<C-l>", "<cmd>lua require('tmux').move_right()<cr>", { desc = "Move to right" }) + vim.keymap.set("i", "<C-j>", "<cmd>lua require('tmux').move_bottom()<cr>", { desc = "Move to bottom" }) + vim.keymap.set("i", "<C-k>", "<cmd>lua require('tmux').move_top()<cr>", { desc = "Move to top" }) + vim.keymap.set("n", "<C-left>", function() + require("tmux").resize_left() + end, { desc = "Decrease window width" }) + vim.keymap.set("n", "<C-down>", function() + require("tmux").resize_bottom() + end, { desc = "Decrease window height" }) + vim.keymap.set("n", "<C-up>", function() + require("tmux").resize_top() + end, { desc = "Increase window height" }) + vim.keymap.set("n", "<C-right>", function() + require("tmux").resize_right() + end, { desc = "Increase window width" }) + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/keys.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/keys.lua new file mode 100644 index 0000000..0f95202 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/keys.lua @@ -0,0 +1,121 @@ +return { + { + "nvzone/showkeys", + cmd = "ShowkeysToggle", + opts = {}, + keys = { + { "<leader>zk", "<Cmd>ShowkeysToggle<cr>", desc = "Toggle keys" }, + }, + }, + { + "folke/which-key.nvim", + event = "VeryLazy", + cmd = "WhichKey", + dependencies = { "echasnovski/mini.icons", "nvim-tree/nvim-web-devicons" }, + opts = { + preset = "classic", -- false | "classic" | "modern" | "helix" + keys = { + scroll_down = "<c-e>", + scroll_up = "<c-y>", + }, + }, + config = function(_, opts) + local wk = require("which-key") + wk.setup(opts) + wk.add({ + { + mode = { "n", "v" }, + { "g", group = "Goto" }, + { "g`", group = "Marks" }, + { "g'", group = "Marks" }, + { "gr", group = "Lsp buf" }, + { "gs", group = "Search/Surround" }, + { "gx", desc = "Open with system app" }, + { "s", group = "Surround/Search & replace on line" }, + { "S", group = "Surround/Search & replace in file" }, + { "z", group = "Fold" }, + { "`", group = "Marks" }, + { "'", group = "Marks" }, + { '"', group = "Registers" }, + { "]", group = "Next" }, + { "]]", group = "Next" }, + { "[", group = "Prev" }, + { "[[", group = "Prev" }, + { "=", group = "Line paste" }, + { "<C-w>", group = "Windows" }, + { "<leader>", group = "Leader" }, + { "<leader>a", group = "Ascii" }, + { + "<leader>b", + group = "Buffer", + expand = function() + return require("which-key.extras").expand.buf() + end, + }, + { "<leader>B", group = "Buffer (force)" }, + { "<leader>C", group = "Goto realpath" }, + { "<leader>d", group = "Delete" }, + { "<leader>D", group = "Delete (blackhole)" }, + { "<leader>e", group = "Explorer" }, + { "<leader>i", group = "Inspect" }, + { "<leader>l", group = "Location" }, + { "<leader>L", group = "Lazy" }, + { "<leader>M", group = "Mason" }, + { "<leader>o", group = "Open" }, + { "<leader>p", group = "Paste" }, + { "<leader>P", group = "Paste" }, + { "<leader>q", group = "Quit" }, + { "<leader>rn", group = "Rename" }, + { "<leader>sk", group = "Keys" }, + { "<leader>S", group = "Save/Source" }, + { "<leader>w", group = "Which-key" }, + { "<leader>W", group = "Save all" }, + { "<leader>z", group = "Toggle" }, + { "<leader>Z", group = "All buffer" }, + { "<leader><tab>", group = "Tabs" }, + { "<localleader>", group = "Local Leader (bookmarks)" }, + { "<localleader><leader>", group = "Bookmarks (explorer)" }, + { "<localleader><localleader>", group = "Bookmarks (mini)" }, + { "<localleader>t", group = "Task" }, + }, + { + mode = { "n", "v", "x" }, + { "gw", desc = "Visible in window" }, + { "g%", desc = "Match backward" }, + { "g;", desc = "Last change" }, + { "<leader>Q", group = "Quit all" }, + }, + { + mode = { "i" }, + { "<C-o>", desc = "Execute one command" }, + { "<C-r>", desc = "Paste from registers" }, + }, + }) + end, + keys = { + { + "<leader>?", + function() + require("which-key").show({ global = false }) + end, + desc = "Buffer local keymaps (which-key)", + }, + { + "<leader>wk", + function() + local ok, input = pcall(vim.fn.input, "WhichKey: ") + if ok and input ~= "" then + vim.cmd("WhichKey " .. input) + end + end, + desc = "Which-key query lookup", + }, + { + "<leader>wK", + "<Cmd>WhichKey<cr>", + mode = { "n", "v", "x" }, + desc = "Which-key all key", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua new file mode 100644 index 0000000..da49976 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua @@ -0,0 +1,707 @@ +return { + { + "neovim/nvim-lspconfig", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { + "mason-org/mason.nvim", + "mason-org/mason-lspconfig.nvim", + "WhoIsSethDaniel/mason-tool-installer.nvim", + "hrsh7th/cmp-nvim-lsp", + "hrsh7th/cmp-buffer", + "hrsh7th/cmp-path", + "hrsh7th/cmp-cmdline", + "hrsh7th/nvim-cmp", + { + "L3MON4D3/LuaSnip", + version = "v2.*", + build = "make install_jsregexp", + }, + "mfussenegger/nvim-lint", + "saadparwaiz1/cmp_luasnip", + "j-hui/fidget.nvim", + { "folke/neoconf.nvim", cmd = "Neoconf", config = false, dependencies = { "nvim-lspconfig" } }, + { + "folke/lazydev.nvim", + ft = "lua", -- only load on lua files + opts = { + library = { + -- See the configuration section for more details + -- Load luvit types when the `vim.uv` word is found + { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + }, + }, + }, + "stevearc/conform.nvim", + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>tf", group = "Format" }, + }) + end, + config = function() + local cmp = require("cmp") + local cmp_lsp = require("cmp_nvim_lsp") + local capabilities = vim.tbl_deep_extend( + "force", + {}, + vim.lsp.protocol.make_client_capabilities(), + cmp_lsp.default_capabilities() + ) + local lspconfig = require("lspconfig") + + require("fidget").setup({ + progress = { + poll_rate = false, -- How and when to poll for progress messages + suppress_on_insert = true, -- Suppress new messages while in insert mode + ignore_done_already = true, -- Ignore new tasks that are already complete + ignore_empty_message = true, -- Ignore new tasks that don't contain a message + clear_on_detach = function(client_id) -- Clear notification group when LSP server detaches + local client = vim.lsp.get_client_by_id(client_id) + return client and client.name or nil + end, + -- ignore = { "lua_ls" }, + }, + notification = { + window = { + normal_hl = "Comment", -- Base highlight group in the notification window + winblend = 0, -- Background color opacity in the notification window + border = "none", -- Border around the notification window + zindex = 45, -- Stacking priority of the notification window + max_width = 0, -- Maximum width of the notification window + max_height = 0, -- Maximum height of the notification window + x_padding = 1, -- Padding from right edge of window boundary + y_padding = 0, -- Padding from bottom edge of window boundary + align = "bottom", -- How to align the notification window + relative = "editor", -- What the notification window position is relative to + }, + }, + integration = { + ["nvim-tree"] = { + enable = false, -- Integrate with nvim-tree/nvim-tree.lua (if installed) + }, + }, + }) + + require("mason").setup({ + pip = { + use_python3_host_prog = true, + }, + }) + require("mason-lspconfig").setup({ + ensure_installed = { + "bashls", + "dockerls", + "docker_compose_language_service", + "harper_ls", + "jdtls", + "jsonls", + "lua_ls", + -- "mutt_ls", + "pyright", + "ruff", + "sqls", + "ts_ls", + }, + automatic_enable = true, + handlers = { + function(server_name) -- default handler (optional) + require("lspconfig")[server_name].setup({ + capabilities = capabilities, + }) + end, + ["bashls"] = function() + lspconfig.bashls.setup({ + capabilities = capabilities, + }) + end, + ["dockerls"] = function() + lspconfig.dockerls.setup({ + capabilities = capabilities, + -- settings = { + -- python = { + -- disableLanguageServices = false, + -- disableOrganizeImports = false, + -- }, + -- }, + }) + end, + ["docker_compose_language_service"] = function() + lspconfig.docker_compose_language_service.setup({ + capabilities = capabilities, + -- settings = { + -- python = { + -- disableLanguageServices = false, + -- disableOrganizeImports = false, + -- }, + -- }, + }) + end, + ["harper_ls"] = function() + lspconfig.harper_ls.setup({ + capabilities = capabilities, + filetypes = { "markdown", "python" }, + settings = { + ToDoHyphen = false, + -- SentenceCapitalization = true, + -- SpellCheck = true, + isolateEnglish = true, + markdown = { + -- [ignores this part]() + -- [[ also ignores my marksman links ]] + IgnoreLinkTitle = true, + }, + }, + }) + end, + ["jdtls"] = function() + lspconfig.jdtls.setup({ + capabilities = capabilities, + }) + end, + ["jsonls"] = function() + lspconfig.jsonls.setup({ + capabilities = capabilities, + settings = { + json = { + format = { + enable = true, + }, + validate = { enable = true }, + }, + }, + }) + end, + ["lua_ls"] = function() + lspconfig.lua_ls.setup({ + capabilities = capabilities, + settings = { + Lua = { + runtime = { version = "Lua 5.4" }, + diagnostics = { + globals = { "bit", "vim", "it", "describe", "before_each", "after_each" }, + }, + }, + }, + }) + end, + ["mutt_ls"] = function() + lspconfig.mutt_ls.setup({ + capabilities = capabilities, + }) + end, + ["pyright"] = function() + lspconfig.pyright.setup({ + capabilities = capabilities, + settings = { + python = { + disableLanguageServices = false, + disableOrganizeImports = false, + }, + }, + }) + end, + ["ruff"] = function() + lspconfig.ruff.setup({ + capabilities = capabilities, + -- settings = { + -- python = { + -- disableLanguageServices = false, + -- disableOrganizeImports = false, + -- }, + -- }, + }) + end, + ["sqls"] = function() + lspconfig.sqls.setup({ + capabilities = capabilities, + }) + end, + ["ts_ls"] = function() + lspconfig.ruff.setup({ + capabilities = capabilities, + }) + end, + }, + }) + + local lint = require("lint") + lint.linters_by_ft = { + dockerfile = { "hadolint" }, + javascript = { "eslint_d" }, + javascriptreact = { "eslint_d" }, + python = { "pylint" }, + sh = { "shellcheck" }, + sql = { "sqlfluff" }, + svelte = { "eslint_d" }, + typescript = { "eslint_d" }, + typescriptreact = { "eslint_d" }, + } + + local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) + vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave", "TextChanged" }, { + group = lint_augroup, + callback = function() + lint.try_lint() + end, + }) + + require("mason-tool-installer").setup({ + ensure_installed = { + "beautysh", -- zsh formatter + "black", -- python formatter + "debugpy", -- python debuger + "eslint_d", -- eslint linter + -- "hadolint", -- docker linter + "isort", -- python formatter + "java-debug-adapter", -- java debugger + "java-test", -- java test + "js-debug-adapter", -- javascript debugger + "markdown-toc", -- markdown toc + "prettier", -- prettier formatter + "pylint", -- python linter + "ruff", -- python formatter + "shellcheck", -- bash lint + "shfmt", -- sh formatter + "sqlfluff", -- sql linter + "sql-formatter", -- sql formatter + "stylua", -- lua formatter + }, + integrations = { + ["mason-lspconfig"] = true, + ["mason-null-ls"] = false, + ["mason-nvim-dap"] = true, + }, + }) + + local cmp_select = { behavior = cmp.SelectBehavior.Select } + local luasnip = require("luasnip") + + cmp.setup({ + snippet = { + expand = function(args) + luasnip.lsp_expand(args.body) -- For `luasnip` users. + end, + }, + mapping = cmp.mapping.preset.insert({ + ["<C-u>"] = cmp.mapping.scroll_docs(-4), -- Up + ["<C-d>"] = cmp.mapping.scroll_docs(4), -- Down + ["<C-p>"] = cmp.mapping.select_prev_item(cmp_select), + ["<C-n>"] = cmp.mapping.select_next_item(cmp_select), + ["<CR>"] = cmp.mapping.confirm({ + behavior = cmp.ConfirmBehavior.Replace, + select = true, + }), + ["<C-Space>"] = cmp.mapping.complete(), + ["<Tab>"] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_next_item() + elseif luasnip.expand_or_jumpable() then + luasnip.expand_or_jump() + else + fallback() + end + end, { "i", "s" }), + ["<S-Tab>"] = cmp.mapping(function(fallback) + if cmp.visible() then + cmp.select_prev_item() + elseif luasnip.jumpable(-1) then + luasnip.jump(-1) + else + fallback() + end + end, { "i", "s" }), + }), + sources = cmp.config.sources({ + { name = "nvim_lsp" }, + { name = "luasnip" }, -- For luasnip users. + { name = "buffer" }, + }), + }) + + vim.diagnostic.config({ + update_in_insert = true, + float = { + header = "", + border = "rounded", + prefix = "", + source = "if_many", + }, + }) + + require("conform").setup({ + formatters_by_ft = { + bash = { "shfmt" }, + css = { "prettier" }, + graphql = { "prettier" }, + html = { "prettier" }, + javascript = { "prettier" }, + javascriptreact = { "prettier" }, + json = { "prettier" }, + liquid = { "prettier" }, + lua = { "stylua" }, + markdown = { "prettier" }, + python = { "ruff", "isort", "black" }, + sh = { "shfmt" }, + sql = { "sql-formatter" }, + svelte = { "prettier" }, + typescript = { "prettier" }, + typescriptreact = { "prettier" }, + vimwiki = { "prettier" }, + yaml = { "prettier" }, + zsh = { "beautysh" }, + }, + default_format_opts = {}, + format_on_save = function(bufnr) + -- Disable with a global or buffer-local variable + if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then + return + end + local ft = vim.bo[bufnr].filetype + local off = { + javascript = true, + typescript = true, + javascriptreact = true, + typescriptreact = true, + json = true, + css = true, + } + if off[ft] then + return false + end + return { lsp_fallback = true, timeout_ms = 1000, async = false } + end, + }) + + vim.api.nvim_create_user_command("FormatDisable", function(args) + if args.bang then + vim.b.disable_autoformat = true + else + vim.g.disable_autoformat = true + end + end, { + desc = "Disable autoformat-on-save", + bang = true, + }) + vim.api.nvim_create_user_command("FormatEnable", function() + vim.b.disable_autoformat = false + vim.g.disable_autoformat = false + end, { + desc = "Re-enable autoformat-on-save", + }) + end, + keys = { + { + "<leader>lf", + function() + require("conform").format({ async = true }) + end, + mode = { "n", "v" }, + desc = "Format buffer by lsp", + }, + { + "<leader>ci", + "<Cmd>PyrightOrganizeImports<cr>", + desc = "Organize imports", + }, + { + "<leader>bl", + function() + require("lint").try_lint() + end, + desc = "Buffer lint", + }, + { + "<leader>le", + "<Cmd>FormatEnable<CR>", + desc = "Enable format", + }, + { + "<leader>ld", + "<Cmd>FormatDisable<CR>", + desc = "Disable format", + }, + { + "<leader>lD", + "<Cmd>FormatDisable!<CR>", + desc = "Disable current buffer format", + }, + }, + }, + -- { + -- "neovim/nvim-lspconfig", + -- event = { "BufReadPre", "BufNewFile" }, + -- dependencies = { + -- "mason-org/mason.nvim", + -- "mason-org/mason-lspconfig.nvim", + -- "WhoIsSethDaniel/mason-tool-installer.nvim", + -- "hrsh7th/cmp-nvim-lsp", + -- "hrsh7th/cmp-buffer", + -- "hrsh7th/cmp-path", + -- "hrsh7th/cmp-cmdline", + -- { + -- "L3MON4D3/LuaSnip", + -- version = "v2.*", + -- build = "make install_jsregexp", + -- }, + -- "mfussenegger/nvim-lint", + -- "saadparwaiz1/cmp_luasnip", + -- "j-hui/fidget.nvim", + -- { "folke/neoconf.nvim", cmd = "Neoconf", config = false, dependencies = { "nvim-lspconfig" } }, + -- { + -- "folke/lazydev.nvim", + -- ft = "lua", -- only load on lua files + -- opts = { + -- library = { + -- -- See the configuration section for more details + -- -- Load luvit types when the `vim.uv` word is found + -- { path = "${3rd}/luv/library", words = { "vim%.uv" } }, + -- }, + -- }, + -- }, + -- "stevearc/conform.nvim", + -- "saghen/blink.cmp", + -- }, + -- init = function() + -- local wk = require("which-key") + -- wk.add({ + -- mode = { "n", "v", "x" }, + -- { "<leader>tf", group = "Format" }, + -- }) + -- end, + -- opts = { + -- servers = { + -- lua_ls = { + -- settings = { + -- Lua = { + -- workspace = { + -- checkThirdParty = false, + -- }, + -- codeLens = { + -- enable = true, + -- }, + -- completion = { + -- callSnippet = "Replace", + -- }, + -- doc = { + -- privateName = { "^_" }, + -- }, + -- hint = { + -- enable = true, + -- setType = false, + -- paramType = true, + -- paramName = "Disable", + -- semicolon = "Disable", + -- arrayIndex = "Disable", + -- }, + -- runtime = { version = "Lua 5.4" }, + -- diagnostics = { + -- globals = { "bit", "vim", "it", "describe", "before_each", "after_each" }, + -- }, + -- }, + -- }, + -- }, + -- pyright = { + -- settings = { + -- python = { + -- disableLanguageServices = false, + -- disableOrganizeImports = false, + -- }, + -- }, + -- }, + -- }, + -- }, + -- config = function(_, opts) + -- local cmp = require("blink.cmp") + -- local lspconfig = require("lspconfig") + -- + -- require("mason").setup() + -- + -- for server, config in pairs(opts.servers) do + -- -- passing config.capabilities to blink.cmp merges with the capabilities in your + -- -- `opts[server].capabilities, if you've defined it + -- config.capabilities = cmp.get_lsp_capabilities(config.capabilities) + -- lspconfig[server].setup(config) + -- require("mason-lspconfig").setup({ + -- ensure_installed = { server }, + -- handlers = { + -- [server] = function() + -- lspconfig[server].setup(config) + -- end, + -- }, + -- }) + -- end + -- + -- require("fidget").setup({ + -- progress = { + -- poll_rate = 0, -- How and when to poll for progress messages + -- suppress_on_insert = true, -- Suppress new messages while in insert mode + -- ignore_done_already = true, -- Ignore new tasks that are already complete + -- ignore_empty_message = true, -- Ignore new tasks that don't contain a message + -- clear_on_detach = function(client_id) -- Clear notification group when LSP server detaches + -- local client = vim.lsp.get_client_by_id(client_id) + -- return client and client.name or nil + -- end, + -- ignore = { "lua_ls" }, + -- }, + -- notification = { + -- window = { + -- normal_hl = "Comment", -- Base highlight group in the notification window + -- winblend = 0, -- Background color opacity in the notification window + -- border = "none", -- Border around the notification window + -- zindex = 45, -- Stacking priority of the notification window + -- max_width = 0, -- Maximum width of the notification window + -- max_height = 0, -- Maximum height of the notification window + -- x_padding = 1, -- Padding from right edge of window boundary + -- y_padding = 0, -- Padding from bottom edge of window boundary + -- align = "bottom", -- How to align the notification window + -- relative = "editor", -- What the notification window position is relative to + -- }, + -- }, + -- integration = { + -- ["nvim-tree"] = { + -- enable = false, -- Integrate with nvim-tree/nvim-tree.lua (if installed) + -- }, + -- }, + -- }) + -- + -- local lint = require("lint") + -- lint.linters_by_ft = { + -- javascript = { "eslint_d" }, + -- typescript = { "eslint_d" }, + -- javascriptreact = { "eslint_d" }, + -- typescriptreact = { "eslint_d" }, + -- svelte = { "eslint_d" }, + -- python = { "pylint" }, + -- sh = { "shellcheck" }, + -- } + -- + -- local lint_augroup = vim.api.nvim_create_augroup("lint", { clear = true }) + -- vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost", "InsertLeave", "TextChanged" }, { + -- group = lint_augroup, + -- callback = function() + -- lint.try_lint() + -- end, + -- }) + -- + -- require("mason-tool-installer").setup({ + -- ensure_installed = { + -- "beautysh", -- zsh formatter + -- "black", -- python formatter + -- "debugpy", -- python debuger + -- "eslint_d", -- eslint linter + -- "isort", -- python formatter + -- "markdown-toc", -- markdown toc + -- "prettier", -- prettier formatter + -- "pylint", -- python linter + -- "ruff", -- python formatter + -- "shellcheck", -- bash lint + -- "shfmt", -- sh formatter + -- "stylua", -- lua formatter + -- }, + -- integrations = { + -- ["mason-lspconfig"] = true, + -- ["mason-null-ls"] = false, + -- ["mason-nvim-dap"] = true, + -- }, + -- }) + -- + -- vim.diagnostic.config({ + -- -- update_in_insert = true, + -- float = { + -- focusable = false, + -- style = "minimal", + -- border = "rounded", + -- source = "always", + -- header = "", + -- prefix = "", + -- }, + -- }) + -- + -- require("conform").setup({ + -- formatters_by_ft = { + -- bash = { "shfmt" }, + -- css = { "prettier" }, + -- graphql = { "prettier" }, + -- html = { "prettier" }, + -- javascript = { "prettier" }, + -- javascriptreact = { "prettier" }, + -- json = { "prettier" }, + -- liquid = { "prettier" }, + -- lua = { "stylua" }, + -- markdown = { "prettier" }, + -- python = { "ruff", "isort", "black" }, + -- sh = { "shfmt" }, + -- svelte = { "prettier" }, + -- typescript = { "prettier" }, + -- typescriptreact = { "prettier" }, + -- yaml = { "prettier" }, + -- zsh = { "beautysh" }, + -- }, + -- default_format_opts = {}, + -- format_on_save = function(bufnr) + -- -- Disable with a global or buffer-local variable + -- if vim.g.disable_autoformat or vim.b[bufnr].disable_autoformat then + -- return + -- end + -- return { lsp_format = "fallback", timeout_ms = 1000, async = false } + -- end, + -- }) + -- + -- vim.api.nvim_create_user_command("FormatDisable", function(args) + -- if args.bang then + -- vim.b.disable_autoformat = true + -- else + -- vim.g.disable_autoformat = true + -- end + -- end, { + -- desc = "Disable autoformat-on-save", + -- bang = true, + -- }) + -- vim.api.nvim_create_user_command("FormatEnable", function() + -- vim.b.disable_autoformat = false + -- vim.g.disable_autoformat = false + -- end, { + -- desc = "Re-enable autoformat-on-save", + -- }) + -- end, + -- keys = { + -- { + -- mode = { "n", "v" }, + -- "<leader>lf", + -- function() + -- require("conform").format({ async = true }) + -- end, + -- desc = "Format buffer by lsp", + -- }, + -- { + -- "<leader>ci", + -- "<Cmd>PyrightOrganizeImports<cr>", + -- desc = "Organize imports", + -- }, + -- { + -- "<leader>bl", + -- function() + -- require("lint").try_lint() + -- end, + -- desc = "Buffer lint", + -- }, + -- { + -- "<leader>le", + -- "<Cmd>FormatEnable<CR>", + -- desc = "Enable format", + -- }, + -- { + -- "<leader>ld", + -- "<Cmd>FormatDisable<CR>", + -- desc = "Disable format", + -- }, + -- { + -- "<leader>lD", + -- "<Cmd>FormatDisable!<CR>", + -- desc = "Disable current buffer format", + -- }, + -- }, + -- }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua new file mode 100644 index 0000000..b1b3159 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua @@ -0,0 +1,355 @@ +return { + "nvim-lualine/lualine.nvim", + dependencies = { "nvim-tree/nvim-web-devicons" }, + config = function() + local navic = require("nvim-navic") + require("lualine").setup({ + options = { + icons_enabled = true, + theme = "auto", + section_separators = { left = "", right = "" }, + component_separators = { left = "", right = "" }, + disabled_filetypes = { + statusline = {}, + winbar = {}, + }, + ignore_focus = {}, + always_divide_middle = true, + globalstatus = false, + refresh = { + statusline = 100, + tabline = 100, + winbar = 100, + }, + }, + sections = { + lualine_a = { + { + "mode", + fmt = function(str) + return str:sub(1, 1) + end, + }, + { + function() + local has_noice, noice = pcall(require, "noice") + if has_noice and noice.api and noice.api.status and noice.api.status.mode then + return noice.api.status.mode.get() or "" + else + return "" + end + end, + cond = function() + local has_noice, noice = pcall(require, "noice") + return has_noice + and noice.api + and noice.api.status + and noice.api.status.mode + and noice.api.status.mode.has() + end, + color = { bg = "#ff9e64" }, + }, + }, + lualine_b = { + { + function() + return vim.g.remote_neovim_host and ("Remote: %s"):format(vim.uv.os_gethostname()) or "" + end, + }, + { + function() + local build_status_last = require("devcontainer.status").find_build({ running = true }) + if build_status_last then + return string.format( + "[%s/%s]%s", + build_status_last.current_step or "", + build_status_last.step_count or "", + build_status_last.progress and ("(" .. build_status_last.progress .. "%%)") or "" + ) + else + return "" + end + end, + }, + "branch", + { + "diff", + colored = true, -- Displays a colored diff status if set to true + diff_color = { + -- Same color values as the general color option can be used here. + added = "LuaLineDiffAdd", -- Changes the diff's added color + modified = "LuaLineDiffChange", -- Changes the diff's modified color + removed = "LuaLineDiffDelete", -- Changes the diff's removed color you + }, + symbols = { added = "+", modified = "~", removed = "-" }, -- Changes the symbols used by the diff. + source = nil, -- A function that works as a data source for diff. + -- It must return a table as such: + -- { added = add_count, modified = modified_count, removed = removed_count } + -- or nil on failure. count <= 0 won't be displayed. + }, + { + "diagnostics", + -- Table of diagnostic sources, available sources are: + -- 'nvim_lsp', 'nvim_diagnostic', 'nvim_workspace_diagnostic', 'coc', 'ale', 'vim_lsp'. + -- or a function that returns a table as such: + -- { error=error_cnt, warn=warn_cnt, info=info_cnt, hint=hint_cnt } + sources = { "nvim_lsp", "nvim_diagnostic", "nvim_workspace_diagnostic", "coc" }, + + -- Displays diagnostics for the defined severity types + sections = { "error", "warn", "info", "hint" }, + + diagnostics_color = { + -- Same values as the general color option can be used here. + error = "DiagnosticError", -- Changes diagnostics' error color. + warn = "DiagnosticWarn", -- Changes diagnostics' warn color. + info = "DiagnosticInfo", -- Changes diagnostics' info color. + hint = "DiagnosticHint", -- Changes diagnostics' hint color. + }, + symbols = { + error = " ", + warn = " ", + info = " ", + hint = " ", + }, + colored = true, -- Displays diagnostics status in color if set to true. + update_in_insert = true, -- Update diagnostics in insert mode. + always_visible = false, -- Show diagnostics even if there are none. + }, + { + function() + local ok, neocomposer = pcall(require, "NeoComposer.ui") + if ok and neocomposer and neocomposer.status_recording then + return neocomposer.status_recording() + end + return "" + end, + }, + }, + lualine_c = { + { + "filename", + file_status = true, -- Displays file status (readonly status, modified status) + newfile_status = true, -- Display new file status (new file means no write after created) + path = 3, -- 0: Just the filename + -- 1: Relative path + -- 2: Absolute path + -- 3: Absolute path, with tilde as the home directory + -- 4: Filename and parent dir, with tilde as the home directory + + shorting_target = 40, -- Shortens path to leave 40 spaces in the window + -- for other components. (terrible name, any suggestions?) + symbols = { + modified = "[*]", -- Text to show when the file is modified. + readonly = "[r]", -- Text to show when the file is non-modifiable or readonly. + unnamed = "[?]", -- Text to show for unnamed buffers. + newfile = "[%%]", -- Text to show for newly created file before first write + }, + }, + }, + lualine_x = { + { + function() + local ok, rest = pcall(require, "rest") + if ok and rest then + return "rest" + end + return "" + end, + }, + { + function() + -- Check if MCPHub is loaded + if not vim.g.loaded_mcphub then + return " -" + end + + local count = vim.g.mcphub_servers_count or 0 + local status = vim.g.mcphub_status or "stopped" + local executing = vim.g.mcphub_executing + + -- Show "-" when stopped + if status == "stopped" then + return " -" + end + + -- Show spinner when executing, starting, or restarting + if executing or status == "starting" or status == "restarting" then + local frames = { "⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏" } + local frame = math.floor(vim.loop.now() / 100) % #frames + 1 + return " " .. frames[frame] + end + + return " " .. count + end, + color = function() + if not vim.g.loaded_mcphub then + return { fg = "#6c7086" } -- Gray for not loaded + end + + local status = vim.g.mcphub_status or "stopped" + if status == "ready" or status == "restarted" then + return { fg = "#50fa7b" } -- Green for connected + elseif status == "starting" or status == "restarting" then + return { fg = "#ffb86c" } -- Orange for connecting + else + return { fg = "#ff5555" } -- Red for error/stopped + end + end, + }, + { + function() + local has_noice, noice = pcall(require, "noice") + if has_noice and noice.api and noice.api.status and noice.api.status.mode then + return noice.api.status.search.get() or "" + else + return "" + end + end, + cond = function() + local has_noice, noice = pcall(require, "noice") + return has_noice + and noice.api + and noice.api.status + and noice.api.status.search + and noice.api.status.search.has() + end, + color = { bg = "#ff9e64" }, + }, + "copilot", + { + function() + return require("molten.status").initialized() + end, + }, + "encoding", + "fileformat", + { + "filetype", + colored = true, -- Displays filetype icon in color if set to true + icon_only = true, -- Display only an icon for filetype + icon = { align = "right" }, -- Display filetype icon on the right hand side + -- icon = {'X', align='right'} + -- Icon string ^ in table is ignored in filetype component + }, + }, + lualine_y = { + "progress", + }, + lualine_z = { + { + function() + local is_tmux = os.getenv("TMUX") ~= nil + if is_tmux then + return "" + end + return os.date("%H:%M") + end, + }, + { + function() + if not package.loaded["korean_ime"] then + return "" + end + local mode = require("korean_ime").get_mode() + if mode == "en" then + return "A " + elseif mode == "ko" then + return "한" + end + end, + }, + }, + }, + inactive_sections = {}, + tabline = { + lualine_a = { + { + "tabs", + tab_max_length = 40, -- Maximum width of each tab. The content will be shorten dynamically (example: apple/orange -> a/orange) + max_length = vim.o.columns / 3, -- Maximum width of tabs component. + -- Note: + -- It can also be a function that returns + -- the value of `max_length` dynamically. + mode = 0, -- 0: Shows tab_nr + -- 1: Shows tab_name + -- 2: Shows tab_nr + tab_name + + path = nil, -- 0: just shows the filename + -- 1: shows the relative path and shorten $HOME to ~ + -- 2: shows the full path + -- 3: shows the full path and shorten $HOME to ~ + + -- Automatically updates active tab color to match color of other components (will be overidden if buffers_color is set) + use_mode_colors = true, + + -- tabs_color = { + -- -- Same values as the general color option can be used here. + -- active = "lualine_{section}_normal", -- Color for active tab. + -- inactive = "lualine_{section}_inactive", -- Color for inactive tab. + -- }, + -- + show_modified_status = false, -- Shows a symbol next to the tab name if the file has been modified. + symbols = { + modified = "*", -- Text to show when the file is modified. + }, + + fmt = function(name, context) + -- Show + if buffer is modified in tab + local buflist = vim.fn.tabpagebuflist(context.tabnr) + local winnr = vim.fn.tabpagewinnr(context.tabnr) + local bufnr = buflist[winnr] + local mod = vim.fn.getbufvar(bufnr, "&mod") + + return name .. (mod == 1 and " +" or "") + end, + }, + }, + lualine_b = { + { + function() + local function buffer_status() + local buffers = vim.fn.getbufinfo({ buflisted = true }) + local current_buf = vim.fn.bufnr() + local current_buffer_index = 0 + local modified_symbol = vim.bo.modified and "●" or "" + for i, buf in ipairs(buffers) do + if buf.bufnr == current_buf then + current_buffer_index = i + break + end + end + return string.format("%s%d/%d", modified_symbol, current_buffer_index, #buffers) + end + return buffer_status() + end, + }, + }, + lualine_c = { + { + function() + return navic.get_location() + end, + cond = function() + return navic.is_available() + end, + }, + }, + lualine_x = {}, + lualine_y = {}, + lualine_z = {}, + }, + winbar = {}, + inactive_winbar = {}, + extensions = {}, + }) + + local lualine_hidden = true + vim.keymap.set({ "n", "v" }, "<leader>zl", function() + lualine_hidden = not lualine_hidden + require("lualine").hide({ + place = { "statusline", "tabline", "winbar" }, + unhide = lualine_hidden, + }) + end, { desc = "Toggle lualine" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/macro.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/macro.lua new file mode 100644 index 0000000..b69d000 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/macro.lua @@ -0,0 +1,172 @@ +return { + -- { + -- "kr40/nvim-macros", + -- lazy = false, + -- cmd = { "MacroSave", "MacroYank", "MacroSelect", "MacroDelete" }, + -- opts = {}, + -- config = function() + -- require("nvim-macros").setup({ + -- json_file_path = vim.fn.expand("~/.local/share/thesiah/macros.json"), -- Location where the macros will be stored + -- default_macro_register = "q", -- Use as default register for :MacroYank and :MacroSave and :MacroSelect Raw functions + -- json_formatter = "none", -- can be "none" | "jq" | "yq" used to pretty print the json file (jq or yq must be installed!) + -- }) + -- vim.keymap.set("n", "yQ", ":MacroYank<CR>", { desc = "Yank macro" }) + -- vim.keymap.set("n", "<leader>wQ", ":MacroSave<CR>", { desc = "Save macro" }) + -- vim.keymap.set("n", "<leader>fQ", ":MacroSelect<CR>", { desc = "Search macro" }) + -- vim.keymap.set("n", "<leader>xQ", ":MacroDelete<CR>", { desc = "Delete macro" }) + -- end, + -- }, + { + "desdic/macrothis.nvim", + opts = {}, + config = function() + require("macrothis").setup({ + datafile = (function() + local path = vim.fn.expand("~/.local/share/thesiah/macros.json") + + -- Create directory if it doesn't exist + local dir = vim.fn.fnamemodify(path, ":h") + if vim.fn.isdirectory(dir) == 0 then + vim.fn.mkdir(dir, "p") + end + + -- Create file if it doesn't exist or is empty + if vim.fn.filereadable(path) == 0 or vim.fn.getfsize(path) == 0 then + local file = io.open(path, "w") + if file then + file:write("[]") + file:close() + end + end + + return path + end)(), + run_register = "Q", -- content of register z is replaced when running/editing a macro + editor = { -- Edit window + width = 100, + height = 2, + style = "minimal", + border = "rounded", + }, + clipboard_register = '"', + default_register = "q", -- Use this register when loading a macro (will never prompt for register if set) + }) + require("telescope").load_extension("macrothis") + vim.keymap.set("n", "<leader>fq", ":Telescope macrothis<CR>", { desc = "Find macro" }) + end, + keys = { + { + "<Leader>dq", + function() + require("macrothis").delete() + end, + desc = "Delete macro", + }, + { + "<Leader>eq", + function() + require("macrothis").edit() + end, + desc = "Edit macro", + }, + { + "<Leader>lq", + function() + require("macrothis").load() + end, + desc = "Load macro", + }, + { + "<Leader>rnq", + function() + require("macrothis").rename() + end, + desc = "Rename macro", + }, + { + "<Leader>rQ", + function() + require("macrothis").quickfix() + end, + desc = "Run macro on all files in quickfix", + }, + { + "<Leader>rq", + function() + require("macrothis").run() + end, + desc = "Run macro", + }, + { + "<Leader>wq", + function() + require("macrothis").save() + end, + desc = "Save macro", + }, + { + '<Leader>e"', + function() + require("macrothis").register() + end, + desc = "Edit register", + }, + { + 'y"', + function() + require("macrothis").copy_register_printable() + end, + desc = "Copy register as printable", + }, + { + "yq", + function() + require("macrothis").copy_macro_printable() + end, + desc = "Copy macro as printable", + }, + }, + }, + -- { + -- "ecthelionvi/NeoComposer.nvim", + -- dependencies = { "kkharji/sqlite.lua" }, + -- opts = {}, + -- config = function() + -- require("NeoComposer").setup({ + -- notify = true, + -- delay_timer = 150, + -- queue_most_recent = false, + -- window = { + -- width = 80, + -- height = 10, + -- border = "rounded", + -- winhl = { + -- Normal = "ComposerNormal", + -- }, + -- }, + -- colors = { + -- bg = "NONE", + -- fg = "#ff9e64", + -- red = "#ec5f67", + -- blue = "#5fb3b3", + -- green = "#99c794", + -- }, + -- keymaps = { + -- play_macro = "Q", + -- yank_macro = "yq", + -- stop_macro = "cq", + -- toggle_record = "q", + -- cycle_next = "<m-n>", + -- cycle_prev = "<m-p>", + -- toggle_macro_menu = "<m-q>", + -- }, + -- }) + -- + -- require("telescope").load_extension("macros") + -- + -- vim.keymap.set("n", "<leader>sm", ":Telescope macros<CR>", { desc = "Search macros" }) + -- vim.keymap.set("n", "<leader>em", ":EditMacros<CR>", { desc = "Edit macros" }) + -- vim.keymap.set("n", "<leader>xm", ":ClearNeoComposer<CR>", { desc = "Clear macros" }) + -- end, + -- }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua new file mode 100644 index 0000000..3aa19b5 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua @@ -0,0 +1,554 @@ +-- Select the current cell +local function select_cell() + local bufnr = vim.api.nvim_get_current_buf() + local current_row = vim.api.nvim_win_get_cursor(0)[1] + local current_col = vim.api.nvim_win_get_cursor(0)[2] + + local start_line = nil + local end_line = nil + local line_count = vim.api.nvim_buf_line_count(bufnr) + + -- Find the start of the cell (looking for opening markers or headers) + for line = current_row, 1, -1 do + local line_content = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)[1] + if line_content:match("^```%s*[%w_%-]+") then + start_line = line + break + end + end + + -- If no start line is found, assume start of the file + if not start_line then + start_line = 1 + end + + -- Find the end of the cell (looking for the next opening marker or header) + for line = start_line + 1, line_count do + local line_content = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)[1] + if line_content:match("^```%s*[%w_%-]+") then + end_line = line - 1 + break + end + end + + -- If no end line is found, assume end of the file + if not end_line then + end_line = line_count + end + + return current_row, current_col, start_line, end_line +end + +-- Delete the current cell +local function delete_cell() + local _, _, start_line, end_line = select_cell() -- Use select_cell to get start and end lines of the cell + if start_line and end_line then + -- Move cursor to the start of the cell + vim.api.nvim_win_set_cursor(0, { start_line, 0 }) + + -- Enter visual line mode to select the cell + vim.cmd("normal! V") + -- Move cursor to the end of the cell to extend selection + vim.api.nvim_win_set_cursor(0, { end_line, 0 }) + + -- Delete the selected lines + vim.cmd("normal! d") + end +end + +-- Navigate to the next or previous cell +local function navigate_cell(up) + local bufnr = vim.api.nvim_get_current_buf() + local line_count = vim.api.nvim_buf_line_count(bufnr) + local _, _, start_line, end_line = select_cell() -- Get the start and end lines of the current cell + + local target_line = nil + + if up then + -- Find the previous cell start, skipping any closing markers + for line = start_line - 1, 1, -1 do + local line_content = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)[1] + if line_content:match("^```%s*[%w_%-]+") or line_content:match("^%s*#+%s") then + target_line = line + break + end + end + else + -- Find the next cell start, skipping any closing markers + for line = end_line + 1, line_count do + local line_content = vim.api.nvim_buf_get_lines(bufnr, line - 1, line, false)[1] + if line_content:match("^```%s*[%w_%-]+") or line_content:match("^%s*#+%s") then + target_line = line + break + end + end + end + + -- Navigate to the target line if found, otherwise stay at the current position + if target_line then + -- If the target is a code block, move cursor to the line right after the opening marker + local target_line_content = vim.api.nvim_buf_get_lines(bufnr, target_line - 1, target_line, false)[1] + if target_line_content:match("^```%s*[%w_%-]+") then + vim.api.nvim_win_set_cursor(0, { target_line + 1, 0 }) -- Move inside the code block + else + vim.api.nvim_win_set_cursor(0, { target_line, 0 }) -- Move to the markdown header line + end + else + if up then + vim.api.nvim_win_set_cursor(0, { 1, 0 }) -- Move to start of file if no previous cell found + else + vim.api.nvim_win_set_cursor(0, { line_count, 0 }) -- Move to end of file if no next cell found + end + end +end + +-- Insert a new cell with specific content +local function insert_cell(content) + local _, _, _, end_line = select_cell() + local bufnr = vim.api.nvim_get_current_buf() + local line = end_line + if end_line ~= 1 then + line = end_line - 1 + vim.api.nvim_win_set_cursor(0, { end_line - 1, 0 }) + else + line = end_line + vim.api.nvim_win_set_cursor(0, { end_line, 0 }) + end + + vim.cmd("normal!2o") + vim.api.nvim_buf_set_lines(bufnr, line, line + 1, false, { content }) + vim.cmd("normal!2o") + vim.cmd("normal!k") +end + +-- Insert a new code cell +local function insert_code_cell() + insert_cell("```python") -- For regular code cells +end + +return { + { + "ixru/nvim-markdown", + config = function() + vim.g.vim_markdown_no_default_key_mappings = 1 + end, + }, + { + "MeanderingProgrammer/render-markdown.nvim", + -- dependencies = { "nvim-treesitter/nvim-treesitter", "echasnovski/mini.nvim" }, -- if you use the mini.nvim suite + dependencies = { "nvim-treesitter/nvim-treesitter", "echasnovski/mini.icons" }, -- if you use standalone mini plugins + -- dependencies = { 'nvim-treesitter/nvim-treesitter', 'nvim-tree/nvim-web-devicons' }, -- if you prefer nvim-web-devicons + ---@module 'render-markdown' + ---@type render.md.UserConfig + opts = {}, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>mr", group = "Markdown render" }, + }) + end, + config = function() + -- require("obsidian").get_client().opts.ui.enable = false + -- vim.api.nvim_buf_clear_namespace(0, vim.api.nvim_get_namespaces()["ObsidianUI"], 0, -1) + require("render-markdown").setup({ + bullet = { + -- Turn on / off list bullet rendering + enabled = false, + }, + code = { + enabled = true, -- disable code rendering for .ipynb files + sign = true, + -- Width of the code block background. + -- | block | width of the code block | + -- | full | full width of the window | + width = "block", + }, + file_types = { "markdown", "vimwiki" }, + heading = { + enabled = true, + sign = false, + icons = { "", "", "", "", "", "" }, + -- icons = { " ", " ", " ", " ", " ", " " }, + }, + ignore = function(bufnr) + local name = vim.api.nvim_buf_get_name(bufnr) + return name:lower():match("%.ipynb$") ~= nil + end, + }) + + vim.treesitter.language.register("markdown", "vimwiki") + + local opts = { noremap = true, silent = true } + vim.keymap.set("n", "<leader>mrt", function() + require("render-markdown").buf_toggle() + end, vim.tbl_extend("force", opts, { desc = "Toggle render-markdown" })) + vim.keymap.set("n", "<leader>mre", function() + require("render-markdown").buf_enable() + end, vim.tbl_extend("force", opts, { desc = "Enable render-markdown" })) + vim.keymap.set("n", "<leader>mrx", function() + require("render-markdown").buf_disable() + end, vim.tbl_extend("force", opts, { desc = "Disable render-markdown" })) + vim.keymap.set("n", "<leader>mr+", function() + require("render-markdown").expand() + end, vim.tbl_extend("force", opts, { desc = "Expand conceal margin" })) + vim.keymap.set("n", "<leader>mr-", function() + require("render-markdown").contract() + end, vim.tbl_extend("force", opts, { desc = "Contract conceal margin" })) + vim.keymap.set("n", "<leader>mrl", function() + require("render-markdown").log() + end, vim.tbl_extend("force", opts, { desc = "Open render-markdown log" })) + vim.keymap.set("n", "<leader>mrc", function() + require("render-markdown").config() + end, vim.tbl_extend("force", opts, { desc = "Show render-markdown config diff" })) + vim.keymap.set("n", "<leader>mrd", function() + require("render-markdown").debug() + end, vim.tbl_extend("force", opts, { desc = "Debug render-markdown marks" })) + end, + }, + { + -- Install markdown preview, use npm if available. + "iamcco/markdown-preview.nvim", + cmd = { "MarkdownPreviewToggle", "MarkdownPreview", "MarkdownPreviewStop" }, + ft = { "markdown" }, + build = function(plugin) + if vim.fn.executable("npm") then + vim.cmd("!cd " .. plugin.dir .. " && cd app && npm install") + else + vim.cmd([[Lazy load markdown-preview.nvim]]) + vim.fn["mkdp#util#install"]() + end + end, + init = function() + if vim.fn.executable("npm") then + vim.g.mkdp_filetypes = { "markdown" } + end + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>m", group = "Markdown/Map" }, + }) + end, + keys = { + { "<leader>mp", "<Cmd>MarkdownPreview<CR>", desc = "Markdown preview" }, + { "<leader>mx", "<Cmd>MarkdownPreviewStop<CR>", desc = "Markdown stop" }, + { "<leader>md", "<Cmd>MarkdownPreviewToggle<CR>", desc = "Markdown toggle" }, + }, + }, + { + "brianhuster/live-preview.nvim", + dependencies = { + -- You can choose one of the following pickers + "nvim-telescope/telescope.nvim", + -- "ibhagwan/fzf-lua", + -- "echasnovski/mini.pick", + }, + cmd = { "LivePreview start", "LivePreview close", "LivePreview pick", "LivePreview help" }, + init = function() + if vim.fn.executable("npm") then + vim.g.mkdp_filetypes = { "markdown" } + end + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>ml", group = "Markdown live" }, + }) + end, + keys = { + { "<leader>mlp", "<Cmd>LivePreview start<CR>", desc = "Markdown live preview" }, + { "<leader>mlx", "<Cmd>LivePreview close<CR>", desc = "Markdown live close" }, + { "<leader>mlc", "<Cmd>LivePreview pick<CR>", desc = "Markdown live pick" }, + { "<leader>mlh", "<Cmd>LivePreview help<CR>", desc = "Markdown live help" }, + }, + }, + { + "ellisonleao/glow.nvim", + cmd = "Glow", + config = function() + require("glow").setup({ + border = "single", -- floating window border config + style = "dark", -- filled automatically with your current editor background, you can override using glow json style + }) + end, + keys = { + { "<leader>mf", "<Cmd>Glow<CR>", desc = "Floating markdown preview" }, + }, + }, + { + "dhruvasagar/vim-open-url", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "g<CR>", group = "Search word under curosr" }, + { "gB", group = "Open url in browser" }, + { "gG", group = "Google search word under cursor" }, + { "gW", group = "Wikipedia search word under cursor" }, + }) + end, + }, + { + "AckslD/nvim-FeMaco.lua", + config = function() + require("femaco").setup() + end, + }, + { + "goerz/jupytext.nvim", + version = "0.2.0", + lazy = false, + config = function() + require("jupytext").setup({ + jupytext = "jupytext", + format = "markdown", + update = true, + filetype = require("jupytext").get_filetype, + new_template = require("jupytext").default_new_template(), + sync_patterns = { "*.md", "*.py", "*.jl", "*.R", "*.Rmd", "*.qmd" }, + autosync = true, + handle_url_schemes = true, + }) + end, + keys = { + { "<A-i>", insert_code_cell, desc = "Insert Code Cell" }, + { "<A-x>", delete_cell, desc = "Delete Cell" }, + { + "<S-Tab>", + function() + navigate_cell(true) + end, + desc = "Previous Cell", + }, + { "<Tab>", navigate_cell, desc = "Next Cell" }, + }, + }, + { + "vhyrro/luarocks.nvim", + priority = 1001, -- this plugin needs to run before anything else + init = function() + package.path = package.path + .. ";" + .. vim.fn.expand("$HOME") + .. "/.config/luarocks/share/lua/5.1/magick/init.lua;" + end, + opt = { + rocks = { "magick" }, + }, + }, + { "benlubas/image-save.nvim", cmd = "SaveImage" }, + { + "3rd/image.nvim", + build = build, + dependencies = { "leafo/magick", "vhyrro/luarocks.nvim" }, + config = function() + require("image").setup({ + backend = "ueberzug", -- "ueberzug" or "kitty", whatever backend you would like to use + processor = "magick_rock", -- "magick_rock" or "magick_cli" + integrations = { + markdown = { + enabled = true, + clear_in_insert_mode = false, + download_remote_images = false, + only_render_image_at_cursor = false, + floating_windows = false, -- if true, images will be rendered in floating markdown windows + filetypes = { "markdown", "quarto" }, -- markdown extensions (ie. quarto) can go here + }, + neorg = { + enabled = true, + filetypes = { "norg" }, + }, + typst = { + enabled = true, + filetypes = { "typst" }, + }, + html = { + enabled = false, + }, + css = { + enabled = false, + }, + }, + max_width = 100, + max_height = 8, + max_height_window_percentage = math.huge, + max_width_window_percentage = math.huge, + window_overlap_clear_enabled = true, -- toggles images when windows are overlapped + window_overlap_clear_ft_ignore = { "cmp_menu", "cmp_docs", "fidget", "" }, + editor_only_render_when_focused = true, -- auto show/hide images when the editor gains/looses focus + tmux_show_only_in_active_window = true, -- auto show/hide images in the correct Tmux window (needs visual-activity off) + hijack_file_patterns = { "*.png", "*.jpg", "*.jpeg", "*.gif", "*.webp", "*.avif" }, -- render image files as images when opened + }) + end, + }, + { + "quarto-dev/quarto-nvim", + dependencies = { + { + "jmbuhr/otter.nvim", + lazy = false, + dependencies = { + "nvim-treesitter/nvim-treesitter", + }, + opts = {}, + config = function() + require("otter").setup() + end, + }, + "hrsh7th/nvim-cmp", + "neovim/nvim-lspconfig", + }, + ft = { "quarto", "markdown" }, + command = "QuartoActivate", + config = function() + require("quarto").setup({ + debug = false, + closePreviewOnExit = true, + lspFeatures = { + languages = { "r", "python", "rust" }, + chunks = "all", + diagnostics = { + enabled = true, + triggers = { "BufWritePost" }, + }, + completion = { + enabled = true, + }, + }, + keymap = { + hover = "H", + definition = "gd", + rename = "<leader>rn", + references = "gr", + format = "<leader>gf", + }, + codeRunner = { + enabled = true, + default_method = "molten", + ft_runners = { + bash = "slime", + python = "molten", + }, + never_run = { "yaml" }, -- filetypes which are never sent to a code runner + }, + }) + local runner = require("quarto.runner") + vim.keymap.set("n", "<leader>jc", runner.run_cell, { silent = true, desc = "Run cell" }) + vim.keymap.set("n", "<leader>jC", runner.run_above, { silent = true, desc = "Run above cell" }) + vim.keymap.set("n", "<leader>jl", runner.run_line, { silent = true, desc = "Run line" }) + vim.keymap.set("v", "<leader>jv", runner.run_range, { silent = true, desc = "Run block" }) + vim.keymap.set("n", "<leader>ja", runner.run_all, { silent = true, desc = "Run all" }) + vim.keymap.set("n", "<leader>jA", function() + runner.run_all(true) + end, { desc = "run all cells of all languages", silent = true }) + vim.keymap.set( + "n", + "<leader>jp", + require("quarto").quartoPreview, + { noremap = true, silent = true, desc = "Preview the quarto document" } + ) + -- to create a cell in insert mode, I have the ` snippet + vim.keymap.set( + "n", + "<leader>cc", + "i```python\n```<Esc>O", + { silent = true, desc = "Create a new code cell" } + ) + vim.keymap.set( + "n", + "<leader>cs", + "i```\r\r```{}<left>", + { noremap = true, silent = true, desc = "Split code cell" } + ) + end, + }, + { + "benlubas/molten-nvim", + version = "^1.0.0", -- use version <2.0.0 to avoid breaking changes + dependencies = { "3rd/image.nvim" }, + build = ":UpdateRemotePlugins", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>j", group = "Molten (Jupyter)" }, + }) + + vim.g.molten_auto_image_popup = true + vim.g.molten_auto_init_behavior = "raise" + vim.g.molten_auto_open_html_in_browser = false + -- I find auto open annoying, keep in mind setting this option will require setting + -- a keybind for `:noautocmd MoltenEnterOutput` to open the output again + vim.g.molten_auto_open_output = false + vim.g.molten_cover_empty_lines = false + vim.g.molten_cover_lines_starting_with = {} + vim.g.molten_copy_output = false + vim.g.molten_enter_output_behavior = "open_then_enter" + -- this guide will be using image.nvim + -- Don't forget to setup and install the plugin if you want to view image outputs + vim.g.molten_image_provider = "image.nvim" + vim.g.molten_output_show_more = false + vim.g.molten_output_win_max_height = 30 + vim.g.molten_output_win_style = "minimal" + -- this will make it so the output shows up below the \`\`\` cell delimiter + vim.g.molten_virt_lines_off_by_1 = true + -- Output as virtual text. Allows outputs to always be shown, works with images, but can + -- be buggy with longer images + vim.g.molten_virt_text_output = true + -- optional, works for virt text and the output window + vim.g.molten_wrap_output = true + vim.g.molten_virt_text_max_lines = 20 + end, + config = function() + -- image nvim options table. Pass to `require('image').setup` + vim.keymap.set("n", "<leader>jJ", ":MoltenInit<CR>", { silent = true, desc = "Init molten" }) + vim.keymap.set("n", "<leader>j[", ":MoltenPrev<CR>", { silent = true, desc = "Go to prev code cell" }) + vim.keymap.set("n", "<leader>j]", ":MoltenNext<CR>", { silent = true, desc = "Go to next code cell" }) + vim.keymap.set( + "n", + "<leader>jo", + ":MoltenEvaluateOperator<CR>", + { silent = true, desc = "Evaluate operator" } + ) + vim.keymap.set("n", "<leader>jL", ":MoltenEvaluateLine<CR>", { silent = true, desc = "Evaluate line" }) + vim.keymap.set("n", "<leader>jr", ":MoltenReevaluateCell<CR>", { silent = true, desc = "Re-evaluate cell" }) + vim.keymap.set( + "v", + "<leader>jV", + ":<C-u>MoltenEvaluateVisual<CR>gv<Esc>", + { silent = true, desc = "Evaluate visual block" } + ) + vim.keymap.set("n", "<leader>jd", ":MoltenDelete<CR>", { silent = true, desc = "Delete molten" }) + vim.keymap.set("n", "<leader>js", ":MoltenShowOutput<CR>", { silent = true, desc = "Show output" }) + vim.keymap.set("n", "<leader>jh", ":MoltenHideOutput<CR>", { silent = true, desc = "Hide output" }) + vim.keymap.set( + "n", + "<leader>jm", + ":noautocmd MoltenEnterOutput<CR>", + { silent = true, desc = "Enter output" } + ) + vim.api.nvim_create_autocmd("User", { + pattern = "MoltenInitPost", + callback = function() + require("quarto").activate() + end, + }) + vim.keymap.set("n", "<leader>ji", ":MoltenImagePopup<CR>", { silent = true, desc = "Pop-up image" }) + vim.keymap.set("n", "<leader>jw", ":MoltenOpenInBrowser<CR>", { silent = true, desc = "Open in browser" }) + vim.keymap.set("n", "<leader>jj", function() + local venv_path = os.getenv("VIRTUAL_ENV") + if venv_path then + local venv_name = vim.fn.fnamemodify(venv_path, ":t") + vim.cmd(("MoltenInit %s"):format(venv_name)) + else + vim.cmd("MoltenInit /opt/homebrew/bin/python@3.13") + end + end, { desc = "Init default molten" }) + end, + }, + { + "mipmip/vim-scimark", + config = function() + vim.keymap.set("n", "<leader>si", ":OpenInScim<cr>", { desc = "Sc-im" }) + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/marks.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/marks.lua new file mode 100644 index 0000000..d59d0f1 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/marks.lua @@ -0,0 +1,16 @@ +return { + "chentoast/marks.nvim", + config = function() + require("marks").setup() + end, + init = function() + local wk = require("which-key") + wk.add({ + { + mode = { "n", "v" }, + { "m", group = "Marks" }, + { "dm", desc = "Delete marks" }, + }, + }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua new file mode 100644 index 0000000..993b02c --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua @@ -0,0 +1,1178 @@ +-- Updated pattern to match what Echasnovski has in the documentation +-- https://github.com/echasnovski/mini.nvim/blob/c6eede272cfdb9b804e40dc43bb9bff53f38ed8a/doc/mini-files.txt#L508-L529 + +-- Define a function to update MiniJump highlight based on Search +local function update_mini_jump_highlight() + local search_hl = vim.api.nvim_get_hl(0, { name = "Search" }) + vim.api.nvim_set_hl(0, "MiniJump", { + fg = search_hl.fg, + bg = search_hl.bg, + bold = search_hl.bold or false, + }) +end + +return { + { + "echasnovski/mini.ai", + version = false, + config = function() + require("mini.ai").setup({ + -- Table with textobject id as fields, textobject specification as values. + -- Also use this to disable builtin textobjects. See |MiniAi.config|. + custom_textobjects = nil, + + -- Module mappings. Use `''` (empty string) to disable one. + mappings = { + -- Main textobject prefixes + around = "a", + inside = "i", + + -- Next/last variants + around_next = "an", + inside_next = "in", + around_last = "al", + inside_last = "il", + + -- Move cursor to corresponding edge of `a` textobject + goto_left = "g[", + goto_right = "g]", + }, + + -- Number of lines within which textobject is searched + n_lines = 50, + + -- How to search for object (first inside current line, then inside + -- neighborhood). One of 'cover', 'cover_or_next', 'cover_or_prev', + -- 'cover_or_nearest', 'next', 'previous', 'nearest'. + search_method = "cover_or_next", + + -- Whether to disable showing non-error feedback + -- This also affects (purely informational) helper messages shown after + -- idle time if user input is required. + silent = false, + }) + end, + }, + { + "echasnovski/mini.bracketed", + version = false, + config = function() + require("mini.bracketed").setup({ + buffer = { suffix = "", options = {} }, + comment = { suffix = "", options = {} }, + conflict = { suffix = "", options = {} }, + diagnostic = { suffix = "", options = {} }, + file = { suffix = "", options = {} }, + indent = { suffix = "", options = {} }, + jump = { suffix = "", options = {} }, + location = { suffix = "", options = {} }, + oldfile = { suffix = "", options = {} }, + quickfix = { suffix = "", options = {} }, + treesitter = { suffix = "", options = {} }, + undo = { suffix = "", options = {} }, + window = { suffix = "", options = {} }, + yank = { suffix = "", options = {} }, + }) + + vim.keymap.set("n", "<leader>[B", "<Cmd>lua MiniBracketed.buffer('first')<cr>", { desc = "Buffer first" }) + vim.keymap.set( + "n", + "<leader>[b", + "<Cmd>lua MiniBracketed.buffer('backward')<cr>", + { desc = "Buffer backward" } + ) + vim.keymap.set( + "n", + "<leader>]b", + "<Cmd>lua MiniBracketed.buffer('forward')<cr>", + { desc = "Buffer forward" } + ) + vim.keymap.set("n", "<leader>]B", "<Cmd>lua MiniBracketed.buffer('last')<cr>", { desc = "Buffer last" }) + vim.keymap.set("n", "<leader>[C", "<Cmd>lua MiniBracketed.comment('first')<cr>", { desc = "Comment first" }) + vim.keymap.set( + "n", + "<leader>[c", + "<Cmd>lua MiniBracketed.comment('backward')<cr>", + { desc = "Comment backward" } + ) + vim.keymap.set( + "n", + "<leader>]c", + "<Cmd>lua MiniBracketed.comment('forward')<cr>", + { desc = "Comment forward" } + ) + vim.keymap.set("n", "<leader>]C", "<Cmd>lua MiniBracketed.comment('last')<cr>", { desc = "Comment last" }) + vim.keymap.set( + "n", + "<leader>[X", + "<Cmd>lua MiniBracketed.conflict('first')<cr>", + { desc = "Conflict first" } + ) + vim.keymap.set( + "n", + "<leader>[x", + "<Cmd>lua MiniBracketed.conflict('backward')<cr>", + { desc = "Conflict backward" } + ) + vim.keymap.set( + "n", + "<leader>]x", + "<Cmd>lua MiniBracketed.conflict('forward')<cr>", + { desc = "Conflict forward" } + ) + vim.keymap.set("n", "<leader>]X", "<Cmd>lua MiniBracketed.conflict('last')<cr>", { desc = "Conflict last" }) + vim.keymap.set( + "n", + "<leader>[D", + "<Cmd>lua MiniBracketed.diagnostic('first')<cr>", + { desc = "Diagnostic first" } + ) + vim.keymap.set( + "n", + "<leader>[d", + "<Cmd>lua MiniBracketed.diagnostic('backward')<cr>", + { desc = "Diagnostic backward" } + ) + vim.keymap.set( + "n", + "<leader>]d", + "<Cmd>lua MiniBracketed.diagnostic('forward')<cr>", + { desc = "Diagnostic forward" } + ) + vim.keymap.set( + "n", + "<leader>]D", + "<Cmd>lua MiniBracketed.diagnostic('last')<cr>", + { desc = "Diagnostic last" } + ) + vim.keymap.set("n", "<leader>[F", "<Cmd>lua MiniBracketed.file('first')<cr>", { desc = "File first" }) + vim.keymap.set("n", "<leader>[f", "<Cmd>lua MiniBracketed.file('backward')<cr>", { desc = "File backward" }) + vim.keymap.set("n", "<leader>]f", "<Cmd>lua MiniBracketed.file('forward')<cr>", { desc = "File forward" }) + vim.keymap.set("n", "<leader>]F", "<Cmd>lua MiniBracketed.file('last')<cr>", { desc = "File last" }) + vim.keymap.set("n", "<leader>[I", "<Cmd>lua MiniBracketed.indent('first')<cr>", { desc = "Indent first" }) + vim.keymap.set( + "n", + "<leader>[i", + "<Cmd>lua MiniBracketed.indent('backward')<cr>", + { desc = "Indent backward" } + ) + vim.keymap.set( + "n", + "<leader>]i", + "<Cmd>lua MiniBracketed.indent('forward')<cr>", + { desc = "Indent forward" } + ) + vim.keymap.set("n", "<leader>]I", "<Cmd>lua MiniBracketed.indent('last')<cr>", { desc = "Indent last" }) + vim.keymap.set("n", "<leader>[J", "<Cmd>lua MiniBracketed.jump('first')<cr>", { desc = "Jump first" }) + vim.keymap.set("n", "<leader>[j", "<Cmd>lua MiniBracketed.jump('backward')<cr>", { desc = "Jump backward" }) + vim.keymap.set("n", "<leader>]j", "<Cmd>lua MiniBracketed.jump('forward')<cr>", { desc = "Jump forward" }) + vim.keymap.set("n", "<leader>]J", "<Cmd>lua MiniBracketed.jump('last')<cr>", { desc = "Jump last" }) + vim.keymap.set( + "n", + "<leader>[L", + "<Cmd>lua MiniBracketed.location('first')<cr>", + { desc = "Location first" } + ) + vim.keymap.set( + "n", + "<leader>[l", + "<Cmd>lua MiniBracketed.location('backward')<cr>", + { desc = "Location backward" } + ) + vim.keymap.set( + "n", + "<leader>]l", + "<Cmd>lua MiniBracketed.location('forward')<cr>", + { desc = "Location forward" } + ) + vim.keymap.set("n", "<leader>]L", "<Cmd>lua MiniBracketed.location('last')<cr>", { desc = "Location last" }) + vim.keymap.set("n", "<leader>[O", "<Cmd>lua MiniBracketed.oldfile('first')<cr>", { desc = "Oldfile first" }) + vim.keymap.set( + "n", + "<leader>[o", + "<Cmd>lua MiniBracketed.oldfile('backward')<cr>", + { desc = "Oldfile backward" } + ) + vim.keymap.set( + "n", + "<leader>]o", + "<Cmd>lua MiniBracketed.oldfile('forward')<cr>", + { desc = "Oldfile forward" } + ) + vim.keymap.set("n", "<leader>]O", "<Cmd>lua MiniBracketed.oldfile('last')<cr>", { desc = "Oldfile last" }) + vim.keymap.set( + "n", + "<leader>[Q", + "<Cmd>lua MiniBracketed.quickfix('first')<cr>", + { desc = "Quickfix first" } + ) + vim.keymap.set( + "n", + "<leader>[q", + "<Cmd>lua MiniBracketed.quickfix('backward')<cr>", + { desc = "Quickfix backward" } + ) + vim.keymap.set( + "n", + "<leader>]q", + "<Cmd>lua MiniBracketed.quickfix('forward')<cr>", + { desc = "Quickfix forward" } + ) + vim.keymap.set("n", "<leader>]Q", "<Cmd>lua MiniBracketed.quickfix('last')<cr>", { desc = "Quickfix last" }) + vim.keymap.set( + "n", + "<leader>[T", + "<Cmd>lua MiniBracketed.treesitter('first')<cr>", + { desc = "Treesitter first" } + ) + vim.keymap.set( + "n", + "<leader>[t", + "<Cmd>lua MiniBracketed.treesitter('backward')<cr>", + { desc = "Treesitter backward" } + ) + vim.keymap.set( + "n", + "<leader>]t", + "<Cmd>lua MiniBracketed.treesitter('forward')<cr>", + { desc = "Treesitter forward" } + ) + vim.keymap.set( + "n", + "<leader>]T", + "<Cmd>lua MiniBracketed.treesitter('last')<cr>", + { desc = "Treesitter last" } + ) + vim.keymap.set("n", "<leader>[U", "<Cmd>lua MiniBracketed.undo('first')<cr>", { desc = "Undo first" }) + vim.keymap.set("n", "<leader>[u", "<Cmd>lua MiniBracketed.undo('backward')<cr>", { desc = "Undo backward" }) + vim.keymap.set("n", "<leader>]u", "<Cmd>lua MiniBracketed.undo('forward')<cr>", { desc = "Undo forward" }) + vim.keymap.set("n", "<leader>]U", "<Cmd>lua MiniBracketed.undo('last')<cr>", { desc = "Undo last" }) + vim.keymap.set("n", "<leader>w0", "<Cmd>lua MiniBracketed.window('first')<cr>", { desc = "Window first" }) + vim.keymap.set( + "n", + "<leader>w[", + "<Cmd>lua MiniBracketed.window('backward')<cr>", + { desc = "Window backward" } + ) + vim.keymap.set( + "n", + "<leader>w]", + "<Cmd>lua MiniBracketed.window('forward')<cr>", + { desc = "Window forward" } + ) + vim.keymap.set("n", "<leader>w$", "<Cmd>lua MiniBracketed.window('last')<cr>", { desc = "Window last" }) + vim.keymap.set("n", "<leader>[Y", "<Cmd>lua MiniBracketed.yank('first')<cr>", { desc = "Yank first" }) + vim.keymap.set("n", "<leader>[y", "<Cmd>lua MiniBracketed.yank('backward')<cr>", { desc = "Yank backward" }) + vim.keymap.set("n", "<leader>]y", "<Cmd>lua MiniBracketed.yank('forward')<cr>", { desc = "Yank forward" }) + vim.keymap.set("n", "<leader>]Y", "<Cmd>lua MiniBracketed.yank('last')<cr>", { desc = "Yank last" }) + end, + }, + { + "echasnovski/mini.files", + opts = { + -- I didn't like the default mappings, so I modified them + -- Module mappings created only inside explorer. + -- Use `''` (empty string) to not create one. + mappings = { + close = "q", + -- Use this if you want to open several files + go_in = "l", + -- This opens the file, but quits out of mini.files (default L) + go_in_plus = "<CR>", + -- I swapped the following 2 (default go_out: h) + -- go_out_plus: when you go out, it shows you only 1 item to the right + -- go_out: shows you all the items to the right + go_out = "H", + go_out_plus = "h", + -- Default <BS> + reset = ",", + -- Default @ + reveal_cwd = ".", + show_help = "g?", + -- Default = + synchronize = "s", + trim_left = "<", + trim_right = ">", + toggle_hidden = nil, + change_cwd = nil, + go_in_horizontal = nil, + go_in_vertical = nil, + go_in_horizontal_plus = nil, + go_in_vertical_plus = nil, + }, + options = { + use_as_default_explorer = true, + permanent_delete = false, + }, + windows = { + preview = true, + width_focus = 25, + width_preview = 40, + }, + }, + keys = { + { + "<leader>ee", + function() + if not MiniFiles.close() then + require("mini.files").open(vim.api.nvim_buf_get_name(0), true) + end + end, + desc = "Open mini.files", + }, + { + "<leader>eE", + function() + require("mini.files").open(vim.uv.cwd(), true) + end, + desc = "Open mini.files (cwd)", + }, + }, + config = function(_, opts) + require("mini.files").setup(opts) + + local show_dotfiles = true + local filter_show = function(fs_entry) + return true + end + local filter_hide = function(fs_entry) + return not vim.startswith(fs_entry.name, ".") + end + + local toggle_dotfiles = function() + show_dotfiles = not show_dotfiles + local new_filter = show_dotfiles and filter_show or filter_hide + require("mini.files").refresh({ content = { filter = new_filter } }) + end + + local map_split = function(buf_id, lhs, direction, close_on_file) + local rhs = function() + local new_target_window + local cur_target_window = require("mini.files").get_explorer_state().arget_window + + if cur_target_window ~= nil then + vim.api.nvim_win_call(cur_target_window, function() + vim.cmd("belowright " .. direction .. " split") + new_target_window = vim.api.nvim_get_current_win() + end) + + require("mini.files").set_target_window(new_target_window) + require("mini.files").go_in({ close_on_file = close_on_file }) + end + end + + local desc = "Open in " .. direction .. " split" + if close_on_file then + desc = desc .. " and close" + end + vim.keymap.set("n", lhs, rhs, { buffer = buf_id, desc = desc }) + end + + local files_set_cwd = function() + local cur_entry_path = MiniFiles.get_fs_entry().path + local cur_directory = vim.fs.dirname(cur_entry_path) + if cur_directory ~= nil then + vim.fn.chdir(cur_directory) + end + end + + local mini_files = require("mini.files") + local tmux_pane_function = require("TheSiahxyz.utils.tmux").tmux_pane_function + + local open_tmux_pane = function() + local curr_entry = mini_files.get_fs_entry() + if curr_entry then + if curr_entry.fs_type == "directory" then + tmux_pane_function(curr_entry.path) + elseif curr_entry.fs_type == "file" then + local parent_dir = vim.fn.fnamemodify(curr_entry.path, ":h") + tmux_pane_function(parent_dir) + elseif curr_entry.fs_type == "link" then + local resolved_path = vim.fn.resolve(curr_entry.path) + if vim.fn.isdirectory(resolved_path) == 1 then + tmux_pane_function(resolved_path) + else + local parent_dir = vim.fn.fnamemodify(resolved_path, ":h") + tmux_pane_function(parent_dir) + end + else + vim.notify("Unsupported file system entry type", vim.log.levels.WARN) + end + else + vim.notify("No entry selected", vim.log.levels.WARN) + end + end + + local copy_to_clipboard = function() + local curr_entry = mini_files.get_fs_entry() + if curr_entry then + local path = curr_entry.path + -- Escape the path for shell command + local escaped_path = vim.fn.fnameescape(path) + local cmd = vim.fn.has("mac") == 1 + and string.format([[osascript -e 'set the clipboard to POSIX file "%s"']], escaped_path) + or string.format([[echo -n %s | xclip -selection clipboard]], escaped_path) + local result = vim.fn.system(cmd) + if vim.v.shell_error ~= 0 then + vim.notify("Copy failed: " .. result, vim.log.levels.ERROR) + else + vim.notify(vim.fn.fnamemodify(path, ":t"), vim.log.levels.INFO) + vim.notify("Copied to system clipboard", vim.log.levels.INFO) + end + else + vim.notify("No file or directory selected", vim.log.levels.WARN) + end + end + + local zip_and_copy_to_clipboard = function() + local curr_entry = require("mini.files").get_fs_entry() + if curr_entry then + local path = curr_entry.path + local name = vim.fn.fnamemodify(path, ":t") -- Extract the file or directory name + local parent_dir = vim.fn.fnamemodify(path, ":h") -- Get the parent directory + local timestamp = os.date("%y%m%d%H%M%S") -- Append timestamp to avoid duplicates + local zip_path = string.format("/tmp/%s_%s.zip", name, timestamp) -- Path in macOS's tmp directory + -- Create the zip file + local zip_cmd = string.format( + "cd %s && zip -r %s %s", + vim.fn.shellescape(parent_dir), + vim.fn.shellescape(zip_path), + vim.fn.shellescape(name) + ) + local result = vim.fn.system(zip_cmd) + if vim.v.shell_error ~= 0 then + vim.notify("Failed to create zip file: " .. result, vim.log.levels.ERROR) + return + end + -- Copy the zip file to the system clipboard + local copy_cmd = vim.fn.has("mac") == 1 + and string.format([[osascript -e 'set the clipboard to POSIX file "%s"']], zip_path) + or string.format([[echo -n %s | xclip -selection clipboard]], zip_path) + local copy_result = vim.fn.system(copy_cmd) + if vim.v.shell_error ~= 0 then + vim.notify("Failed to copy zip file to clipboard: " .. copy_result, vim.log.levels.ERROR) + return + end + vim.notify(zip_path, vim.log.levels.INFO) + vim.notify("Zipped and copied to clipboard: ", vim.log.levels.INFO) + else + vim.notify("No file or directory selected", vim.log.levels.WARN) + end + end + + local paste_from_clipboard = function() + -- vim.notify("Starting the paste operation...", vim.log.levels.INFO) + if not mini_files then + vim.notify("mini.files module not loaded.", vim.log.levels.ERROR) + return + end + local curr_entry = mini_files.get_fs_entry() -- Get the current file system entry + if not curr_entry then + vim.notify("Failed to retrieve current entry in mini.files.", vim.log.levels.ERROR) + return + end + local curr_dir = curr_entry.fs_type == "directory" and curr_entry.path + or vim.fn.fnamemodify(curr_entry.path, ":h") -- Use parent directory if entry is a file + -- vim.notify("Current directory: " .. curr_dir, vim.log.levels.INFO) + local script = [[ +tell application "System Events" + try + set theFile to the clipboard as alias + set posixPath to POSIX path of theFile + return posixPath + on error + return "error" + end try +end tell +]] + local output = vim.fn.has("mac") == 1 and vim.fn.system("osascript -e " .. vim.fn.shellescape(script)) + or vim.fn.system("xclip -o -selection clipboard") + if vim.v.shell_error ~= 0 or output:find("error") then + vim.notify("Clipboard does not contain a valid file or directory.", vim.log.levels.WARN) + return + end + local source_path = output:gsub("%s+$", "") -- Trim whitespace from clipboard output + if source_path == "" then + vim.notify("Clipboard is empty or invalid.", vim.log.levels.WARN) + return + end + local dest_path = curr_dir .. "/" .. vim.fn.fnamemodify(source_path, ":t") -- Destination path in current directory + local copy_cmd = vim.fn.isdirectory(source_path) == 1 and { "cp", "-R", source_path, dest_path } + or { "cp", source_path, dest_path } -- Construct copy command + local result = vim.fn.system(copy_cmd) -- Execute the copy command + if vim.v.shell_error ~= 0 then + vim.notify("Paste operation failed: " .. result, vim.log.levels.ERROR) + return + end + -- vim.notify("Pasted " .. source_path .. " to " .. dest_path, vim.log.levels.INFO) + mini_files.synchronize() -- Refresh mini.files to show updated directory content + vim.notify("Pasted successfully.", vim.log.levels.INFO) + end + + local copy_path_to_clipboard = function() + -- Get the current entry (file or directory) + local curr_entry = mini_files.get_fs_entry() + if curr_entry then + -- Convert path to be relative to home directory + local home_dir = vim.fn.expand("~") + local relative_path = curr_entry.path:gsub("^" .. home_dir, "~") + vim.fn.setreg("+", relative_path) -- Copy the relative path to the clipboard register + vim.notify(vim.fn.fnamemodify(relative_path, ":t"), vim.log.levels.INFO) + vim.notify("Path copied to clipboard: ", vim.log.levels.INFO) + else + vim.notify("No file or directory selected", vim.log.levels.WARN) + end + end + + local preview_image = function() + local curr_entry = mini_files.get_fs_entry() + if curr_entry then + -- Preview the file using Quick Look + if vim.fn.has("mac") == 1 then + vim.system({ "qlmanage", "-p", curr_entry.path }, { + stdout = false, + stderr = false, + }) + vim.defer_fn(function() + vim.system({ "osascript", "-e", 'tell application "qlmanage" to activate' }) + end, 200) + else + -- TODO: add previewer for linux + vim.notify("Preview not supported on Linux.", vim.log.levels.WARN) + end + else + vim.notify("No file selected", vim.log.levels.WARN) + end + end + + local preview_image_popup = function() + -- Clear any existing images before rendering the new one + require("image").clear() + local curr_entry = mini_files.get_fs_entry() + if curr_entry and curr_entry.fs_type == "file" then + local ext = vim.fn.fnamemodify(curr_entry.path, ":e"):lower() + local supported_image_exts = { "png", "jpg", "jpeg", "gif", "bmp", "webp", "avif" } + -- Check if the file has a supported image extension + if vim.tbl_contains(supported_image_exts, ext) then + -- Save mini.files state (current path and focused entry) + local current_dir = vim.fn.fnamemodify(curr_entry.path, ":h") + local focused_entry = vim.fn.fnamemodify(curr_entry.path, ":t") -- Extract filename + -- Create a floating window for the image preview + local popup_width = math.floor(vim.o.columns * 0.6) + local popup_height = math.floor(vim.o.lines * 0.6) + local col = math.floor((vim.o.columns - popup_width) / 2) + local row = math.floor((vim.o.lines - popup_height) / 2) + local buf = vim.api.nvim_create_buf(false, true) -- Create a scratch buffer + local win = vim.api.nvim_open_win(buf, true, { + relative = "editor", + row = row, + col = col, + width = popup_width, + height = popup_height, + style = "minimal", + border = "rounded", + }) + -- Declare img_width and img_height at the top + local img_width, img_height + -- Get image dimensions using ImageMagick's identify command + local dimensions = vim.fn.systemlist( + string.format("identify -format '%%w %%h' %s", vim.fn.shellescape(curr_entry.path)) + ) + if #dimensions > 0 then + img_width, img_height = dimensions[1]:match("(%d+) (%d+)") + img_width = tonumber(img_width) + img_height = tonumber(img_height) + end + -- Calculate image display size while maintaining aspect ratio + local display_width = popup_width + local display_height = popup_height + if img_width and img_height then + local aspect_ratio = img_width / img_height + if aspect_ratio > (popup_width / popup_height) then + -- Image is wider than the popup window + display_height = math.floor(popup_width / aspect_ratio) + else + -- Image is taller than the popup window + display_width = math.floor(popup_height * aspect_ratio) + end + end + -- Center the image within the popup window + local image_x = math.floor((popup_width - display_width) / 2) + local image_y = math.floor((popup_height - display_height) / 2) + -- Use image.nvim to render the image + local img = require("image").from_file(curr_entry.path, { + id = curr_entry.path, -- Unique ID + window = win, -- Bind the image to the popup window + buffer = buf, -- Bind the image to the popup buffer + x = image_x, + y = image_y, + width = display_width, + height = display_height, + with_virtual_padding = true, + }) + -- Render the image + if img ~= nil then + img:render() + end + -- Use `stat` or `ls` to get the file size in bytes + local file_size_bytes = "" + if vim.fn.has("mac") == 1 or vim.fn.has("unix") == 1 then + -- For macOS or Linux systems + local handle = io.popen( + "stat -f%z " + .. vim.fn.shellescape(curr_entry.path) + .. " || ls -l " + .. vim.fn.shellescape(curr_entry.path) + .. " | awk '{print $5}'" + ) + if handle then + file_size_bytes = handle:read("*a"):gsub("%s+$", "") -- Trim trailing whitespace + handle:close() + end + else + -- Fallback message if the command isn't available + file_size_bytes = "0" + end + -- Convert the size to MB (if valid) + local file_size_mb = tonumber(file_size_bytes) and tonumber(file_size_bytes) / (1024 * 1024) + or 0 + local file_size_mb_str = string.format("%.2f", file_size_mb) -- Format to 2 decimal places as a string + -- Add image information (filename, size, resolution) + local image_info = {} + table.insert(image_info, "Image File: " .. focused_entry) -- Add only the filename + if tonumber(file_size_bytes) > 0 then + table.insert(image_info, "Size: " .. file_size_mb_str .. " MB") -- Use the formatted string + else + table.insert(image_info, "Size: Unable to detect") -- Fallback if size isn't found + end + if img_width and img_height then + table.insert(image_info, "Resolution: " .. img_width .. " x " .. img_height) + else + table.insert(image_info, "Resolution: Unable to detect") + end + -- Append the image information after the image + local line_count = vim.api.nvim_buf_line_count(buf) + vim.api.nvim_buf_set_lines(buf, line_count, -1, false, { "", "", "" }) -- Add 3 empty lines + vim.api.nvim_buf_set_lines(buf, -1, -1, false, image_info) + -- Keymap for closing the popup and reopening mini.files + local function reopen_mini_files() + if img ~= nil then + img:clear() + end + vim.api.nvim_win_close(win, true) + -- Reopen mini.files in the same directory + require("mini.files").open(current_dir, true) + vim.defer_fn(function() + -- Simulate navigation to the file by searching for the line matching the file + local lines = vim.api.nvim_buf_get_lines(0, 0, -1, false) -- Get all lines in the buffer + for i, line in ipairs(lines) do + if line:match(focused_entry) then + vim.api.nvim_win_set_cursor(0, { i, 0 }) -- Move cursor to the matching line + break + end + end + end, 50) -- Small delay to ensure mini.files is initialized + end + vim.keymap.set("n", "<esc>", reopen_mini_files, { buffer = buf, noremap = true, silent = true }) + else + vim.notify("Not an image file.", vim.log.levels.WARN) + end + else + vim.notify("No file selected or not a file.", vim.log.levels.WARN) + end + end + + local follow_symlink = function() + local curr_entry = mini_files.get_fs_entry() + if curr_entry and curr_entry.fs_type == "file" then + local resolved_path = vim.fn.resolve(curr_entry.path) -- Resolve symlink to original file + if resolved_path ~= curr_entry.path then + vim.notify("Following symlink to: " .. resolved_path, vim.log.levels.INFO) + mini_files.open(resolved_path, true) -- Open the original file in mini.files + else + vim.notify("The file is not a symlink.", vim.log.levels.WARN) + end + else + vim.notify("No file selected or not a valid file.", vim.log.levels.WARN) + end + end + + vim.api.nvim_create_autocmd("User", { + pattern = "MiniFilesBufferCreate", + callback = function() + local buf_id = vim.api.nvim_get_current_buf() + + vim.keymap.set( + "n", + opts.mappings and opts.mappings.toggle_hidden or "g.", + toggle_dotfiles, + { buffer = buf_id, desc = "Toggle hidden files" } + ) + + vim.keymap.set( + "n", + opts.mappings and opts.mappings.change_cwd or "gc", + files_set_cwd, + { buffer = buf_id, desc = "Set cwd" } + ) + + map_split(buf_id, opts.mappings and opts.mappings.go_in_horizontal or "<C-w>s", "horizontal", false) + map_split(buf_id, opts.mappings and opts.mappings.go_in_vertical or "<C-w>v", "vertical", false) + map_split( + buf_id, + opts.mappings and opts.mappings.go_in_horizontal_plus or "<C-w>S", + "horizontal", + true + ) + map_split(buf_id, opts.mappings and opts.mappings.go_in_vertical_plus or "<C-w>V", "vertical", true) + + vim.keymap.set( + "n", + "zt", + open_tmux_pane, + { buffer = buf_id, noremap = true, silent = true, desc = "Open tmux pane" } + ) + vim.keymap.set( + "n", + "zy", + copy_to_clipboard, + { buffer = buf_id, noremap = true, silent = true, desc = "Copy to clipboard" } + ) + vim.keymap.set( + "n", + "zY", + copy_path_to_clipboard, + { buffer = buf_id, desc = "Copy path to clipboard" } + ) + vim.keymap.set( + "n", + "zc", + zip_and_copy_to_clipboard, + { buffer = buf_id, noremap = true, silent = true, desc = "Zip and copy" } + ) + vim.keymap.set( + "n", + "zp", + paste_from_clipboard, + { buffer = buf_id, noremap = true, silent = true, desc = "Paste from clipboard" } + ) + vim.keymap.set( + "n", + "zi", + preview_image, + { buffer = buf_id, noremap = true, silent = true, desc = "Preview image" } + ) + vim.keymap.set( + "n", + "zI", + preview_image_popup, + { buffer = buf_id, noremap = true, silent = true, desc = "Pop-up preview image" } + ) + vim.keymap.set( + "n", + "gl", + follow_symlink, + { buffer = buf_id, noremap = true, silent = true, desc = "Follow link" } + ) + end, + }) + + -- Git status + local nsMiniFiles = vim.api.nvim_create_namespace("mini_files_git") + local autocmd = vim.api.nvim_create_autocmd + local _, MiniFiles = pcall(require, "mini.files") + + -- Cache for git status + local gitStatusCache = {} + local cacheTimeout = 2000 -- Cache timeout in milliseconds + + local function isSymlink(path) + local stat = vim.loop.fs_lstat(path) + return stat and stat.type == "link" + end + + ---@type table<string, {symbol: string, hlGroup: string}> + ---@param status string + ---@return string symbol, string hlGroup + local function mapSymbols(status, is_symlink) + local statusMap = { +-- stylua: ignore start +[" M"] = { symbol = "✹", hlGroup = "MiniDiffSignChange"}, -- Modified in the working directory +["M "] = { symbol = "•", hlGroup = "MiniDiffSignChange"}, -- modified in index +["MM"] = { symbol = "≠", hlGroup = "MiniDiffSignChange"}, -- modified in both working tree and index +["A "] = { symbol = "+", hlGroup = "MiniDiffSignAdd" }, -- Added to the staging area, new file +["AA"] = { symbol = "≈", hlGroup = "MiniDiffSignAdd" }, -- file is added in both working tree and index +["D "] = { symbol = "-", hlGroup = "MiniDiffSignDelete"}, -- Deleted from the staging area +["AM"] = { symbol = "⊕", hlGroup = "MiniDiffSignChange"}, -- added in working tree, modified in index +["AD"] = { symbol = "-•", hlGroup = "MiniDiffSignChange"}, -- Added in the index and deleted in the working directory +["R "] = { symbol = "→", hlGroup = "MiniDiffSignChange"}, -- Renamed in the index +["U "] = { symbol = "‖", hlGroup = "MiniDiffSignChange"}, -- Unmerged path +["UU"] = { symbol = "⇄", hlGroup = "MiniDiffSignAdd" }, -- file is unmerged +["UA"] = { symbol = "⊕", hlGroup = "MiniDiffSignAdd" }, -- file is unmerged and added in working tree +["??"] = { symbol = "?", hlGroup = "MiniDiffSignDelete"}, -- Untracked files +["!!"] = { symbol = "!", hlGroup = "MiniDiffSignChange"}, -- Ignored files + -- stylua: ignore end + } + + local result = statusMap[status] or { symbol = "?", hlGroup = "NonText" } + local gitSymbol = result.symbol + local gitHlGroup = result.hlGroup + + local symlinkSymbol = is_symlink and "↩" or "" + + -- Combine symlink symbol with Git status if both exist + local combinedSymbol = (symlinkSymbol .. gitSymbol):gsub("^%s+", ""):gsub("%s+$", "") + -- Change the color of the symlink icon from "MiniDiffSignDelete" to something else + local combinedHlGroup = is_symlink and "MiniDiffSignDelete" or gitHlGroup + + return combinedSymbol, combinedHlGroup + end + + ---@param cwd string + ---@param callback function + ---@return nil + local function fetchGitStatus(cwd, callback) + local function on_exit(content) + if content.code == 0 then + callback(content.stdout) + vim.g.content = content.stdout + end + end + vim.system({ "git", "status", "--ignored", "--porcelain" }, { text = true, cwd = cwd }, on_exit) + end + + ---@param str string|nil + ---@return string + local function escapePattern(str) + if not str then + return "" + end + return (str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")) + end + + ---@param buf_id integer + ---@param gitStatusMap table + ---@return nil + local function updateMiniWithGit(buf_id, gitStatusMap) + vim.schedule(function() + local nlines = vim.api.nvim_buf_line_count(buf_id) + local cwd = vim.fs.root(buf_id, ".git") + local escapedcwd = escapePattern(cwd) + if vim.fn.has("win32") == 1 then + escapedcwd = escapedcwd:gsub("\\", "/") + end + + for i = 1, nlines do + local entry = MiniFiles.get_fs_entry(buf_id, i) + if not entry then + break + end + local relativePath = entry.path:gsub("^" .. escapedcwd .. "/", "") + local status = gitStatusMap[relativePath] + + if status then + local is_symlink = isSymlink(entry.path) + local symbol, hlGroup = mapSymbols(status, is_symlink) + vim.api.nvim_buf_set_extmark(buf_id, nsMiniFiles, i - 1, 0, { + -- NOTE: if you want the signs on the right uncomment those and comment + -- the 3 lines after + -- virt_text = { { symbol, hlGroup } }, + -- virt_text_pos = "right_align", + sign_text = symbol, + sign_hl_group = hlGroup, + priority = 2, + }) + else + end + end + end) + end + + -- Thanks for the idea of gettings https://github.com/refractalize/oil-git-status.nvim signs for dirs + ---@param content string + ---@return table + local function parseGitStatus(content) + local gitStatusMap = {} + -- lua match is faster than vim.split (in my experience ) + for line in content:gmatch("[^\r\n]+") do + local status, filePath = string.match(line, "^(..)%s+(.*)") + -- Split the file path into parts + local parts = {} + for part in filePath:gmatch("[^/]+") do + table.insert(parts, part) + end + -- Start with the root directory + local currentKey = "" + for i, part in ipairs(parts) do + if i > 1 then + -- Concatenate parts with a separator to create a unique key + currentKey = currentKey .. "/" .. part + else + currentKey = part + end + -- If it's the last part, it's a file, so add it with its status + if i == #parts then + gitStatusMap[currentKey] = status + else + -- If it's not the last part, it's a directory. Check if it exists, if not, add it. + if not gitStatusMap[currentKey] then + gitStatusMap[currentKey] = status + end + end + end + end + return gitStatusMap + end + + ---@param buf_id integer + ---@return nil + local function updateGitStatus(buf_id) + local cwd = vim.uv.cwd() + if not cwd or not vim.fs.root(cwd, ".git") then + return + end + + local currentTime = os.time() + if gitStatusCache[cwd] and currentTime - gitStatusCache[cwd].time < cacheTimeout then + updateMiniWithGit(buf_id, gitStatusCache[cwd].statusMap) + else + fetchGitStatus(cwd, function(content) + local gitStatusMap = parseGitStatus(content) + gitStatusCache[cwd] = { + time = currentTime, + statusMap = gitStatusMap, + } + updateMiniWithGit(buf_id, gitStatusMap) + end) + end + end + + ---@return nil + local function clearCache() + gitStatusCache = {} + end + + local function augroup(name) + return vim.api.nvim_create_augroup("MiniFiles_" .. name, { clear = true }) + end + + autocmd("User", { + group = augroup("start"), + pattern = "MiniFilesExplorerOpen", + -- pattern = { "minifiles" }, + callback = function() + local bufnr = vim.api.nvim_get_current_buf() + updateGitStatus(bufnr) + end, + }) + + autocmd("User", { + group = augroup("close"), + pattern = "MiniFilesExplorerClose", + callback = function() + clearCache() + end, + }) + + autocmd("User", { + group = augroup("update"), + pattern = "MiniFilesBufferUpdate", + callback = function(sii) + local bufnr = sii.data.buf_id + local cwd = vim.fn.expand("%:p:h") + if gitStatusCache[cwd] then + updateMiniWithGit(bufnr, gitStatusCache[cwd].statusMap) + end + end, + }) + end, + }, + { + "echasnovski/mini.indentscope", + version = false, -- wait till new 0.7.0 release to put it back on semver + event = "VeryLazy", + opts = { + mappings = { + -- Textobjects + object_scope = "i-", + object_scope_with_border = "a-", + + -- Motions (jump to respective border line; if not present - body line) + goto_top = "g,", + goto_bottom = "g;", + }, + draw = { + animation = function() + return 0 + end, + }, + options = { try_as_border = true }, + symbol = "│", + }, + init = function() + vim.api.nvim_create_autocmd("FileType", { + pattern = { + "help", + "Trouble", + "trouble", + "lazy", + "mason", + }, + callback = function() + vim.b.miniindentscope_disable = true + end, + }) + end, + }, + { + "echasnovski/mini.map", + version = false, + config = function() + require("mini.map").setup( + -- No need to copy this inside `setup()`. Will be used automatically. + { + -- Highlight integrations (none by default) + integrations = nil, + + -- Symbols used to display data + symbols = { + -- Encode symbols. See `:h MiniMap.config` for specification and + -- `:h MiniMap.gen_encode_symbols` for pre-built ones. + -- Default: solid blocks with 3x2 resolution. + encode = nil, + + -- Scrollbar parts for view and line. Use empty string to disable any. + scroll_line = "█", + scroll_view = "┃", + }, + + -- Window options + window = { + -- Whether window is focusable in normal way (with `wincmd` or mouse) + focusable = true, + + -- Side to stick ('left' or 'right') + side = "right", + + -- Whether to show count of multiple integration highlights + show_integration_count = true, + + -- Total width + width = 10, + + -- Value of 'winblend' option + winblend = 25, + + -- Z-index + zindex = 10, + }, + } + ) + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>zm", group = "Map" }, + }) + end, + keys = { + { "<leader>zmo", "<Cmd>lua MiniMap.open()<cr>", desc = "Open map" }, + { "<leader>zmm", "<Cmd>lua MiniMap.refresh()<cr>", desc = "Refresh map" }, + { "<leader>zmq", "<Cmd>lua MiniMap.close()<cr>", desc = "Close map" }, + { "<leader>zmm", "<Cmd>lua MiniMap.toggle()<cr>", desc = "Toggle map" }, + { "<leader>zms", "<Cmd>lua MiniMap.toggle_side()<cr>", desc = "Toggle side map" }, + }, + }, + { + "echasnovski/mini.move", + version = false, + config = function() + -- No need to copy this inside `setup()`. Will be used automatically. + require("mini.move").setup({ + -- Module mappings. Use `''` (empty string) to disable one. + mappings = { + -- Move visual selection in Visual mode. Defaults are Alt (Meta) + hjkl. + left = "<M-m>", + right = "<M-/>", + -- down = "<M-,>", + -- up = "<M-.>", + + -- Move current line in Normal mode + line_left = "<M-m>", + line_right = "<M-/>", + -- line_down = "<M-,>", + -- line_up = "<M-.>", + }, + + -- Options which control moving behavior + options = { + -- Automatically reindent selection during linewise vertical move + reindent_linewise = true, + }, + }) + end, + }, + { + "echasnovski/mini.pairs", + version = false, + event = "VeryLazy", + config = function() + require("mini.pairs").setup() + end, + keys = { + { + "<leader>zp", + function() + vim.g.minipairs_disable = not vim.g.minipairs_disable + end, + desc = "Toggle auto pairs", + }, + }, + }, + { + "echasnovski/mini.splitjoin", + version = false, + config = function() + require("mini.splitjoin").setup() + + vim.keymap.set( + "n", + "<leader>zj", + ":lua MiniSplitjoin.toggle()<cr>", + { noremap = true, silent = true, desc = "Toggle split-join" } + ) + vim.keymap.set( + "n", + "<leader>J", + ":lua MiniSplitjoin.join()<cr>", + { noremap = true, silent = true, desc = "Join" } + ) + vim.keymap.set( + "n", + "<leader><cr>", + ":lua MiniSplitjoin.split()<cr>", + { noremap = true, silent = true, desc = "Split" } + ) + end, + }, + { + "echasnovski/mini.trailspace", + version = false, + config = function() + require("mini.trailspace").setup() + vim.keymap.set( + "n", + "<leader>zW", + ":lua MiniTrailspace.trim()<cr>", + { noremap = true, silent = true, desc = "Trim trailing whitespace" } + ) + vim.keymap.set( + "n", + "<leader>zL", + ":lua MiniTrailspace.trim_last_lines()<cr>", + { noremap = true, silent = true, desc = "Trim trailing empty lines" } + ) + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/navic.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/navic.lua new file mode 100644 index 0000000..89cfa81 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/navic.lua @@ -0,0 +1,52 @@ +return { + "SmiteshP/nvim-navic", + dependencies = { + "neovim/nvim-lspconfig", + }, + config = function() + require("nvim-navic").setup({ + icons = { + File = " ", + Module = " ", + Namespace = " ", + Package = " ", + Class = " ", + Method = " ", + Property = " ", + Field = " ", + Constructor = " ", + Enum = "", + Interface = "", + Function = " ", + Variable = " ", + Constant = " ", + String = " ", + Number = " ", + Boolean = "◩ ", + Array = " ", + Object = " ", + Key = " ", + Null = " ", + EnumMember = " ", + Struct = " ", + Event = " ", + Operator = " ", + TypeParameter = " ", + }, + lsp = { + auto_attach = true, + preference = nil, + }, + highlight = true, + separator = " > ", + depth_limit = 5, + depth_limit_indicator = "..", + safe_output = true, + lazy_update_context = false, + click = true, + format_text = function(text) + return text + end, + }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua new file mode 100644 index 0000000..c05716d --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua @@ -0,0 +1,167 @@ +return { + { + "nvim-neo-tree/neo-tree.nvim", + branch = "v3.x", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-tree/nvim-web-devicons", -- not strictly required, but recommended + "MunifTanjim/nui.nvim", + { + "s1n7ax/nvim-window-picker", -- for open_with_window_picker keymaps + version = "2.*", + config = function() + require("window-picker").setup({ + filter_rules = { + include_current_win = false, + autoselect_one = true, + -- filter using buffer options + bo = { + -- if the file type is one of following, the window will be ignored + filetype = { "neo-tree", "neo-tree-popup", "notify" }, + -- if the buffer type is one of following, the window will be ignored + buftype = { "terminal", "quickfix" }, + }, + }, + }) + end, + }, + { "3rd/image.nvim", opts = {} }, -- Optional image support in preview window: See `# Preview Mode` for more information + }, + lazy = false, -- neo-tree will lazily load itself + ---@module "neo-tree" + ---@type neotree.Config? + opts = { + filesystem = { + hijack_netrw_behavior = "disabled", -- open_default, open_current + follow_current_file = { enabled = false }, + commands = { + -- over write default 'delete' command to 'trash'. + delete = function(state) + if vim.fn.executable("trash") == 0 then + vim.api.nvim_echo({ + { "- Trash utility not installed. Make sure to install it first\n", nil }, + { "- In macOS run `brew install trash`\n", nil }, + { "- Or delete the `custom delete command` section in neo-tree", nil }, + }, false, {}) + return + end + local inputs = require("neo-tree.ui.inputs") + local path = state.tree:get_node().path + local msg = "Are you sure you want to trash " .. path + inputs.confirm(msg, function(confirmed) + if not confirmed then + return + end + + vim.fn.system({ "trash", vim.fn.fnameescape(path) }) + require("neo-tree.sources.manager").refresh(state.name) + end) + end, + -- Overwrite default 'delete_visual' command to 'trash' x n. + delete_visual = function(state, selected_nodes) + if vim.fn.executable("trash") == 0 then + vim.api.nvim_echo({ + { "- Trash utility not installed. Make sure to install it first\n", nil }, + { "- In macOS run `brew install trash`\n", nil }, + { "- Or delete the `custom delete command` section in neo-tree", nil }, + }, false, {}) + return + end + local inputs = require("neo-tree.ui.inputs") + + -- Function to get the count of items in a table + local function GetTableLen(tbl) + local len = 0 + for _ in pairs(tbl) do + len = len + 1 + end + return len + end + + local count = GetTableLen(selected_nodes) + local msg = "Are you sure you want to trash " .. count .. " files?" + inputs.confirm(msg, function(confirmed) + if not confirmed then + return + end + for _, node in ipairs(selected_nodes) do + vim.fn.system({ "trash", vim.fn.fnameescape(node.path) }) + end + require("neo-tree.sources.manager").refresh(state.name) + end) + end, + avante_add_files = function(state) + local node = state.tree:get_node() + local filepath = node:get_id() + local relative_path = require("avante.utils").relative_path(filepath) + + local sidebar = require("avante").get() + + local open = sidebar:is_open() + -- ensure avante sidebar is open + if not open then + require("avante.api").ask() + sidebar = require("avante").get() + end + + sidebar.file_selector:add_selected_file(relative_path) + + -- remove neo tree buffer + if not open then + sidebar.file_selector:remove_selected_file("neo-tree filesystem [1]") + end + end, + }, + window = { + mappings = { + ["oa"] = "avante_add_files", + }, + }, + }, + }, + keys = { + { "<leader>e", false }, + { "<leader>E", false }, + { + "<leader>en", + function() + local buf_name = vim.api.nvim_buf_get_name(0) + -- Function to check if NeoTree is open in any window + local function is_neo_tree_open() + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.bo[buf].filetype == "neo-tree" then + return true + end + end + return false + end + -- Check if the current file exists + if + vim.fn.filereadable(buf_name) == 1 + or vim.fn.isdirectory(vim.fn.fnamemodify(buf_name, ":p:h")) == 1 + then + if is_neo_tree_open() then + -- Close NeoTree if it's open + vim.cmd("Neotree close") + else + -- Open NeoTree and reveal the current file + vim.cmd("Neotree reveal") + end + else + -- If the file doesn't exist, execute the logic for <leader>R + require("neo-tree.command").execute({ toggle = true, dir = vim.uv.cwd() }) + end + end, + desc = "Open neo-tree", + }, + { + "<leader>eN", + function() + require("neo-tree.command").execute({ toggle = true, dir = vim.uv.cwd() }) + end, + desc = "Open neo-tree (cwd)", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/obsidian.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/obsidian.lua new file mode 100644 index 0000000..c5f3a59 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/obsidian.lua @@ -0,0 +1,616 @@ +return { + "epwalsh/obsidian.nvim", + version = "*", -- recommended, use latest release instead of latest commit + lazy = true, + ft = "markdown", + -- Replace the above line with this if you only want to load obsidian.nvim for markdown files in your vault: + -- event = { + -- -- If you want to use the home shortcut '~' here you need to call 'vim.fn.expand'. + -- -- E.g. "BufReadPre " .. vim.fn.expand "~" .. "/my-vault/*.md" + -- -- refer to `:h file-pattern` for more examples + -- "BufReadPre path/to/my-vault/*.md", + -- "BufNewFile path/to/my-vault/*.md", + -- }, + dependencies = { + -- Required. + "nvim-lua/plenary.nvim", + -- see below for full list of optional dependencies 👇 + "hrsh7th/nvim-cmp", + "nvim-telescope/telescope.nvim", + "nvim-treesitter/nvim-treesitter", + { + "epwalsh/pomo.nvim", + dependencies = "nvim-lualine/lualine.nvim", + config = function() + require("lualine").setup({ + sections = { + lualine_x = { + function() + local ok, pomo = pcall(require, "pomo") + if not ok then + return "" + end + + local timer = pomo.get_first_to_finish() + if timer == nil then + return "" + end + + return " " .. tostring(timer) + end, + "encoding", + "fileformat", + "filetype", + }, + }, + }) + + require("telescope").load_extension("pomodori") + + vim.keymap.set("n", "<leader>mp", function() + require("telescope").extensions.pomodori.timers() + end, { desc = "Manage pomodori" }) + end, + }, + }, + cmd = { + "ObsidianOpen", + "ObsidianNew", + "ObsidianQuickSwitch", + "ObsidianFollowLink", + "ObsidianBacklinks", + "ObsidianTags", + "ObsidianToday", + "ObsidianYesterday", + "ObsidianTomorrow", + "ObsidianDailies", + "ObsidianTemplate", + "ObsidianSearch", + "ObsidianLink", + "ObsidianLinkNew", + "ObsidianExtractNote", + "ObsidianWorkspace", + "ObsidianPasteImg", + "ObsidianRename", + "ObsidianToggleCheckbox", + "ObsidianNewFromTemplate", + "ObsidianTOC", + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>o", group = "Open/Obsidian" }, + { "<leader>of", group = "Find files (Obsidian)" }, + { "<leader>on", group = "Notes (Obsidian)" }, + { "<leader>op", group = "Paste (Obsidian)" }, + { "<leader>ot", group = "Templates (Obsidian)" }, + }) + end, + config = function() + require("obsidian").setup({ + -- A list of workspace names, paths, and configuration overrides. + -- If you use the Obsidian app, the 'path' of a workspace should generally be + -- your vault root (where the `.obsidian` folder is located). + -- When obsidian.nvim is loaded by your plugin manager, it will automatically set + -- the workspace to the first workspace in the list whose `path` is a parent of the + -- current markdown file being edited. + workspaces = { + { + name = "personal", + path = "~/Private/repos/Obsidian/SI", + -- Optional, override certain settings. + overrides = { + notes_subdir = "", + }, + }, + }, + + -- Alternatively - and for backwards compatibility - you can set 'dir' to a single path instead of + -- 'workspaces'. For example: + -- dir = "~/vaults/work", + + -- Optional, if you keep notes in a specific subdirectory of your vault. + notes_subdir = "", + + -- Optional, set the log level for obsidian.nvim. This is an integer corresponding to one of the log + -- levels defined by "vim.log.levels.*". + log_level = vim.log.levels.INFO, + + daily_notes = { + -- Optional, if you keep daily notes in a separate directory. + folder = "Area/Notes", + -- Optional, if you want to change the date format for the ID of daily notes. + date_format = "%Y-%m-%d", + -- Optional, if you want to change the date format of the default alias of daily notes. + alias_format = "%B %-d, %Y", + -- Optional, default tags to add to each new daily note created. + default_tags = { "daily-notes" }, + -- Optional, if you want to automatically insert a template from your template directory like 'daily.md' + template = nil, + }, + + -- Optional, completion of wiki links, local markdown links, and tags using nvim-cmp. + completion = { + -- Set to false to disable completion. + nvim_cmp = true, + -- Trigger completion at 2 chars. + min_chars = 2, + }, + + -- Optional, configure key mappings. These are the defaults. If you don't want to set any keymappings this + -- way then set 'mappings = {}'. + mappings = { + -- Smart action depending on context, either follow link or toggle checkbox. + ["<cr>"] = { + action = function() + return require("obsidian").util.smart_action() + end, + opts = { buffer = true, expr = true }, + }, + }, + + -- Where to put new notes. Valid options are + -- * "current_dir" - put new notes in same directory as the current buffer. + -- * "notes_subdir" - put new notes in the default notes subdirectory. + new_notes_location = "current_dir", + + -- Optional, customize how note IDs are generated given an optional title. + ---@param title string|? + ---@return string + note_id_func = function(title) + -- Create note IDs in a Zettelkasten format with a timestamp and a suffix. + -- In this case a note with the title 'My new note' will be given an ID that looks + -- like '1657296016-my-new-note', and therefore the file name '1657296016-my-new-note.md' + local suffix = "" + if title ~= nil then + -- If title is given, transform it into valid file name. + suffix = title:gsub(" ", "-"):gsub("[^A-Za-z0-9-]", ""):lower() + else + -- If title is nil, just add 4 random uppercase letters to the suffix. + for _ = 1, 4 do + suffix = suffix .. string.char(math.random(65, 90)) + end + end + return suffix + end, + + -- Optional, customize how note file names are generated given the ID, target directory, and title. + ---@param spec { id: string, dir: obsidian.Path, title: string|? } + ---@return string|obsidian.Path The full path to the new note. + note_path_func = function(spec) + -- This is equivalent to the default behavior. + local path = spec.dir / "Contents" / tostring(spec.title) + return path:with_suffix(".md") + end, + + -- Optional, customize how wiki links are formatted. You can set this to one of: + -- * "use_alias_only", e.g. '[[Foo Bar]]' + -- * "prepend_note_id", e.g. '[[foo-bar|Foo Bar]]' + -- * "prepend_note_path", e.g. '[[foo-bar.md|Foo Bar]]' + -- * "use_path_only", e.g. '[[foo-bar.md]]' + -- Or you can set it to a function that takes a table of options and returns a string, like this: + wiki_link_func = function(opts) + return require("obsidian.util").wiki_link_path_prefix(opts) + end, + + -- Optional, customize how markdown links are formatted. + markdown_link_func = function(opts) + return require("obsidian.util").markdown_link(opts) + end, + + -- Either 'wiki' or 'markdown'. + preferred_link_style = "wiki", + + -- Optional, boolean or a function that takes a filename and returns a boolean. + -- `true` indicates that you don't want obsidian.nvim to manage frontmatter. + disable_frontmatter = false, + + -- -- Optional, alternatively you can customize the frontmatter data. + -- ---@return table + -- note_frontmatter_func = function(note) + -- -- Add the title of the note as an alias. + -- if note.title then + -- note:add_alias(note.title) + -- end + -- + -- local out = { id = note.id, aliases = note.aliases, tags = note.tags } + -- + -- -- `note.metadata` contains any manually added fields in the frontmatter. + -- -- So here we just make sure those fields are kept in the frontmatter. + -- if note.metadata ~= nil and not vim.tbl_isempty(note.metadata) then + -- for k, v in pairs(note.metadata) do + -- out[k] = v + -- end + -- end + -- + -- return out + -- end, + + -- Optional, for templates (see below). + templates = { + folder = "Resource/Templates", + date_format = "%Y-%m-%d", + time_format = "%H:%M", + -- A map for custom variables, the key should be the variable and the value a function + substitutions = {}, + }, + + -- Optional, by default when you use `:ObsidianFollowLink` on a link to an external + -- URL it will be ignored but you can customize this behavior here. + ---@param url string + follow_url_func = function(url) + -- Open the URL in the default web browser. + -- vim.fn.jobstart({ "open", url }) -- Mac OS + vim.fn.jobstart({ "xdg-open", url }) -- linux + -- vim.cmd(':silent exec "!start ' .. url .. '"') -- Windows + -- vim.ui.open(url) -- need Neovim 0.10.0+ + end, + + -- Optional, by default when you use `:ObsidianFollowLink` on a link to an image + -- file it will be ignored but you can customize this behavior here. + ---@param img string + follow_img_func = function(img) + -- vim.fn.jobstart({ "qlmanage", "-p", img }) -- Mac OS quick look preview + vim.fn.jobstart({ "nsxiv", "-aiop", img }) -- linux + -- vim.cmd(':silent exec "!start ' .. url .. '"') -- Windows + end, + + -- Optional, set to true if you use the Obsidian Advanced URI plugin. + -- https://github.com/Vinzent03/obsidian-advanced-uri + use_advanced_uri = false, + + -- Optional, set to true to force ':ObsidianOpen' to bring the app to the foreground. + open_app_foreground = false, + + picker = { + -- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', or 'mini.pick'. + name = "telescope.nvim", + -- Optional, configure key mappings for the picker. These are the defaults. + -- Not all pickers support all mappings. + note_mappings = { + -- Create a new note from your query. + new = "<C-x>", + -- Insert a link to the selected note. + insert_link = "<C-l>", + }, + tag_mappings = { + -- Add tag(s) to current note. + tag_note = "<C-x>", + -- Insert a tag at the current location. + insert_tag = "<C-l>", + }, + }, + + -- Optional, sort search results by "path", "modified", "accessed", or "created". + -- The recommend value is "modified" and `true` for `sort_reversed`, which means, for example, + -- that `:ObsidianQuickSwitch` will show the notes sorted by latest modified time + sort_by = "modified", + sort_reversed = true, + + -- Set the maximum number of lines to read from notes on disk when performing certain searches. + search_max_lines = 1000, + + -- Optional, determines how certain commands open notes. The valid options are: + -- 1. "current" (the default) - to always open in the current window + -- 2. "vsplit" - to open in a vertical split if there's not already a vertical split + -- 3. "hsplit" - to open in a horizontal split if there's not already a horizontal split + open_notes_in = "current", + + -- Optional, define your own callbacks to further customize behavior. + callbacks = { + -- Runs at the end of `require("obsidian").setup()`. + ---@param client obsidian.Client + post_setup = function(client) end, + + -- Runs anytime you enter the buffer for a note. + ---@param client obsidian.Client + ---@param note obsidian.Note + enter_note = function(client, note) end, + + -- Runs anytime you leave the buffer for a note. + ---@param client obsidian.Client + ---@param note obsidian.Note + leave_note = function(client, note) end, + + -- Runs right before writing the buffer for a note. + ---@param client obsidian.Client + ---@param note obsidian.Note + pre_write_note = function(client, note) end, + + -- Runs anytime the workspace is set/changed. + ---@param client obsidian.Client + ---@param workspace obsidian.Workspace + post_set_workspace = function(client, workspace) end, + }, + + -- Optional, configure additional syntax highlighting / extmarks. + -- This requires you have `conceallevel` set to 1 or 2. See `:help conceallevel` for more details. + ui = { + enable = false, -- set to false to disable all additional syntax features + update_debounce = 200, -- update delay after a text change (in milliseconds) + max_file_length = 5000, -- disable UI features for files with more than this many lines + -- Define how various check-boxes are displayed + checkboxes = { + -- NOTE: the 'char' value has to be a single character, and the highlight groups are defined below. + [" "] = { char = "", hl_group = "ObsidianTodo" }, + ["x"] = { char = "", hl_group = "ObsidianDone" }, + [">"] = { char = "", hl_group = "ObsidianRightArrow" }, + ["~"] = { char = "", hl_group = "ObsidianTilde" }, + ["!"] = { char = "", hl_group = "ObsidianImportant" }, + -- Replace the above with this if you don't have a patched font: + -- [" "] = { char = "☐", hl_group = "ObsidianTodo" }, + -- ["x"] = { char = "✔", hl_group = "ObsidianDone" }, + + -- You can also add more custom ones... + }, + -- Use bullet marks for non-checkbox lists. + bullets = { char = "•", hl_group = "ObsidianBullet" }, + external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" }, + -- Replace the above with this if you don't have a patched font: + -- external_link_icon = { char = "", hl_group = "ObsidianExtLinkIcon" }, + reference_text = { hl_group = "ObsidianRefText" }, + highlight_text = { hl_group = "ObsidianHighlightText" }, + tags = { hl_group = "ObsidianTag" }, + block_ids = { hl_group = "ObsidianBlockID" }, + hl_groups = { + -- The options are passed directly to `vim.api.nvim_set_hl()`. See `:help nvim_set_hl`. + ObsidianTodo = { bold = true, fg = "#f78c6c" }, + ObsidianDone = { bold = true, fg = "#89ddff" }, + ObsidianRightArrow = { bold = true, fg = "#f78c6c" }, + ObsidianTilde = { bold = true, fg = "#ff5370" }, + ObsidianImportant = { bold = true, fg = "#d73128" }, + ObsidianBullet = { bold = true, fg = "#89ddff" }, + ObsidianRefText = { underline = true, fg = "#c792ea" }, + ObsidianExtLinkIcon = { fg = "#c792ea" }, + ObsidianTag = { italic = true, fg = "#89ddff" }, + ObsidianBlockID = { italic = true, fg = "#89ddff" }, + ObsidianHighlightText = { bg = "#75662e" }, + }, + }, + + -- Specify how to handle attachments. + attachments = { + -- The default folder to place images in via `:ObsidianPasteImg`. + -- If this is a relative path it will be interpreted as relative to the vault root. + -- You can always override this per image by passing a full path to the command instead of just a filename. + img_folder = "assets/imgs", -- This is the default + + -- Optional, customize the default name or prefix when pasting images via `:ObsidianPasteImg`. + ---@return string + img_name_func = function() + -- Prefix image names with timestamp. + return string.format("%s-", os.time()) + end, + + -- A function that determines the text to insert in the note when pasting an image. + -- It takes two arguments, the `obsidian.Client` and an `obsidian.Path` to the image file. + -- This is the default implementation. + ---@param client obsidian.Client + ---@param path obsidian.Path the absolute path to the image file + ---@return string + img_text_func = function(client, path) + path = client:vault_relative_path(path) or path + return string.format("", path.name, path) + end, + }, + }) + + vim.api.nvim_create_autocmd("FileType", { + pattern = "markdown", + callback = function() + vim.keymap.set("n", "gl", function() + if require("obsidian").util.cursor_on_markdown_link() then + return "<Cmd>ObsidianFollowLink<cr>" + else + return "gl" + end + end, { noremap = false, expr = true, desc = "Follow link (Obsidian)" }) + end, + }) + end, + keys = { + { + "<leader>zb", + function() + return require("obsidian").util.toggle_checkbox() + end, + buffer = true, + ft = "markdown", + desc = "Toggle check box (Obsidian)", + }, + { + "<leader>ob", + function() + local query = vim.fn.input("Enter query: ") + if query and #query > 0 then + vim.cmd("ObsidianOpen " .. query) + end + end, + ft = "markdown", + desc = "Open note (Obsidian)", + }, + { + "<leader>onn", + function() + local title = vim.fn.input("Enter title: ") + if title and #title > 0 then + vim.cmd("ObsidianNew " .. title) + end + end, + ft = "markdown", + desc = "New note (Obsidian)", + }, + { + "<leader>os", + "<Cmd>ObsidianQuickSwitch<cr>", + ft = "markdown", + desc = "Quick switch (Obsidian)", + }, + { + "<leader>oL", + "<Cmd>ObsidianFollowLink<cr>", + ft = "markdown", + desc = "Follow link (Obsidian)", + }, + { + "<leader>oH", + "<Cmd>ObsidianBacklinks<cr>", + ft = "markdown", + desc = "Back link (Obsidian)", + }, + { + "<leader>oft", + function() + local tags = vim.fn.input("Enter tag: ") + if tags and #tags > 0 then + vim.cmd("ObsidianTags " .. tags) + end + end, + ft = "markdown", + desc = "Search tag notes (Obsidian)", + }, + { + "<leader>ont", + function() + local offset = vim.fn.input("Enter offset: ") + if offset and #offset > 0 then + vim.cmd("ObsidianToday " .. offset) + else + vim.cmd("ObsidianToday") + end + end, + ft = "markdown", + desc = "Today note (Obsidian)", + }, + { + "<leader>ony", + "<Cmd>ObsidianYesterday<cr>", + ft = "markdown", + desc = "Yesterday note (Obsidian)", + }, + { + "<leader>ont", + "<Cmd>ObsidianTomorrow<cr>", + ft = "markdown", + desc = "Tomorrow note (Obsidian)", + }, + { + "<leader>ond", + function() + local offset = vim.fn.input("Enter offset: ") + if offset and #offset > 0 then + vim.cmd("ObsidianDailies " .. offset) + else + vim.cmd("ObsidianDailies") + end + end, + ft = "markdown", + desc = "Daily notes (Obsidian)", + }, + { + "<leader>oti", + "<Cmd>ObsidianTemplate<cr>", + ft = "markdown", + desc = "Insert templates (Obsidian)", + }, + { + "<leader>ofn", + function() + local note = vim.fn.input("Enter note: ") + if note and #note > 0 then + vim.cmd("ObsidianSearch " .. note) + end + end, + ft = "markdown", + desc = "Search note (Obsidian)", + }, + { + "<leader>ow", + function() + local name = vim.fn.input("Enter name: ") + if name and #name > 0 then + vim.cmd("ObsidianWorkspace " .. name) + end + end, + ft = "markdown", + desc = "Workspace name (Obsidian)", + }, + { + "<leader>opi", + function() + local image = vim.fn.input("Enter image: ") + if image and #image > 0 then + vim.cmd("ObsidianPasteImg " .. image) + end + end, + ft = "markdown", + desc = "Paste image (Obsidian)", + }, + { + "<leader>onr", + function() + local name = vim.fn.input("Enter name: ") + if name and #name > 0 then + vim.cmd("ObsidianRename " .. name) + end + end, + ft = "markdown", + desc = "Rename note (Obsidian)", + }, + { + mode = "v", + "<leader>ol", + function() + local query = vim.fn.input("Enter query: ") + if query and #query > 0 then + vim.cmd("ObsidianLink " .. query) + else + vim.cmd("ObsidianLink") + end + end, + ft = "markdown", + desc = "Link query (Obsidian)", + }, + { + mode = "v", + "<leader>onl", + function() + local note = vim.fn.input("Enter note: ") + if note and #note > 0 then + vim.cmd("ObsidianLinkNew " .. note) + else + vim.cmd("ObsidianLinkNew") + end + end, + ft = "markdown", + desc = "New link note (Obsidian)", + }, + { + mode = "v", + "<leader>ox", + function() + local note = vim.fn.input("Enter note: ") + if note and #note > 0 then + vim.cmd("ObsidianExtractNote " .. note) + else + vim.cmd("ObsidianExtractNote") + end + end, + ft = "markdown", + desc = "New extract text (Obsidian)", + }, + { + "<leader>otn", + "<Cmd>ObsidianNewFromTemplate<cr>", + ft = "markdown", + desc = "Open new note with template (Obsidian)", + }, + { + "<leader>oc", + "<Cmd>ObsidianTOC<cr>", + ft = "markdown", + desc = "Open contents (Obsidian)", + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/outline.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/outline.lua new file mode 100644 index 0000000..5d28f7d --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/outline.lua @@ -0,0 +1,11 @@ +return { + "hedyhli/outline.nvim", + lazy = true, + cmd = { "Outline", "OutlineOpen" }, + keys = { -- Example mapping to toggle outline + { "<leader>zo", "<Cmd>Outline<cr>", desc = "Toggle outline" }, + }, + opts = { + -- Your setup opts here + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/project.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/project.lua new file mode 100644 index 0000000..13ee82b --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/project.lua @@ -0,0 +1,12 @@ +return { + "Zeioth/project.nvim", + dependencies = "nvim-telescope/telescope.nvim", + config = function() + require("project_nvim").setup() + require("telescope").load_extension("projects") + + vim.keymap.set("n", "<leader>fpj", function() + require("telescope").extensions.projects.projects() + end, { desc = "Find projects" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua new file mode 100644 index 0000000..75b1ce7 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua @@ -0,0 +1,54 @@ +return { + -- { + -- "bps/vim-textobj-python", + -- dependencies = { "kana/vim-textobj-user" }, + -- }, + { + "nvim-neotest/neotest", + optional = true, + dependencies = { + "nvim-neotest/neotest-python", + }, + opts = { + adapters = { + ["neotest-python"] = { + -- Here you can specify the settings for the adapter, i.e. + -- runner = "pytest", + -- python = ".venv/bin/python", + }, + }, + }, + }, + { + "linux-cultist/venv-selector.nvim", + dependencies = { + "neovim/nvim-lspconfig", + "mfussenegger/nvim-dap", + "mfussenegger/nvim-dap-python", --optional + { "nvim-telescope/telescope.nvim", branch = "0.1.x", dependencies = { "nvim-lua/plenary.nvim" } }, + }, + lazy = false, + ft = "python", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>v", group = "Virtual envs" }, + }) + end, + config = function() + require("venv-selector").setup({ + notify_user_on_activate = true, + search = { + venvs = { + command = "fd /bin/python$ ~/.local/share/venvs --full-path", + }, + }, + }) + end, + keys = { + { "<leader>vs", "<Cmd>VenvSelect<cr>", desc = "Select virtual env", ft = "python" }, + { "<leader>vc", "<Cmd>VenvSelectCached<cr>", desc = "Select venv (cache)", ft = "python" }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/quickfix.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/quickfix.lua new file mode 100644 index 0000000..f586310 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/quickfix.lua @@ -0,0 +1,76 @@ +return { + { + "folke/trouble.nvim", + cmd = { "Trouble" }, + opts = { + modes = { + lsp = { + win = { position = "right" }, + }, + preview_float = { + mode = "diagnostics", + preview = { + type = "float", + relative = "editor", + border = "rounded", + title = "Preview", + title_pos = "center", + position = { 0, -2 }, + size = { width = 0.3, height = 0.3 }, + zindex = 200, + }, + }, + }, + }, + config = function(_, opts) + require("trouble").setup(opts) + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>x", group = "Quickfix (trouble)" }, + }) + end, + keys = { + { "<leader>xd", "<Cmd>Trouble diagnostics toggle<cr>", desc = "Toggle diagnostics (Trouble)" }, + { + "<leader>xD", + "<Cmd>Trouble diagnostics toggle filter.buf=0<cr>", + desc = "Toggle buffer Diagnostics (Trouble)", + }, + { "<leader>xs", "<Cmd>Trouble symbols toggle<cr>", desc = "Toggle symbols (Trouble)" }, + { "<leader>xS", "<Cmd>Trouble lsp toggle<cr>", desc = "Toggle LSP def/ref/... (Trouble)" }, + { "<leader>xl", "<Cmd>Trouble loclist toggle<cr>", desc = "Toggle location List (Trouble)" }, + { "<leader>xq", "<Cmd>Trouble qflist toggle<cr>", desc = "Toggle quickfix List (Trouble)" }, + { + "[x", + function() + if require("trouble").is_open() then + require("trouble").prev({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cprev) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Previous quickfix (trouble)", + }, + { + "]x", + function() + if require("trouble").is_open() then + require("trouble").next({ skip_groups = true, jump = true }) + else + local ok, err = pcall(vim.cmd.cnext) + if not ok then + vim.notify(err, vim.log.levels.ERROR) + end + end + end, + desc = "Next quickfix (trouble)", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/refactoring.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/refactoring.lua new file mode 100644 index 0000000..8bcf274 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/refactoring.lua @@ -0,0 +1,78 @@ +return { + "ThePrimeagen/refactoring.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-treesitter/nvim-treesitter", + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v", "x" }, + { "<leader>r", group = "Compiler/Refactoring" }, + { "<leader>rb", group = "Extract block" }, + }) + end, + lazy = false, + config = function() + require("refactoring").setup({ + prompt_func_return_type = { + c = true, + cpp = true, + cxx = true, + go = true, + h = true, + hpp = true, + java = true, + lua = true, + python = true, + }, + prompt_func_param_type = { + c = true, + cpp = true, + cxx = true, + go = true, + h = true, + hpp = true, + java = true, + lua = true, + python = true, + }, + printf_statements = {}, + print_var_statements = {}, + show_success_message = false, + }) + vim.keymap.set({ "n", "x" }, "<leader>re", function() + return require("refactoring").refactor("Extract Function") + end, { expr = true, desc = "Extract" }) + vim.keymap.set({ "n", "x" }, "<leader>rf", function() + return require("refactoring").refactor("Extract Function To File") + end, { expr = true, desc = "Extract to file" }) + vim.keymap.set({ "n", "x" }, "<leader>rv", function() + return require("refactoring").refactor("Extract Variable") + end, { expr = true, desc = "Extract variable" }) + vim.keymap.set({ "n", "x" }, "<leader>rI", function() + return require("refactoring").refactor("Inline Function") + end, { expr = true, desc = "Refactor inline function" }) + vim.keymap.set({ "n", "x" }, "<leader>ri", function() + return require("refactoring").refactor("Inline Variable") + end, { expr = true, desc = "Refactor inline variable" }) + + vim.keymap.set({ "n", "x" }, "<leader>rbb", function() + return require("refactoring").refactor("Extract Block") + end, { expr = true, desc = "Extract block" }) + vim.keymap.set({ "n", "x" }, "<leader>rbf", function() + return require("refactoring").refactor("Extract Block To File") + end, { expr = true, desc = "Extract block to file" }) + + -- prompt for a refactor to apply when the remap is triggered + vim.keymap.set({ "n", "x" }, "<leader>rs", function() + require("refactoring").select_refactor({ prefer_ex_cmd = true }) + end, { desc = "Refactor selection" }) + -- Note that not all refactor support both normal and visual mode + -- load refactoring Telescope extension + require("telescope").load_extension("refactoring") + vim.keymap.set({ "n", "x" }, "<leader>rf", function() + require("telescope").extensions.refactoring.refactors() + end, { desc = "Open refactor" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/rest.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/rest.lua new file mode 100644 index 0000000..33586d3 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/rest.lua @@ -0,0 +1,133 @@ +return { + "rest-nvim/rest.nvim", + dependencies = { + { + "nvim-treesitter/nvim-treesitter", + opts = function(_, opts) + opts.ensure_installed = opts.ensure_installed or {} + table.insert(opts.ensure_installed, "http") + end, + }, + }, + config = function() + ---rest.nvim default configuration + ---@class rest.Config + local default_config = { + ---@type table<string, fun():string> Table of custom dynamic variables + custom_dynamic_variables = {}, + ---@class rest.Config.Request + request = { + ---@type boolean Skip SSL verification, useful for unknown certificates + skip_ssl_verification = false, + ---Default request hooks + ---@class rest.Config.Request.Hooks + hooks = { + ---@type boolean Encode URL before making request + encode_url = true, + ---@type string Set `User-Agent` header when it is empty + user_agent = "rest.nvim v" .. require("rest-nvim.api").VERSION, + ---@type boolean Set `Content-Type` header when it is empty and body is provided + set_content_type = true, + }, + }, + ---@class rest.Config.Response + response = { + ---Default response hooks + ---@class rest.Config.Response.Hooks + hooks = { + ---@type boolean Decode the request URL segments on response UI to improve readability + decode_url = true, + ---@type boolean Format the response body using `gq` command + format = true, + }, + }, + ---@class rest.Config.Clients + clients = { + ---@class rest.Config.Clients.Curl + curl = { + ---Statistics to be shown, takes cURL's `--write-out` flag variables + ---See `man curl` for `--write-out` flag + ---@type RestStatisticsStyle[] + statistics = { + { id = "time_total", winbar = "take", title = "Time taken" }, + { id = "size_download", winbar = "size", title = "Download size" }, + }, + ---Curl-secific request/response hooks + ---@class rest.Config.Clients.Curl.Opts + opts = { + ---@type boolean Add `--compressed` argument when `Accept-Encoding` header includes + ---`gzip` + set_compressed = false, + ---@type table<string, Certificate> Table containing certificates for each domains + certificates = {}, + }, + }, + }, + ---@class rest.Config.Cookies + cookies = { + ---@type boolean Whether enable cookies support or not + enable = true, + ---@type string Cookies file path + path = vim.fs.joinpath(vim.fn.stdpath("data") --[[@as string]], "rest-nvim.cookies"), + }, + ---@class rest.Config.Env + env = { + ---@type boolean + enable = true, + ---@type string + pattern = ".*%.env.*", + ---@type fun():string[] + find = function() + local config = require("rest-nvim.config") + return vim.fs.find(function(name, _) + return name:match(config.env.pattern) + end, { + path = vim.fn.getcwd(), + type = "file", + limit = math.huge, + }) + end, + }, + ---@class rest.Config.UI + ui = { + ---@type boolean Whether to set winbar to result panes + winbar = true, + ---@class rest.Config.UI.Keybinds + keybinds = { + ---@type string Mapping for cycle to previous result pane + prev = "H", + ---@type string Mapping for cycle to next result pane + next = "L", + }, + }, + ---@class rest.Config.Highlight + highlight = { + ---@type boolean Whether current request highlighting is enabled or not + enable = true, + ---@type number Duration time of the request highlighting in milliseconds + timeout = 750, + }, + ---@see vim.log.levels + ---@type integer log level + _log_level = vim.log.levels.WARN, + } + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<localleader>h", group = "HTTP" }, + }) + end, + keys = { + { "<localleader>ho", ":Rest open<CR>", desc = "Open result pane" }, + { "<localleader>hr", ":Rest run<CR>", desc = "Run request under the cursor" }, + { "<localleader>hn", ":Rest run", desc = "Run request with name" }, + { "<localleader>hq", ":Rest last<CR>", desc = "Run last request" }, + { "<localleader>hl", ":Rest logs<CR>", desc = "Edit logs file" }, + { "<localleader>hc", ":Rest cookies<CR>", desc = "Edit cookies file" }, + { "<localleader>hd", ":Rest env show<CR>", desc = "Show dotenv file registered to current .http file" }, + { "<localleader>hs", ":Rest env select<CR>", desc = "Select & register .env file" }, + { "<localleader>ha", ":Rest env set", desc = "Register .env file to current .http file" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/sessions.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/sessions.lua new file mode 100644 index 0000000..3a644c1 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/sessions.lua @@ -0,0 +1,60 @@ +return { + "rmagatti/auto-session", + lazy = false, + config = function() + require("auto-session").setup({ + enabled = true, -- Enables/disables auto creating, saving and restoring + root_dir = vim.fn.stdpath("data") .. "/sessions/", -- Root dir where sessions will be stored + auto_save = true, -- Enables/disables auto saving session on exit + auto_restore = false, -- Enables/disables auto restoring session on start + auto_create = true, -- Enables/disables auto creating new session files. Can take a function that should return true/false if a new session file should be created or not + suppressed_dirs = nil, -- Suppress session restore/create in certain directories + allowed_dirs = nil, -- Allow session restore/create in certain directories + auto_restore_last_session = false, -- On startup, loads the last saved session if session for cwd does not exist + git_use_branch_name = true, -- Include git branch name in session name + git_auto_restore_on_branch_change = true, -- Should we auto-restore the session when the git branch changes. Requires git_use_branch_name + lazy_support = true, -- Automatically detect if Lazy.nvim is being used and wait until Lazy is done to make sure session is restored correctly. Does nothing if Lazy isn't being used. Can be disabled if a problem is suspected or for debugging + bypass_save_filetypes = nil, -- List of filetypes to bypass auto save when the only buffer open is one of the file types listed, useful to ignore dashboards + close_unsupported_windows = true, -- Close windows that aren't backed by normal file before autosaving a session + args_allow_single_directory = true, -- Follow normal sesion save/load logic if launched with a single directory as the only argument + args_allow_files_auto_save = false, -- Allow saving a session even when launched with a file argument (or multiple files/dirs). It does not load any existing session first. While you can just set this to true, you probably want to set it to a function that decides when to save a session when launched with file args. See documentation for more detail + continue_restore_on_error = true, -- Keep loading the session even if there's an error + show_auto_restore_notif = false, -- Whether to show a notification when auto-restoring + cwd_change_handling = false, -- Follow cwd changes, saving a session before change and restoring after + lsp_stop_on_restore = false, -- Should language servers be stopped when restoring a session. Can also be a function that will be called if set. Not called on autorestore from startup + restore_error_handler = nil, -- Called when there's an error restoring. By default, it ignores fold errors otherwise it displays the error and returns false to disable auto_save + purge_after_minutes = nil, -- Sessions older than purge_after_minutes will be deleted asynchronously on startup, e.g. set to 14400 to delete sessions that haven't been accessed for more than 10 days, defaults to off (no purging), requires >= nvim 0.10 + log_level = "error", -- Sets the log level of the plugin (debug, info, warn, error). + + session_lens = { + load_on_setup = true, -- Initialize on startup (requires Telescope) + theme_conf = { -- Pass through for Telescope theme options + layout_config = { -- As one example, can change width/height of picker + -- width = 0.8, -- percent of window + -- height = 0.5, + }, + }, + previewer = false, -- File preview for session picker + + mappings = { + -- Mode can be a string or a table, e.g. {"i", "n"} for both insert and normal mode + delete_session = { "i", "<C-X>" }, + alternate_session = { "i", "<C-S>" }, + copy_session = { "i", "<C-Y>" }, + }, + + session_control = { + control_dir = vim.fn.stdpath("data") .. "/auto_session/", -- Auto session control dir, for control files, like alternating between two sessions with session-lens + control_filename = "session_control.json", -- File name of the session control file + }, + }, + }) + end, + keys = { + { "<leader>fs", "<Cmd>SessionSearch<CR>", desc = "Session search" }, + { "<leader>ws", "<Cmd>SessionSave<CR>", desc = "Save session" }, + { "<leader>wx", "<Cmd>SessionDisableAutoSave<CR>", desc = "Disable autosave" }, + { "<leader>wp", "<Cmd>SessionPurgeOrphaned<CR>", desc = "Purge autosave" }, + { "<leader>wa", "<Cmd>SessionToggleAutoSave<CR>", desc = "Toggle autosave" }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/silicon.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/silicon.lua new file mode 100644 index 0000000..b708e60 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/silicon.lua @@ -0,0 +1,152 @@ +return { + "michaelrommel/nvim-silicon", + lazy = true, + cmd = "Silicon", + main = "nvim-silicon", + opts = { + -- Configuration here, or leave empty to use defaults + -- disable_defaults will disable all builtin default settings apart + -- from the base arguments, that are needed to call silicon at all, see + -- mandatory_options below, also those options can be overridden + -- all of the settings could be overridden in the lua setup call, + -- but this clashes with the use of an external silicon --config=file, + -- see issue #9 + disable_defaults = false, + -- turn on debug messages + debug = false, + -- most of them could be overridden with other + -- the font settings with size and fallback font + -- Example: font = "VictorMono NF=34;Noto Emoji", + font = nil, + -- the theme to use, depends on themes available to silicon + theme = "gruvbox-dark", + -- the background color outside the rendered os window + -- (in hexcode string e.g "#076678") + background = nil, + -- a path to a background image + background_image = nil, + -- the paddings to either side + pad_horiz = 100, + pad_vert = 80, + -- whether to have the os window rendered with rounded corners + no_round_corner = false, + -- whether to put the close, minimize, maximise traffic light + -- controls on the border + no_window_controls = false, + -- whether to turn off the line numbers + no_line_number = false, + -- with which number the line numbering shall start + line_offset = 1, + -- here a function is used to return the actual source code line number + -- line_offset = function(args) + -- return args.line1 + -- end, + + -- the distance between lines of code + line_pad = 0, + -- the rendering of tab characters as so many space characters + tab_width = 4, + -- with which language the syntax highlighting shall be done, should be + -- a function that returns either a language name or an extension like "js" + -- it is set to nil, so you can override it, if you do not set it, we try the + -- filetype first, and if that fails, the extension + language = nil, + -- language = function() + -- return vim.bo.filetype + -- end, + -- language = function() + -- return vim.fn.fnamemodify( + -- vim.api.nvim_buf_get_name(vim.api.nvim_get_current_buf()), + -- ":e" + -- ) + -- end, + + -- if the shadow below the os window should have be blurred + shadow_blur_radius = 16, + -- the offset of the shadow in x and y directions + shadow_offset_x = 8, + shadow_offset_y = 8, + -- the color of the shadow (in hexcode string e.g "#100808") + shadow_color = nil, + -- whether to strip of superfluous leading whitespace + gobble = true, + -- a string to pad each line with after gobbling removed larger indents, + num_separator = nil, + -- here a bar glyph is used to draw a vertial line and some space + -- num_separator = "\u{258f} ", + + -- whether to put the image onto the clipboard, may produce an error, + -- if run on WSL2 + to_clipboard = false, + -- a string or function returning a string that defines the title + -- showing in the image, only works in silicon versions greater than v0.5.1 + window_title = nil, + -- here a function is used to get the name of the current buffer + -- window_title = function() + -- return vim.fn.fnamemodify( + -- vim.api.nvim_buf_get_name(vim.api.nvim_get_current_buf()), + -- ":t" + -- ) + -- end, + + -- how to deal with the clipboard on WSL2 + -- possible values are: never, always, auto + wslclipboard = nil, + -- what to do with the temporary screenshot image file when using the Windows + -- clipboard from WSL2, possible values are: keep, delete + wslclipboardcopy = nil, + -- the silicon command, put an absolute location here, if the + -- command is not in your ${PATH} + command = "silicon", + -- a string or function that defines the path to the output image + -- output = nil, + -- here a function is used to create a file in the current directory + output = function() + local home_dir = vim.fn.expand("~") -- Get home directory + local timestamp = os.date("!%Y-%m-%d_%H-%M-%S") -- Get timestamp + local file_name = vim.fn.expand("%:t:r") -- Get the file name without extension + local file_extension = vim.fn.expand("%:e") + return home_dir + .. "/Pictures/screenshots" + .. timestamp + .. "_" + .. file_name + .. "_" + .. file_extension + .. ".png" + end, + }, + keys = { + { + "<leader>sc", + function() + require("nvim-silicon").clip() + end, + mode = "v", + desc = "Copy code screenshot to clipboard", + }, + { + "<leader>sf", + function() + require("nvim-silicon").file() + end, + mode = "v", + desc = "Save code screenshot as file", + }, + { + "<leader>ss", + function() + require("nvim-silicon").shoot() + end, + mode = "v", + desc = "Create code screenshot", + }, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "v" }, + { "<leader>s", group = "Snapshot" }, + }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/snippets.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/snippets.lua new file mode 100644 index 0000000..96c52a7 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/snippets.lua @@ -0,0 +1,72 @@ +return { + { + "L3MON4D3/LuaSnip", + version = "v2.*", + build = "make install_jsregexp", + dependencies = { + "rafamadriz/friendly-snippets", + config = function() + require("luasnip.loaders.from_vscode").lazy_load() + end, + }, + config = function() + local ls = require("luasnip") + ls.setup({ + link_children = true, + link_roots = false, + keep_roots = false, + update_events = { "TextChanged", "TextChangedI" }, + }) + local c = ls.choice_node + ls.choice_node = function(pos, choices, opts) + if opts then + opts.restore_cursor = true + else + opts = { restore_cursor = true } + end + return c(pos, choices, opts) + end + + require("luasnip.loaders.from_vscode").lazy_load({ + paths = { '"' .. vim.fn.stdpath("config") .. '/lua/TheSiahxyz/snippets"' }, + }) + + vim.cmd.runtime({ args = { "lua/TheSiahxyz/snippets/*.lua" }, bang = true }) -- load custom snippets + + vim.keymap.set({ "i", "x" }, "<A-L>", function() + if ls.expand_or_jumpable() then + ls.expand_or_jump() + end + end, { silent = true, desc = "Expand snippet or jump to the next snippet node" }) + + vim.keymap.set({ "i", "x" }, "<A-H>", function() + if ls.jumpable(-1) then + ls.jump(-1) + end + end, { silent = true, desc = "Previous spot in the snippet" }) + + vim.keymap.set({ "i", "x" }, "<A-l>", function() + if ls.choice_active() then + ls.change_choice(1) + end + end, { silent = true, desc = "Next snippet choice" }) + + vim.keymap.set({ "i", "x" }, "<A-h>", function() + if ls.choice_active() then + ls.change_choice(-1) + end + end, { silent = true, desc = "Previous snippet choice" }) + end, + keys = { + vim.keymap.set("i", "<tab>", function() + return require("luasnip").jumpable(1) and "<Plug>luasnip-jump-next" or "<tab>" + end, { expr = true, silent = true, desc = "Jump to next snippet" }), + vim.keymap.set("s", "<tab>", function() + require("luasnip").jump(1) + end, { desc = "Jump to next snippet" }), + vim.keymap.set({ "i", "s" }, "<s-tab>", function() + require("luasnip").jump(-1) + end, { desc = "Jump to Previous Snippet" }), + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua new file mode 100644 index 0000000..df8aad5 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua @@ -0,0 +1,427 @@ +return { + { + "amitds1997/remote-nvim.nvim", + version = "*", + dependencies = { + "nvim-lua/plenary.nvim", + "MunifTanjim/nui.nvim", + "nvim-telescope/telescope.nvim", + }, + config = true, + init = function() + local ok, wk = pcall(require, "which-key") + if ok then + wk.add({ { "<localleader>r", group = "SSH Remote" } }) + end + end, + keys = { + { "<localleader>rs", "<cmd>RemoteStart<CR>", desc = "Start/Connect", mode = "n", silent = true }, + { "<localleader>rx", "<cmd>RemoteStop<CR>", desc = "Stop/Close", mode = "n", silent = true }, + { "<localleader>ri", "<cmd>RemoteInfo<CR>", desc = "Info/Progress Viewer", mode = "n", silent = true }, + { "<localleader>rC", "<cmd>RemoteCleanup<CR>", desc = "Cleanup workspace", mode = "n", silent = true }, + + -- Delete saved config: show a list, allow multi-select, then run :RemoteConfigDel <name> + { + "<localleader>rd", + function() + local function get_names() + -- use command-line completion if the command supports it + local list = vim.fn.getcompletion("RemoteConfigDel ", "cmdline") or {} + return list + end + + local names = get_names() + if #names == 0 then + return vim.notify( + "No saved remote configs found (completion empty)", + vim.log.levels.INFO, + { title = "Remote" } + ) + end + + -- Prefer Telescope if present + local ok_picker, pickers = pcall(require, "telescope.pickers") + if ok_picker then + local finders = require("telescope.finders") + local conf = require("telescope.config").values + local actions = require("telescope.actions") + local state = require("telescope.actions.state") + + pickers + .new({}, { + prompt_title = "Delete Remote Config(s)", + finder = finders.new_table(names), + sorter = conf.generic_sorter({}), + attach_mappings = function(_, map) + local function run_delete(prompt_bufnr, picked) + local function del(name) + vim.api.nvim_cmd({ cmd = "RemoteConfigDel", args = { name } }, {}) + end + if picked and #picked > 0 then + for _, entry in ipairs(picked) do + del(entry.value or entry[1] or entry.text) + end + else + local entry = state.get_selected_entry() + if entry then + del(entry.value or entry[1] or entry.text) + end + end + actions.close(prompt_bufnr) + end + + actions.select_default:replace(function(bufnr) + local picker = state.get_current_picker(bufnr) + local multi = picker:get_multi_selection() + run_delete(bufnr, multi) + end) + + -- quality of life: <C-d> also deletes without closing (optional) + map("i", "<C-d>", function(bufnr) + local picker = state.get_current_picker(bufnr) + local multi = picker:get_multi_selection() + local function del(name) + vim.api.nvim_cmd({ cmd = "RemoteConfigDel", args = { name } }, {}) + end + if multi and #multi > 0 then + for _, e in ipairs(multi) do + del(e.value or e[1] or e.text) + end + else + local e = state.get_selected_entry() + if e then + del(e.value or e[1] or e.text) + end + end + -- keep picker open + end) + + return true + end, + }) + :find() + else + -- Fallback: vim.ui.select (single delete) + vim.ui.select(names, { prompt = "Select remote config to delete" }, function(choice) + if choice and choice ~= "" then + vim.api.nvim_cmd({ cmd = "RemoteConfigDel", args = { choice } }, {}) + end + end) + end + end, + desc = "Delete saved config (pick from list)", + mode = "n", + silent = true, + }, + + { "<localleader>rl", "<cmd>RemoteLog<CR>", desc = "Open log", mode = "n", silent = true }, + }, + }, + { + "nosduco/remote-sshfs.nvim", + dependencies = { "nvim-telescope/telescope.nvim", "nvim-lua/plenary.nvim" }, + opts = { + -- Refer to the configuration section below + -- or leave empty for defaults + }, + config = function() + require("remote-sshfs").setup({ + connections = { + ssh_configs = { -- which ssh configs to parse for hosts list + vim.fn.expand("$HOME") .. "/.ssh/config", + "/etc/ssh/ssh_config", + -- "/path/to/custom/ssh_config" + }, + ssh_known_hosts = vim.fn.expand("$HOME") .. "/.ssh/known_hosts", + -- NOTE: Can define ssh_configs similarly to include all configs in a folder + -- ssh_configs = vim.split(vim.fn.globpath(vim.fn.expand "$HOME" .. "/.ssh/configs", "*"), "\n") + sshfs_args = { -- arguments to pass to the sshfs command + "-o reconnect", + "-o ConnectTimeout=5", + }, + }, + mounts = { + base_dir = vim.fn.expand("$HOME") .. "/.sshfs/", -- base directory for mount points + unmount_on_exit = true, -- run sshfs as foreground, will unmount on vim exit + }, + handlers = { + on_connect = { + change_dir = true, -- when connected change vim working directory to mount point + }, + on_disconnect = { + clean_mount_folders = false, -- remove mount point folder on disconnect/unmount + }, + on_edit = {}, -- not yet implemented + }, + ui = { + select_prompts = false, -- not yet implemented + confirm = { + connect = true, -- prompt y/n when host is selected to connect to + change_dir = false, -- prompt y/n to change working directory on connection (only applicable if handlers.on_connect.change_dir is enabled) + }, + }, + log = { + enabled = false, -- enable logging + truncate = false, -- truncate logs + types = { -- enabled log types + all = false, + util = false, + handler = false, + sshfs = false, + }, + }, + }) + local api = require("remote-sshfs.api") + vim.keymap.set("n", "<localleader>rc", api.connect, { desc = "Connect SSH" }) + vim.keymap.set("n", "<localleader>rd", function() + local mountpoint = vim.fn.getcwd() + local ok = vim.system({ "diskutil", "unmount", "force", mountpoint }):wait().code == 0 + if not ok then + ok = vim.system({ "umount", "-f", mountpoint }):wait().code == 0 + end + print(ok and ("✅ Unmounted: " .. mountpoint) or ("⚠️ Failed to unmount: " .. mountpoint)) + end, { desc = "Force unmount macFUSE mount (quiet)" }) + vim.keymap.set("n", "<localleader>re", api.edit, { desc = "Edit SSH" }) + + -- (optional) Override telescope find_files and live_grep to make dynamic based on if connected to host + local builtin = require("telescope.builtin") + local connections = require("remote-sshfs.connections") + vim.keymap.set("n", "<localleader>rf", function() + if connections.is_connected() then + api.find_files() + else + builtin.find_files() + end + end, { desc = "Find SSH files" }) + vim.keymap.set("n", "<localleader>rg", function() + if connections.is_connected() then + api.live_grep() + else + builtin.live_grep() + end + end, { desc = "Live SSH grep" }) + require("telescope").load_extension("remote-sshfs") + end, + }, + { + "inhesrom/remote-ssh.nvim", + branch = "master", + dependencies = { + "inhesrom/telescope-remote-buffer", --See https://github.com/inhesrom/telescope-remote-buffer for features + "nvim-telescope/telescope.nvim", + "nvim-lua/plenary.nvim", + "neovim/nvim-lspconfig", + -- nvim-notify is recommended, but not necessarily required into order to get notifcations during operations - https://github.com/rcarriga/nvim-notify + "rcarriga/nvim-notify", + }, + config = function() + require("telescope-remote-buffer").setup( + -- Default keymaps to open telescope and search open buffers including "remote" open buffers + --fzf = "<leader>fz", + --match = "<leader>gb", + --oldfiles = "<leader>rb" + ) + + -- setup lsp_config here or import from part of neovim config that sets up LSP + require("remote-ssh").setup({ + -- Optional: Custom on_attach function for LSP clients + on_attach = function(client, bufnr) + -- Your LSP keybindings and setup + end, + + -- Optional: Custom capabilities for LSP clients + capabilities = vim.lsp.protocol.make_client_capabilities(), + + -- Custom mapping from filetype to LSP server name + filetype_to_server = { + -- Example: Use pylsp for Python (default and recommended) + python = "pylsp", + -- More customizations... + }, + + -- Custom server configurations + server_configs = { + -- Custom config for clangd + clangd = { + filetypes = { "c", "cpp", "objc", "objcpp" }, + root_patterns = { ".git", "compile_commands.json" }, + init_options = { + usePlaceholders = true, + completeUnimported = true, + }, + }, + -- More server configs... + }, + + -- Async write configuration + async_write_opts = { + timeout = 30, -- Timeout in seconds for write operations + debug = false, -- Enable debug logging + log_level = vim.log.levels.INFO, + autosave = true, -- Enable automatic saving on text changes (default: true) + -- Set to false to disable auto-save while keeping manual saves (:w) working + save_debounce_ms = 3000, -- Delay before initiating auto-save to handle rapid editing (default: 3000) + }, + }) + + -- Custom function to parse SSH config and extract Host entries + local function parse_ssh_hosts() + local ssh_config_path = vim.fn.expand("$HOME") .. "/.ssh/config" + local hosts = {} + local seen = {} + + -- Check if file exists + if vim.fn.filereadable(ssh_config_path) == 0 then + return hosts + end + + -- Read and parse SSH config file + local lines = vim.fn.readfile(ssh_config_path) + for _, line in ipairs(lines) do + -- Trim whitespace + local trimmed = vim.fn.trim(line) + -- Skip comments and empty lines + if trimmed ~= "" and not vim.startswith(trimmed, "#") then + -- Match "Host" keyword exactly (case-insensitive) followed by whitespace + -- Use pattern to ensure it's "Host " not "HostName" or other keywords + local host_match = string.match(string.lower(trimmed), "^host%s+(.+)$") + if host_match then + -- Handle multiple hosts on same line (space or comma separated) + for host in vim.gsplit(host_match, "[%s,]+") do + host = vim.fn.trim(host) + -- Skip wildcards and empty strings + if host ~= "" and host ~= "*" and not string.match(host, "^%*") and not seen[host] then + table.insert(hosts, host) + seen[host] = true + end + end + end + end + end + + return hosts + end + + -- Custom function to open RemoteTreeBrowser with selected SSH host + local function remote_tree_browser_picker() + local hosts = parse_ssh_hosts() + if #hosts == 0 then + return vim.notify( + "No SSH hosts found in ~/.ssh/config", + vim.log.levels.WARN, + { title = "Remote SSH" } + ) + end + + -- Use vim.ui.select (default Neovim UI) + vim.ui.select(hosts, { prompt = "Select SSH host for RemoteTreeBrowser" }, function(choice) + if choice and choice ~= "" then + -- Use rsync:// protocol with double slash (//) for SSH config Host aliases + -- Format: rsync://host-alias//path (double slash is required for SSH config aliases) + -- The plugin automatically detects and handles SSH config settings + local rsync_url = "rsync://" .. choice .. "//" + + -- Run RemoteTreeBrowser command + -- rsync:// protocol will use SSH config to resolve Host alias + vim.schedule(function() + -- Step 1: Create browser + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowser", args = { rsync_url } }, {}) + -- Step 2: Hide browser (needed for proper positioning) + vim.defer_fn(function() + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserHide" }, {}) + -- Step 3: Show browser (will open on the right side) + vim.defer_fn(function() + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserShow" }, {}) + end, 50) + end, 100) + end) + end + end) + end + + -- Toggle function for RemoteTreeBrowser show/hide + local function remote_tree_browser_toggle() + -- Try to access remote-ssh.nvim's TreeBrowser module + local ok, tree_browser = pcall(require, "remote-ssh.tree_browser") + if ok and tree_browser then + -- Check if browser buffer exists (like show_tree() does) + local bufnr = tree_browser.bufnr + if not bufnr or not vim.api.nvim_buf_is_valid(bufnr) then + -- Browser doesn't exist, show SSH config picker to create one + remote_tree_browser_picker() + return + end + + -- Browser buffer exists, check if window is visible (like hide_tree() does) + local win_id = tree_browser.win_id + local is_visible = win_id and vim.api.nvim_win_is_valid(win_id) + + if is_visible then + -- Browser is visible, hide it + if tree_browser.hide_tree then + tree_browser.hide_tree() + else + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserHide" }, {}) + end + -- After hiding, return early to prevent any further actions + return + else + -- Browser exists but hidden, show it + -- Directly use command instead of show_tree() to avoid any callbacks + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserShow" }, {}) + end + else + -- Fallback: only use this if module is not accessible + -- Check if browser buffer exists (not just visible windows) + local browser_buf_found = false + local browser_visible = false + + -- Check all buffers, not just visible windows + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_is_valid(buf) then + local buf_name = vim.api.nvim_buf_get_name(buf) + -- Check if it's a remote tree browser buffer + if buf_name:match("rsync://") then + browser_buf_found = true + -- Check if this buffer is visible in any window + for _, win in ipairs(vim.api.nvim_list_wins()) do + if vim.api.nvim_win_get_buf(win) == buf then + browser_visible = true + break + end + end + break + end + end + end + + if browser_buf_found then + -- Browser buffer exists + if browser_visible then + -- Browser is visible, hide it + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserHide" }, {}) + else + -- Browser exists but hidden, show it + vim.api.nvim_cmd({ cmd = "RemoteTreeBrowserShow" }, {}) + end + else + -- Browser not found, show SSH config picker + remote_tree_browser_picker() + end + end + end + + -- Keymap for custom RemoteTreeBrowser picker + vim.keymap.set("n", "<leader>er", remote_tree_browser_picker, { + desc = "RemoteTreeBrowser (pick SSH host)", + silent = true, + }) + + -- Keymap for toggle RemoteTreeBrowser show/hide + vim.keymap.set("n", "<leader>ef", remote_tree_browser_toggle, { + desc = "Toggle RemoteTreeBrowser", + silent = true, + }) + end, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/stay-centered.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/stay-centered.lua new file mode 100644 index 0000000..a2d5aa2 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/stay-centered.lua @@ -0,0 +1,29 @@ +return { + "arnamak/stay-centered.nvim", + lazy = false, + ft = { "markdown", "ipynb" }, + config = function() + require("stay-centered").setup({ + -- The filetype is determined by the vim filetype, not the file extension. In order to get the filetype, open a file and run the command: + -- :lua print(vim.bo.filetype) + skip_filetypes = {}, + -- Set to false to disable by default + enabled = true, + -- allows scrolling to move the cursor without centering, default recommended + allow_scroll_move = true, + -- temporarily disables plugin on left-mouse down, allows natural mouse selection + -- try disabling if plugin causes lag, function uses vim.on_key + disable_on_mouse = false, + }) + end, + keys = { + { + "<leader>zs", + function() + require("stay-centered").toggle() + end, + mode = { "n", "v" }, + desc = "Toggle stay center", + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/surround.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/surround.lua new file mode 100644 index 0000000..f3e0174 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/surround.lua @@ -0,0 +1,14 @@ +return { + "echasnovski/mini.surround", + version = "*", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "s", group = "Surround/Search & replace on line" }, + }) + end, + config = function() + require("mini.surround").setup() + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua new file mode 100644 index 0000000..ddb31de --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua @@ -0,0 +1,1133 @@ +local have_make = vim.fn.executable("make") == 1 +local have_cmake = vim.fn.executable("cmake") == 1 + +function vim.live_grep_from_project_git_root() + local function get_git_toplevel() + local path = vim.fn.system("git rev-parse --show-toplevel") + if vim.v.shell_error then + return nil + end + return path + end + + local opts = { cwd = get_git_toplevel() } + + require("telescope.builtin").live_grep(opts) +end + +local function find_nvim_plugin_files(prompt_bufnr) + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + + actions.close(prompt_bufnr) + + local selection = action_state.get_selected_entry() + if selection and selection.value then + -- Construct the full path + local base_path = vim.fn.stdpath("data") + local full_path = vim.fn.resolve(base_path .. "/" .. selection.value) + + require("mini.files").open(full_path, true) + end +end + +return { + { + "nvim-telescope/telescope-file-browser.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + }, + -- init = function() + -- vim.api.nvim_create_autocmd("VimEnter", { + -- group = vim.api.nvim_create_augroup("TelescopeFileBrowserStartDirectory", { clear = true }), + -- desc = "Start telescope-file-browser with directory", + -- once = true, + -- callback = function() + -- if package.loaded["telescope-file-browser.nvim"] then + -- return + -- else + -- local stats = vim.uv.fs_stat(vim.fn.argv(0)) + -- if stats and stats.type == "directory" then + -- require("telescope").extensions.file_browser.file_browser() + -- end + -- end + -- end, + -- }) + -- end, + config = function() + local fb_actions = require("telescope._extensions.file_browser.actions") + + require("telescope").setup({ + extensions = { + file_browser = { + path = vim.uv.cwd(), + cwd = vim.uv.cwd(), + cwd_to_path = false, + grouped = true, + files = true, + add_dirs = true, + depth = 1, + auto_depth = true, + select_buffer = true, + hidden = { file_browser = false, folder_browser = false }, + respect_gitignore = vim.fn.executable("fd") == 1, + no_ignore = true, + follow_symlinks = true, + browse_files = require("telescope._extensions.file_browser.finders").browse_files, + browse_folders = require("telescope._extensions.file_browser.finders").browse_folders, + hide_parent_dir = false, + collapse_dirs = true, + prompt_path = true, + quiet = true, + dir_icon = "", + dir_icon_hl = "Default", + display_stat = { date = true, size = true, mode = true }, + hijack_netrw = false, + use_fd = true, + git_status = true, + mappings = { + ["i"] = { + ["<C-a>"] = fb_actions.create, + ["<C-e>"] = fb_actions.create_from_prompt, + ["<C-r>"] = fb_actions.rename, + ["<C-d>"] = fb_actions.move, + ["<C-y>"] = fb_actions.copy, + ["<Del>"] = fb_actions.remove, + ["<C-o>"] = fb_actions.open, + ["<C-h>"] = fb_actions.goto_parent_dir, + ["<C-Space>"] = fb_actions.goto_home_dir, + ["<C-w>"] = fb_actions.goto_cwd, + ["<C-g>"] = fb_actions.change_cwd, + ["<C-f>"] = fb_actions.toggle_browser, + ["<C-_>"] = fb_actions.toggle_hidden, + ["<C-t>"] = fb_actions.toggle_all, + ["<bs>"] = fb_actions.backspace, + }, + ["n"] = { + ["a"] = fb_actions.create, + ["n"] = fb_actions.create_from_prompt, + ["r"] = fb_actions.rename, + ["d"] = fb_actions.move, + ["y"] = fb_actions.copy, + ["Del"] = fb_actions.remove, + ["o"] = fb_actions.open, + ["h"] = fb_actions.goto_parent_dir, + ["gh"] = fb_actions.goto_home_dir, + ["<C-w>"] = fb_actions.goto_cwd, + ["<C-g>"] = fb_actions.change_cwd, + ["f"] = fb_actions.toggle_browser, + ["/"] = fb_actions.toggle_hidden, + ["t"] = fb_actions.toggle_all, + }, + }, + results_title = vim.fn.fnamemodify(vim.uv.cwd(), ":~"), + }, + }, + }) + + require("telescope").load_extension("file_browser") + + vim.keymap.set( + "n", + "<leader>et", + ":Telescope file_browser path=%:p:h select_buffer=true<CR>", + { desc = "File browser (cwd)" } + ) + vim.keymap.set("n", "<leader>eT", ":Telescope file_browser<CR>", { desc = "File browser" }) + end, + }, + { + "nvim-telescope/telescope.nvim", + branch = "master", + dependencies = { + { "nvim-lua/plenary.nvim" }, + { + "nvim-telescope/telescope-fzf-native.nvim", + build = have_make and "make" + or "cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=Release && cmake --build build --config Release && cmake --install build --prefix build", + enabled = have_make or have_cmake, + config = function() + require("telescope").load_extension("fzf") + end, + }, + { + "nvim-telescope/telescope-github.nvim", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>gh", group = "gh" }, + }) + end, + config = function() + require("telescope").load_extension("gh") + vim.keymap.set({ "n", "v" }, "<leader>gi", ":Telescope gh issues ", { desc = "Find gh issues" }) + vim.keymap.set( + { "n", "v" }, + "<leader>gp", + ":Telescope gh pull_request ", + { desc = "Find gh pull request" } + ) + vim.keymap.set({ "n", "v" }, "<leader>ght", ":Telescope gh gist ", { desc = "Find gh gist" }) + vim.keymap.set({ "n", "v" }, "<leader>ghr", ":Telescope gh run ", { desc = "Find gh run" }) + end, + }, + { + "nvim-telescope/telescope-ui-select.nvim", + config = function() + require("telescope").setup({ + extensions = { + ["ui-select"] = { + require("telescope.themes").get_dropdown({ + -- even more opts + }), + + -- pseudo code / specification for writing custom displays, like the one + -- for "codeactions" + -- specific_opts = { + -- make_indexed = function(items) -> indexed_items, width, + -- [kind] = { + -- make_displayer = function(widths) -> displayer + -- make_display = function(displayer) -> function(e) + -- make_ordinal = function(e) -> string + -- }, + -- -- for example to disable the custom builtin "codeactions" display + -- do the following + -- codeactions = false, + -- } + }, + }, + }) + require("telescope").load_extension("ui-select") + end, + }, + { + "jvgrootveld/telescope-zoxide", + dependencies = { "nvim-lua/popup.nvim" }, + config = function() + require("telescope").setup({ + extensions = { + zoxide = { + prompt_title = "[ TheSiahxyz ]", + mappings = { + default = { + action = function(selection) + vim.cmd.cd(selection.path) + end, + after_action = function(selection) + print("Update to (" .. selection.z_score .. ") " .. selection.path) + end, + }, + ["<C-s>"] = { + action = require("telescope._extensions.zoxide.utils").create_basic_command( + "split" + ), + opts = { desc = "split" }, + }, + ["<C-v>"] = { + action = require("telescope._extensions.zoxide.utils").create_basic_command( + "vsplit" + ), + }, + ["<C-e>"] = { + action = require("telescope._extensions.zoxide.utils").create_basic_command( + "edit" + ), + }, + ["<C-b>"] = { + keepinsert = true, + action = function(selection) + require("telescope").extensions.file_browser.file_browser({ + cwd = selection.path, + }) + end, + }, + }, + }, + }, + }) + require("telescope").load_extension("zoxide") + + vim.keymap.set("n", "<leader>fz", function() + require("telescope").extensions.zoxide.list() + end, { desc = "Find files (zoxide)" }) + end, + }, + { + "nvim-telescope/telescope-live-grep-args.nvim", + -- This will not install any breaking changes. + -- For major updates, this must be adjusted manually. + version = "^1.0.0", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>f", group = "Find" }, + { "<leader>F", group = "Find (root)" }, + { "<leader>fl", group = "Live grep" }, + }) + end, + config = function() + local lga_actions = require("telescope-live-grep-args.actions") + local actions = require("telescope.actions") + + require("telescope").setup({ + extensions = { + live_grep_args = { + auto_quoting = true, -- enable/disable auto-quoting + -- define mappings, e.g. + mappings = { -- extend mappings + i = { + ["<C-w>"] = lga_actions.quote_prompt(), + ["<C-i>"] = lga_actions.quote_prompt({ postfix = " --iglob " }), + -- freeze the current list and start a fuzzy search in the frozen list + ["<C-space>"] = actions.to_fuzzy_refine, + }, + }, + vimgrep_arguments = { + "rg", + "--color=never", + "--no-heading", + "--with-filename", + "--line-number", + "--column", + "--smart-case", + "--follow", + "--hidden", + "--no-ignore", + }, + -- ... also accepts theme settings, for example: + -- theme = "dropdown", -- use dropdown theme + -- theme = { }, -- use own theme spec + -- layout_config = { mirror=true }, -- mirror preview pane + }, + }, + }) + require("telescope").load_extension("live_grep_args") + vim.keymap.set("n", "<leader>flf", function() + require("telescope").extensions.live_grep_args.live_grep_args() + end, { desc = "Find live grep args" }) + + local live_grep_args_shortcuts = require("telescope-live-grep-args.shortcuts") + vim.keymap.set( + "n", + "<leader>ss", + live_grep_args_shortcuts.grep_word_under_cursor, + { desc = "Search shortcuts (Live grep)" } + ) + + local function search_git(visual) + -- Retrieve the git root path + local handle = io.popen("git rev-parse --show-toplevel") + if not handle then + print("Error: Unable to open git handle") + return + end + + local git_root_path = handle:read("*a"):gsub("%s+", "") + handle:close() + + if not git_root_path or git_root_path == "" then + print("Error: Unable to retrieve git root path") + return + end + + local opts = { + prompt_title = visual and ("Visual-Grep in " .. git_root_path) + or ("Live-Grep in " .. git_root_path), + shorten_path = false, + cwd = git_root_path, + file_ignore_patterns = { ".git", ".png", "tags" }, + initial_mode = "insert", + selection_strategy = "reset", + theme = require("telescope.themes").get_dropdown({}), + } + + if visual then + -- Capture the selected text in visual mode + vim.cmd('normal! "vy') + local visual_selection = vim.fn.getreg("v") + opts.search = visual_selection + require("telescope.builtin").grep_string(opts) + else + require("telescope.builtin").live_grep(opts) + end + end + + vim.keymap.set("n", "<leader>flg", function() + search_git(false) + end, { remap = true, silent = false, desc = "Live grep in the git root folder" }) + + vim.keymap.set("v", "<leader>flg", function() + search_git(true) + end, { remap = true, silent = false, desc = "Grep in the git root folder" }) + -- Retrieve the current tmux session path + -- This will not change when we navigate to a different pane + local function search_tmux(visual) + local handle = io.popen("tmux display-message -p '#{session_path}'") + if not handle then + print("Error: Unable to open tmux handle") + return + end + + local tmux_session_path = handle:read("*a"):gsub("%s+", "") + handle:close() + + if not tmux_session_path or tmux_session_path == "" then + print("Error: Unable to retrieve tmux session path") + return + end + + local opts = { + prompt_title = visual and ("Visual-Grep in " .. tmux_session_path) + or ("Live-Grep in " .. tmux_session_path), + shorten_path = false, + cwd = tmux_session_path, + file_ignore_patterns = { ".git", ".png", "tags" }, + initial_mode = "insert", + selection_strategy = "reset", + theme = require("telescope.themes").get_dropdown({}), + } + + if visual then + require("telescope.builtin").grep_string(opts) + else + require("telescope.builtin").live_grep(opts) + end + end + + vim.keymap.set("n", "<leader>flt", function() + search_tmux(false) + end, { remap = true, silent = false, desc = "Live grep in the current tmux session folder" }) + + vim.keymap.set("v", "<leader>flt", function() + search_tmux(true) + end, { remap = true, silent = false, desc = "Grep string in the current tmux session folder" }) + vim.api.nvim_set_keymap( + "v", + "<leader>fls", + 'y<esc>:Telescope live_grep default_text=<c-r>0<cr> search_dirs={"$PWD"}', + { noremap = true, silent = true, desc = "Live grep default text" } + ) + vim.keymap.set("n", "<leader>f/", function() + require("telescope.builtin").current_buffer_fuzzy_find( + require("telescope.themes").get_dropdown({ + winblend = 10, + previewer = false, + relative = "editor", + }) + ) + end, { desc = "Find in current buffer" }) + end, + }, + { + "xiyaowong/telescope-emoji.nvim", + config = function() + require("telescope").setup({ + extensions = { + emoji = { + action = function(emoji) + -- argument emoji is a table. + -- {name="", value="", cagegory="", description=""} + + vim.fn.setreg("*", emoji.value) + print([[Press p or "*p to paste this emoji]] .. emoji.value) + + -- insert emoji when picked + -- vim.api.nvim_put({ emoji.value }, 'c', false, true) + end, + }, + }, + }) + require("telescope").load_extension("emoji") + end, + keys = { + { "<leader>se", ":Telescope emoji<cr>", desc = "Search emoji" }, + }, + }, + { + "nvim-telescope/telescope-bibtex.nvim", + requires = { + { "nvim-telescope/telescope.nvim" }, + }, + config = function() + local bibtex_actions = require("telescope-bibtex.actions") + require("telescope").setup({ + extensions = { + bibtex = { + -- Use context awareness + context = true, + -- Use non-contextual behavior if no context found + -- This setting has no effect if context = false + context_fallback = true, + mappings = { + i = { + ["<CR>"] = bibtex_actions.key_append("%s"), -- format is determined by filetype if the user has not set it explictly + ["<C-e>"] = bibtex_actions.entry_append, + ["<C-a>"] = bibtex_actions.citation_append("{{author}} ({{year}}), {{title}}."), + }, + }, + }, + }, + }) + require("telescope").load_extension("bibtex") + end, + keys = { + { + "<leader>sB", + function() + require("telescope").extensions.bibtex.bibtex() + end, + desc = "Search bibtex", + }, + }, + }, + { + "mzlogin/vim-markdown-toc", + keys = { + { "<leader>tg", "<Cmd>GenTocGFM<CR>", desc = "Generate ToC to GFM" }, + { "<leader>tr", "<Cmd>GenTocRedcarpet<CR>", desc = "Generate ToC to Redcarpet" }, + { "<leader>tl", "<Cmd>GenTocGitLab<CR>", desc = "Generate ToC to Gitlab" }, + { "<leader>tm", "<Cmd>GenTocMarked<CR>", desc = "Generate ToC to Marked" }, + }, + }, + { + "ThePrimeagen/harpoon", + branch = "harpoon2", + dependencies = { "nvim-lua/plenary.nvim" }, + }, + { + "folke/trouble.nvim", + }, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>f", group = "Find" }, + { "<leader>fp", group = "Private/Public" }, + { "<leader>s", group = "Search" }, + { "<leader>sb", group = "Buffer" }, + }) + end, + config = function() + local actions = require("telescope.actions") + local actions_state = require("telescope.actions.state") + local actions_layout = require("telescope.actions.layout") + local open_with_trouble = require("trouble.sources.telescope").open + local add_to_trouble = require("trouble.sources.telescope").add + + local function telescope_open_single_or_multi(prompt_bufnr) + local picker = actions_state.get_current_picker(prompt_bufnr) + local multi = picker:get_multi_selection() + + -- If you selected multiple (with <Tab>), open them all. + if not vim.tbl_isempty(multi) then + actions.close(prompt_bufnr) + + for _, entry in ipairs(multi) do + -- Try to get a filepath across different pickers + local path = entry.path -- find_files, oldfiles, etc. + or entry.filename -- live_grep/grep_string + or (type(entry.value) == "string" and entry.value) + or (entry.value and entry.value.path) + + if path then + vim.cmd("edit " .. vim.fn.fnameescape(path)) + + -- (Optional) jump to the matched line/col for grep results + local lnum = entry.lnum or entry.row + local col = entry.col + if lnum then + vim.api.nvim_win_set_cursor(0, { lnum, math.max((col or 1) - 1, 0) }) + end + elseif entry.bufnr then + -- buffers picker + vim.cmd("buffer " .. entry.bufnr) + end + end + return + end + + -- Single selection → let Telescope handle it + -- This respects picker-specific behavior (e.g. jumping to lnum for grep). + actions.select_default(prompt_bufnr) + end + require("telescope").setup({ + defaults = { + mappings = { + i = { + ["<C-a>"] = add_to_trouble, + ["<C-e>"] = actions.complete_tag, + ["<C-g>"] = function(prompt_bufnr) + local selection = actions_state.get_selected_entry() + local dir = vim.fn.fnamemodify(selection.path, ":p:h") + actions.close(prompt_bufnr) + -- Depending on what you want put `cd`, `lcd`, `tcd` + vim.cmd(string.format("silent lcd %s", dir)) + end, + ["<C-u>"] = actions.nop, + ["<C-d>"] = actions.nop, + ["<C-b>"] = actions.nop, + ["<C-f>"] = actions_layout.toggle_preview, + ["<C-j>"] = actions.preview_scrolling_down, + ["<C-k>"] = actions.preview_scrolling_up, + ["<C-h>"] = actions.preview_scrolling_left, + ["<C-l>"] = actions.preview_scrolling_right, + ["<C-q>"] = actions.send_to_qflist + actions.open_qflist, + ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist, + ["<C-t>"] = open_with_trouble, + ["<C-z>"] = actions.select_horizontal, + ["<C-w>"] = { "<c-s-w>", type = "command" }, + ["<C-o><C-w>"] = actions.insert_original_cword, + ["<C-o><C-a>"] = actions.insert_original_cWORD, + ["<C-o><C-f>"] = actions.insert_original_cfile, + ["<C-o><C-l>"] = actions.insert_original_cline, + ["<M-f>"] = actions.nop, + ["<M-k>"] = actions.nop, + ["<CR>"] = telescope_open_single_or_multi, + }, + n = { + ["q"] = actions.close, + ["<C-a>"] = add_to_trouble, + ["<C-c>"] = actions.close, + ["<C-d>"] = actions.nop, + ["<C-u>"] = actions.nop, + ["<C-f>"] = actions_layout.toggle_preview, + ["<C-b>"] = actions.nop, + ["<C-e>"] = actions.complete_tag, + ["<C-g>"] = { + function(prompt_bufnr) + local selection = actions_state.get_selected_entry() + local dir = vim.fn.fnamemodify(selection.path, ":p:h") + actions.close(prompt_bufnr) + -- Depending on what you want put `cd`, `lcd`, `tcd` + vim.cmd(string.format("silent lcd %s", dir)) + end, + opts = { desc = "Change directory" }, + }, + ["<C-j>"] = actions.preview_scrolling_down, + ["<C-k>"] = actions.preview_scrolling_up, + ["<C-h>"] = actions.preview_scrolling_left, + ["<C-l>"] = actions.preview_scrolling_right, + ["<C-q>"] = actions.send_to_qflist + actions.open_qflist, + ["<M-q>"] = actions.send_selected_to_qflist + actions.open_qflist, + ["<C-t>"] = open_with_trouble, + ["<C-z>"] = actions.select_horizontal, + ["<M-f"] = actions.nop, + ["<M-k"] = actions.nop, + }, + }, + file_ignore_patterns = { + "node_modules", + "yarn.lock", + ".git", + "^.git/", + "%/bin/zsh/", + ".sl", + "_build", + ".next", + "LICENSE", + "%lock%.json", + }, + find_command = { + "rg", + "--files", + "--follow", + "--hidden", + "--no-ignore", + "--sortr=modified", + }, + hidden = true, + path_display = { + "filename_first", + }, + git_worktrees = { + { + home = vim.env.HOME, + private = vim.env.HOME .. "/Private/repos", + public = vim.env.HOME .. "/Public/repos", + }, + }, + results_title = vim.fn.fnamemodify(vim.uv.cwd(), ":~"), + scroll_strategy = "limit", + }, + pickers = { + buffers = { + mappings = { + i = { + ["<C-x>"] = actions.delete_buffer, + }, + n = { + ["dd"] = actions.delete_buffer, + ["<C-x>"] = actions.delete_buffer, + }, + }, + }, + find_files = { + -- `hidden = true` will still show the inside of `.git/` as it's not `.gitignore`d. + find_command = { + "rg", + "--files", + "--follow", + "--hidden", + "--sortr=modified", + "--glob", + "!**/.cache/*/*/*", + "--glob", + "!**/.git/*/*/*", + "--glob", + "!**/.next/*/*/*", + "--glob", + "!**/node_modules/*/*/*", + }, + }, + }, + }) + + -- find + vim.keymap.set({ "i", "n" }, "<C-b>", function() + require("telescope.builtin").buffers({ + sort_mru = true, + sort_lastused = true, + -- initial_mode = "normal", + }) + end, { desc = "Find buffer files" }) + vim.keymap.set("n", "<leader>fb", function() + require("telescope.builtin").buffers({ + sort_mru = true, + sort_lastused = true, + -- initial_mode = "normal", + }) + end, { desc = "Find buffer files" }) + vim.keymap.set("n", "<leader>fc", function() + require("telescope.builtin").find_files({ cwd = vim.fn.expand("~/.config") }) + end, { desc = "Find config files" }) + vim.keymap.set("n", "<leader>fd", function() + require("telescope.builtin").find_files({ cwd = vim.fn.expand("~/.dotfiles") }) + end, { desc = "Find dotfiles files" }) + vim.keymap.set({ "n", "i" }, "<C-f>", function() + require("telescope.builtin").find_files() + end, { desc = "Find files" }) + vim.keymap.set("n", "<leader>ff", function() + require("telescope.builtin").find_files() + end, { desc = "Find files" }) + vim.keymap.set("n", "<leader>f<leader>", function() + local pickers = require("telescope.pickers") + local finders = require("telescope.finders") + local sorters = require("telescope.config").values.generic_sorter + local previewers = require("telescope.previewers") + local entry_display = require("telescope.pickers.entry_display") + + -- Get list of open buffers + local opened_files = {} + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_is_loaded(buf) then + local name = vim.api.nvim_buf_get_name(buf) + if name ~= "" then + opened_files[name] = true + end + end + end + + -- Create the custom picker + pickers + .new({}, { + prompt_title = "Find Files", + finder = finders.new_oneshot_job({ "fd", "--type", "f" }, { + entry_maker = function(entry) + local is_open = opened_files[vim.fn.fnamemodify(entry, ":p")] -- Match absolute paths + local displayer = entry_display.create({ + separator = " ", + items = { + { width = 1 }, -- Marker width + { remaining = true }, -- Filepath + }, + }) + + return { + value = entry, + ordinal = entry, + display = function() + return displayer({ is_open and "*" or " ", entry }) + end, + path = entry, + } + end, + }), + sorter = sorters({}), + previewer = previewers.vim_buffer_cat.new({}), + }) + :find() + end, { desc = "Find files with open markers" }) + + vim.keymap.set("n", "<leader>FF", function() + require("telescope.builtin").find_files({ + cwd = vim.fn.expand("~"), + find_command = { + "rg", + "--files", + "--follow", + "--hidden", + "--glob", + "!**/.cache/*/*/*", + "--glob", + "!**/.mozilla/*", + "--glob", + "!**/.local/lib/*/*", + "--glob", + "!**/.local/share/*/*", + "--glob", + "!**/.local/state/*/*/*/*", + "--sortr=modified", + }, + }) + end, { desc = "Find root files" }) + vim.keymap.set("n", "<leader>fk", function() + require("telescope.builtin").find_files({ + cwd = vim.fn.expand("~/.local/src/suckless/"), + find_command = { + "find", + "-maxdepth", + "2", + "-type", + "f", + "-name", + ".git", + "-prune", + "-o", + }, + }) + end, { desc = "Find suckless files" }) + vim.keymap.set("n", "<leader>fg", function() + require("telescope.builtin").git_files() + end, { desc = "Find git files" }) + vim.keymap.set("n", "<leader>fo", function() + require("telescope.builtin").oldfiles({}) + end, { desc = "Find old files" }) + vim.keymap.set("n", "<leader>fpv", function() + require("telescope.builtin").find_files({ cwd = vim.fn.expand("~/Private") }) + end, { desc = "Find private files" }) + vim.keymap.set("n", "<leader>fpb", function() + require("telescope.builtin").find_files({ cwd = vim.fn.expand("~/Public") }) + end, { desc = "Find public files" }) + vim.keymap.set("n", "<leader>fa", function() + require("telescope.builtin").find_files({ + cwd = vim.fn.expand("~/.local/bin"), + }) + end, { desc = "Find script files" }) + vim.keymap.set("n", "<leader>fv", function() + require("telescope.builtin").find_files({ + cwd = vim.fn.stdpath("config"), + find_command = { "fd", "--type", "f", "--follow", "--color", "never", "--extension", "lua" }, + }) + end, { desc = "Find neovim config files" }) + vim.keymap.set("n", "<leader>fV", function() + require("telescope.builtin").find_files({ + cwd = vim.fn.stdpath("data"), + find_command = { + "find", + "-maxdepth", + "2", + "-type", + "d", + "-iname", + ".git", + "-prune", + "-o", + }, + attach_mappings = function(_, map) + map("i", "<CR>", find_nvim_plugin_files) + map("n", "<CR>", find_nvim_plugin_files) + return true + end, + }) + end, { desc = "Find neovim plugin files" }) + -- git + vim.keymap.set("n", "<leader>gc", function() + require("telescope.builtin").git_commits() + end, { desc = "Find git commits" }) + vim.keymap.set("n", "<leader>gC", function() + require("telescope.builtin").git_bcommits() + end, { desc = "Find buffer git commits" }) + vim.keymap.set("n", "<leader>gb", function() + require("telescope.builtin").git_branches() + end, { desc = "Find branches" }) + vim.keymap.set("n", "<leader>gl", function() + require("telescope.builtin").git_bcommits_range() + end, { desc = "Find lines git commits" }) + vim.keymap.set("v", "<leader>gl", function() + require("telescope.builtin").git_bcommits_range() + end, { desc = "Find lines git commits" }) + vim.keymap.set("n", "<leader>gs", function() + require("telescope.builtin").git_status() + end, { desc = "Find git status" }) + vim.keymap.set("n", "<leader>gS", function() + require("telescope.builtin").git_stash() + end, { desc = "Find git stash" }) + -- lsp + vim.keymap.set("n", "gd", function() + require("telescope.builtin").lsp_definitions({}) + end, { desc = "Find definitions" }) + vim.keymap.set("n", "gR", function() + require("telescope.builtin").lsp_references({}) + end, { desc = "Find references" }) + -- search + vim.keymap.set("n", "<leader>cc", function() + require("telescope.builtin").colorscheme({}) + end, { desc = "Search color scheme" }) + vim.keymap.set("n", "<leader>sa", function() + require("telescope.builtin").autocommands({}) + end, { desc = "Search auto commands" }) + vim.keymap.set("n", "<leader>sb", function() + require("telescope.builtin").current_buffer_fuzzy_find({}) + end, { desc = "Search current buffers " }) + vim.keymap.set("n", "<leader>st", function() + require("telescope.builtin").current_buffer_tags({}) + end, { desc = "Search current buffer tags" }) + vim.keymap.set("n", "<leader>sc", function() + require("telescope.builtin").commands({}) + end, { desc = "Search commands" }) + vim.keymap.set("n", "<leader>sC", function() + require("telescope.builtin").command_history({}) + end, { desc = "Search history" }) + vim.keymap.set("n", "<leader>sd", function() + require("telescope.builtin").diagnostics({}) + end, { desc = "Search diagonostics" }) + vim.keymap.set("n", "<leader>sg", vim.live_grep_from_project_git_root, { desc = "Live grep (git)" }) + vim.keymap.set("n", "<leader>sh", function() + require("telescope.builtin").help_tags({}) + end, { desc = "Search help tags" }) + vim.keymap.set("n", "<leader>sH", function() + require("telescope.builtin").highlights({}) + end, { desc = "Search highlights" }) + vim.keymap.set("n", "<leader>sj", function() + require("telescope.builtin").jumplist({}) + end, { desc = "Search jump list" }) + vim.keymap.set({ "n", "v", "x" }, "<leader>skb", function() + require("telescope.builtin").keymaps({}) + end, { desc = "Search key bindings" }) + vim.keymap.set("n", "<leader>skk", function() + local word = vim.fn.expand("<cword>") + require("telescope.builtin").grep_string({ search = word }) + end, { desc = "Search words under cursor" }) + vim.keymap.set("n", "<leader>skK", function() + local word = vim.fn.expand("<cWORD>") + require("telescope.builtin").grep_string({ search = word }) + end, { desc = "Search all words under cursor" }) + vim.keymap.set("n", "<leader>sl", function() + require("telescope.builtin").loclist({}) + end, { desc = "Search location list" }) + vim.keymap.set("n", "<leader>s'", function() + require("telescope.builtin").marks({}) + end, { desc = "Search marks" }) + vim.keymap.set("n", "<leader>sM", function() + require("telescope.builtin").man_pages({}) + end, { desc = "Search man pages" }) + vim.keymap.set("n", "<leader>so", function() + require("telescope.builtin").vim_options({}) + end, { desc = "Search vim options" }) + vim.keymap.set("n", "<leader>sq", function() + require("telescope.builtin").quickfix({}) + end, { desc = "Search quickfix list" }) + vim.keymap.set("n", "<leader>sQ", function() + require("telescope.builtin").quickfixhistory({}) + end, { desc = "Search quickfix history" }) + vim.keymap.set("n", '<leader>s"', function() + require("telescope.builtin").registers({}) + end, { desc = "Search registers" }) + vim.keymap.set("n", "<leader>sr", function() + require("telescope.builtin").resume({}) + end, { desc = "Search resume" }) + vim.keymap.set("n", "<leader>sf", function() + require("telescope.builtin").filetypes({}) + end, { desc = "Search file types" }) + vim.keymap.set("n", "<leader>sw", function() + require("telescope.builtin").live_grep({}) + end, { desc = "Search word (Live grep)" }) + vim.keymap.set("n", "<leader>sW", function() + require("telescope.builtin").grep_string({}) + end, { desc = "Search word (Grep)" }) + end, + }, + { + "cljoly/telescope-repo.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + }, + config = function() + require("telescope").setup({ + extensions = { + repo = { + list = { + fd_opts = { + "--no-ignore-vcs", + }, + file_ignore_patterns = { + "^" .. vim.env.HOME .. "/%.cache/", + "^" .. vim.env.HOME .. "/%.cargo/", + }, + }, + }, + }, + }) + + require("telescope").load_extension("repo") + end, + keys = { + { mode = "n", "<leader>fG", "<Cmd>Telescope repo list<cr>", desc = "Find git files (repo)" }, + }, + }, + { + "debugloop/telescope-undo.nvim", + dependencies = { -- note how they're inverted to above example + { + "nvim-telescope/telescope.nvim", + dependencies = { "nvim-lua/plenary.nvim" }, + }, + }, + opts = { + -- don't use `defaults = { }` here, do this in the main telescope spec + extensions = { + undo = { + -- telescope-undo.nvim config, see below + }, + -- no other extensions here, they can have their own spec too + }, + }, + config = function(_, opts) + -- Calling telescope's setup from multiple specs does not hurt, it will happily merge the + -- configs for us. We won't use data, as everything is in it's own namespace (telescope + -- defaults, as well as each extension). + require("telescope").setup(opts) + require("telescope").load_extension("undo") + end, + keys = { + { -- lazy style key map + "<leader>fu", + "<Cmd>Telescope undo<cr>", + desc = "Find undo history", + }, + }, + }, + { + "nvim-telescope/telescope-frecency.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + }, + config = function() + require("telescope").setup({ + extensions = { + frecency = { + auto_validate = false, + matcher = "fuzzy", + }, + }, + }) + + require("telescope").load_extension("frecency") + + vim.keymap.set("n", "<leader>fr", function() + require("telescope").extensions.frecency.frecency({ + workspace = "CWD", + }) + end, { desc = "Find frequency files" }) + + vim.keymap.set("n", "<leader>flq", function() + local frecency = require("telescope").extensions.frecency + require("telescope.builtin").live_grep({ + search_dirs = frecency.query({}), + }) + end, { desc = "Find frequency live grep" }) + + vim.keymap.set("n", "<leader>qd", "<Cmd>FrecencyDelete<cr>", { desc = "Delete current buffer frequency" }) + end, + }, + { + "nvim-telescope/telescope-media-files.nvim", + dependencies = { + "nvim-lua/popup.nvim", + "nvim-lua/plenary.nvim", + "nvim-telescope/telescope.nvim", + }, + config = function() + require("telescope").setup({ + extensions = { + media_files = { + -- filetypes whitelist + -- defaults to {"png", "jpg", "mp4", "webm", "pdf"} + filetypes = { "png", "jpg", "mp4", "mkv", "webm", "pdf" }, + -- find command (defaults to `fd`) + find_cmd = "rg", + }, + }, + }) + require("telescope").load_extension("media_files") + end, + keys = { + { + "<leader>fm", + "<Cmd>Telescope media_files<cr>", + desc = "Find media files", + }, + }, + }, + { + "nvim-telescope/telescope-project.nvim", + dependencies = { + "nvim-telescope/telescope.nvim", + "nvim-telescope/telescope-file-browser.nvim", + }, + config = function() + local project_actions = require("telescope._extensions.project.actions") + require("telescope").setup({ + extensions = { + project = { + base_dirs = { + { path = "~/Private", max_depth = 2 }, + { path = "~/Public", max_depth = 2 }, + }, + mappings = { + i = { + ["<C-x>"] = project_actions.delete_project, + ["<C-r>"] = project_actions.rename_project, + ["<C-a>"] = project_actions.add_project, + ["<C-A>"] = project_actions.add_project_cwd, + ["<C-f>"] = project_actions.find_project_files, + ["<C-b>"] = project_actions.browse_project_files, + ["<C-s>"] = project_actions.search_in_project_files, + ["<C-o>"] = project_actions.recent_project_files, + ["<C-g>"] = project_actions.change_working_directory, + ["<C-l>"] = project_actions.next_cd_scope, + ["<C-w>"] = project_actions.change_workspace, + }, + n = { + ["x"] = project_actions.delete_project, + ["r"] = project_actions.rename_project, + ["c"] = project_actions.add_project, + ["C"] = project_actions.add_project_cwd, + ["f"] = project_actions.find_project_files, + ["b"] = project_actions.browse_project_files, + ["s"] = project_actions.search_in_project_files, + ["o"] = project_actions.recent_project_files, + ["g"] = project_actions.change_working_directory, + ["l"] = project_actions.next_cd_scope, + }, + }, + }, + }, + }) + require("telescope").load_extension("project") + end, + keys = { + { + "<leader>fpj", + "<Cmd>Telescope projects<cr>", + desc = "Find projects", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/textobject.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/textobject.lua new file mode 100644 index 0000000..b82eac6 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/textobject.lua @@ -0,0 +1,173 @@ +return { + "nvim-treesitter/nvim-treesitter-textobjects", + branch = "main", + dependencies = { + { "nvim-treesitter/nvim-treesitter", build = ":TSUpdate" }, + { + "chrisgrieser/nvim-various-textobjs", + event = "UIEnter", + opts = { + keymaps = { + useDefaults = true, + }, + }, + }, + }, + init = function() + -- Disable entire built-in ftplugin mappings to avoid conflicts. + -- See https://github.com/neovim/neovim/tree/master/runtime/ftplugin for built-in ftplugins. + vim.g.no_plugin_maps = true + + -- Or, disable per filetype (add as you like) + -- vim.g.no_python_maps = true + -- vim.g.no_ruby_maps = true + -- vim.g.no_rust_maps = true + -- vim.g.no_go_maps = true + + local wk = require("which-key") + wk.add({ + { + mode = { "n", "v", "x" }, + { "g>", group = "Swap next" }, + { "g<", group = "Swap prev" }, + { "<leader>]", group = "Next" }, + { "<leader>[", group = "Prev" }, + }, + }) + end, + config = function() + require("nvim-treesitter-textobjects").setup({ + select = { + -- Automatically jump forward to textobj, similar to targets.vim + lookahead = true, + -- You can choose the select mode (default is charwise 'v') + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * method: eg 'v' or 'o' + -- and should return the mode ('v', 'V', or '<c-v>') or a table + -- mapping query_strings to modes. + selection_modes = { + ["@parameter.outer"] = "v", -- charwise + ["@function.outer"] = "V", -- linewise + ["@class.outer"] = "<c-v>", -- blockwise + }, + -- If you set this to `true` (default is `false`) then any textobject is + -- extended to include preceding or succeeding whitespace. Succeeding + -- whitespace has priority in order to act similarly to eg the built-in + -- `ap`. + -- + -- Can also be a function which gets passed a table with the keys + -- * query_string: eg '@function.inner' + -- * selection_mode: eg 'v' + -- and should return true of false + include_surrounding_whitespace = false, + }, + move = { + -- whether to set jumps in the jumplist + set_jumps = true, + }, + }) + + -- keymaps + -- You can use the capture groups defined in `textobjects.scm` + vim.keymap.set({ "x", "o" }, "am", function() + require("nvim-treesitter-textobjects.select").select_textobject("@function.outer", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "im", function() + require("nvim-treesitter-textobjects.select").select_textobject("@function.inner", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "ac", function() + require("nvim-treesitter-textobjects.select").select_textobject("@class.outer", "textobjects") + end) + vim.keymap.set({ "x", "o" }, "ic", function() + require("nvim-treesitter-textobjects.select").select_textobject("@class.inner", "textobjects") + end) + -- You can also use captures from other query groups like `locals.scm` + vim.keymap.set({ "x", "o" }, "as", function() + require("nvim-treesitter-textobjects.select").select_textobject("@local.scope", "locals") + end) + -- keymaps + vim.keymap.set("n", "<leader>a", function() + require("nvim-treesitter-textobjects.swap").swap_next("@parameter.inner") + end) + vim.keymap.set("n", "<leader>A", function() + require("nvim-treesitter-textobjects.swap").swap_previous("@parameter.outer") + end) + -- You can use the capture groups defined in `textobjects.scm` + vim.keymap.set({ "n", "x", "o" }, "]m", function() + require("nvim-treesitter-textobjects.move").goto_next_start("@function.outer", "textobjects") + end) + vim.keymap.set({ "n", "x", "o" }, "]]", function() + require("nvim-treesitter-textobjects.move").goto_next_start("@class.outer", "textobjects") + end) + -- You can also pass a list to group multiple queries. + vim.keymap.set({ "n", "x", "o" }, "]o", function() + move.goto_next_start({ "@loop.inner", "@loop.outer" }, "textobjects") + end) + -- You can also use captures from other query groups like `locals.scm` or `folds.scm` + vim.keymap.set({ "n", "x", "o" }, "]s", function() + require("nvim-treesitter-textobjects.move").goto_next_start("@local.scope", "locals") + end) + vim.keymap.set({ "n", "x", "o" }, "]z", function() + require("nvim-treesitter-textobjects.move").goto_next_start("@fold", "folds") + end) + + vim.keymap.set({ "n", "x", "o" }, "]M", function() + require("nvim-treesitter-textobjects.move").goto_next_end("@function.outer", "textobjects") + end) + vim.keymap.set({ "n", "x", "o" }, "][", function() + require("nvim-treesitter-textobjects.move").goto_next_end("@class.outer", "textobjects") + end) + + vim.keymap.set({ "n", "x", "o" }, "[m", function() + require("nvim-treesitter-textobjects.move").goto_previous_start("@function.outer", "textobjects") + end) + vim.keymap.set({ "n", "x", "o" }, "[[", function() + require("nvim-treesitter-textobjects.move").goto_previous_start("@class.outer", "textobjects") + end) + + vim.keymap.set({ "n", "x", "o" }, "[M", function() + require("nvim-treesitter-textobjects.move").goto_previous_end("@function.outer", "textobjects") + end) + vim.keymap.set({ "n", "x", "o" }, "[]", function() + require("nvim-treesitter-textobjects.move").goto_previous_end("@class.outer", "textobjects") + end) + + -- Go to either the start or the end, whichever is closer. + -- Use if you want more granular movements + vim.keymap.set({ "n", "x", "o" }, "]d", function() + require("nvim-treesitter-textobjects.move").goto_next("@conditional.outer", "textobjects") + end) + vim.keymap.set({ "n", "x", "o" }, "[d", function() + require("nvim-treesitter-textobjects.move").goto_previous("@conditional.outer", "textobjects") + end) + + local ts_repeat_move = require("nvim-treesitter-textobjects.repeatable_move") + + -- Repeat movement with ; and , + -- ensure ; goes forward and , goes backward regardless of the last direction + vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move_next) + vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_previous) + + -- vim way: ; goes to the direction you were moving. + -- vim.keymap.set({ "n", "x", "o" }, ";", ts_repeat_move.repeat_last_move) + -- vim.keymap.set({ "n", "x", "o" }, ",", ts_repeat_move.repeat_last_move_opposite) + + -- Optionally, make builtin f, F, t, T also repeatable with ; and , + vim.keymap.set({ "n", "x", "o" }, "f", ts_repeat_move.builtin_f_expr, { expr = true }) + vim.keymap.set({ "n", "x", "o" }, "F", ts_repeat_move.builtin_F_expr, { expr = true }) + vim.keymap.set({ "n", "x", "o" }, "t", ts_repeat_move.builtin_t_expr, { expr = true }) + vim.keymap.set({ "n", "x", "o" }, "T", ts_repeat_move.builtin_T_expr, { expr = true }) + + -- This repeats the last query with always previous direction and to the start of the range. + vim.keymap.set({ "n", "x", "o" }, "<home>", function() + ts_repeat_move.repeat_last_move({ forward = false, start = true }) + end) + + -- This repeats the last query with always next direction and to the end of the range. + vim.keymap.set({ "n", "x", "o" }, "<end>", function() + ts_repeat_move.repeat_last_move({ forward = true, start = false }) + end) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/todo.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/todo.lua new file mode 100644 index 0000000..87c168b --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/todo.lua @@ -0,0 +1,77 @@ +return { + { + "vimichael/floatingtodo.nvim", + config = function() + require("floatingtodo").setup({ + target_file = "~/.local/share/vimwiki/todo.md", + border = "single", -- single, rounded, etc. + width = 0.8, -- width of window in % of screen size + height = 0.8, -- height of window in % of screen size + position = "center", -- topleft, topright, bottomleft, bottomright + }) + vim.keymap.set("n", "<leader>tf", ":Td<CR>", { silent = true, desc = "TODO floating" }) + end, + }, + { + "folke/todo-comments.nvim", + event = { "BufReadPre", "BufNewFile" }, + dependencies = { "nvim-lua/plenary.nvim" }, + config = function() + require("todo-comments").setup({ + keywords = { + FIX = { + icon = " ", -- icon used for the sign, and in search results + color = "error", -- can be a hex color, or a named color (see below) + alt = { "FIXME", "BUG", "FIXIT", "ISSUE" }, -- a set of other keywords that all map to this FIX keywords + -- signs = false, -- configure signs for some keywords individually + }, + TODO = { icon = " ", color = "info" }, + HACK = { icon = " ", color = "warning" }, + WARN = { icon = " ", color = "warning", alt = { "WARNING", "XXX" } }, + PERF = { icon = " ", alt = { "OPTIM", "PERFORMANCE", "OPTIMIZE" } }, + NOTE = { icon = " ", color = "hint", alt = { "INFO" } }, + TEST = { icon = " ", color = "test", alt = { "TESTING", "PASSED", "FAILED" } }, + }, + colors = { + error = { "DiagnosticError", "ErrorMsg", "#DC2626" }, + warning = { "DiagnosticWarn", "WarningMsg", "#FBBF24" }, + info = { "DiagnosticInfo", "#2563EB" }, + hint = { "DiagnosticHint", "#10B981" }, + default = { "Identifier", "#7C3AED" }, + test = { "Identifier", "#FF00FF" }, + }, + }) + end, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>t", group = "TODO" }, + }) + end, + keys = { + { + "]t", + function() + require("todo-comments").jump_next() + end, + desc = "Next Todo Comment", + }, + { + "[t", + function() + require("todo-comments").jump_prev() + end, + desc = "Previous Todo Comment", + }, + { "<leader>tt", "<Cmd>Trouble todo toggle<cr>", desc = "Toggle TODO (Trouble)" }, + { + "<leader>tT", + "<Cmd>Trouble todo toggle filter = {tag = {TODO,FIX,FIXME}}<cr>", + desc = "Toggle Todo/Fix/Fixme (Trouble)", + }, + { "<leader>ft", "<Cmd>TodoTelescope<cr>", desc = "Find Todo" }, + { "<leader>fT", "<Cmd>TodoTelescope keywords=TODO,FIX,FIXME<cr>", desc = "Find Todo/Fix/Fixme" }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/treesitter.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/treesitter.lua new file mode 100644 index 0000000..7a9639c --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/treesitter.lua @@ -0,0 +1,38 @@ +return { + "nvim-treesitter/nvim-treesitter", + lazy = false, + build = ":TSUpdate", + dependencies = { "nvim-treesitter/nvim-treesitter-textobjects" }, + config = function() + require("nvim-treesitter").setup({ + install_dir = vim.fn.stdpath("data") .. "/treesitter", + }) + end, + keys = { + { "<leader>TU", ":TSUpdate<cr>", desc = "Update treesitter" }, + { + "<leader>TI", + function() + require("nvim-treesitter").install({ + "bash", + "c", + "cpp", + "dockerfile", + "html", + "java", + "javascript", + "json5", + "latex", + "lua", + "markdown", + "markdown_inline", + "python", + "sql", + "vim", + "vimdoc", + }) + end, + desc = "Update treesitter", + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ufo.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ufo.lua new file mode 100644 index 0000000..ca7cf03 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ufo.lua @@ -0,0 +1,138 @@ +return { + "kevinhwang91/nvim-ufo", + dependencies = { "kevinhwang91/promise-async" }, + cmd = { + "UfoEnable", + "UfoDisable", + "UfoInspect", + "UfoAttach", + "UfoDetach", + "UfoEnableFold", + "UfoDisableFold", + }, + config = function() + vim.o.foldcolumn = "1" + vim.o.foldlevel = 99 + vim.o.foldlevelstart = 99 + vim.o.foldenable = true + + local caps = vim.lsp.protocol.make_client_capabilities() + caps.textDocument.foldingRange = { dynamicRegistration = false, lineFoldingOnly = true } + local ok_cmp, cmp = pcall(require, "cmp_nvim_lsp") + if ok_cmp then + caps = cmp.default_capabilities(caps) + end + local lsp_util = require("lspconfig.util") + lsp_util.default_config = lsp_util.default_config or {} + lsp_util.default_config.capabilities = + vim.tbl_deep_extend("force", lsp_util.default_config.capabilities or {}, caps) + + local ftMap = { + vim = "indent", + python = { "indent" }, + git = "", + markdown = { "treesitter", "indent" }, + } + + local function chain_selector(bufnr) + local ufo = require("ufo") + local Promise = require("promise") + local function fallback(err, provider) + if type(err) == "string" and err:match("UfoFallbackException") then + return ufo.getFolds(bufnr, provider) + else + return Promise.reject(err) + end + end + return require("ufo") + .getFolds(bufnr, "lsp") + :catch(function(err) + return fallback(err, "treesitter") + end) + :catch(function(err) + return fallback(err, "indent") + end) + end + + local function fold_virt_text_handler(virtText, lnum, endLnum, width, truncate) + local newVirtText = {} + local suffix = (" %d "):format(endLnum - lnum) + local sufWidth = vim.fn.strdisplaywidth(suffix) + local targetWidth = width - sufWidth + local curWidth = 0 + for _, chunk in ipairs(virtText) do + local text, hl = chunk[1], chunk[2] + local chunkWidth = vim.fn.strdisplaywidth(text) + if targetWidth > curWidth + chunkWidth then + table.insert(newVirtText, { text, hl }) + else + local truncated = truncate(text, targetWidth - curWidth) + table.insert(newVirtText, { truncated, hl }) + chunkWidth = vim.fn.strdisplaywidth(truncated) + if curWidth + chunkWidth < targetWidth then + suffix = suffix .. (" "):rep(targetWidth - curWidth - chunkWidth) + end + break + end + curWidth = curWidth + chunkWidth + end + table.insert(newVirtText, { suffix, "MoreMsg" }) + return newVirtText + end + + local function peek_or_hover() + local ufo = require("ufo") + local winid = ufo.peekFoldedLinesUnderCursor() + if winid then + local bufnr = vim.api.nvim_win_get_buf(winid) + for _, k in ipairs({ "a", "i", "o", "A", "I", "O", "gd", "gr" }) do + vim.keymap.set("n", k, "<CR>" .. k, { noremap = false, buffer = bufnr }) + end + else + if vim.lsp.buf.hover then + vim.lsp.buf.hover() + end + end + end + + local function go_prev_and_peek() + require("ufo").goPreviousClosedFold() + require("ufo").peekFoldedLinesUnderCursor() + end + + local function go_next_and_peek() + require("ufo").goNextClosedFold() + require("ufo").peekFoldedLinesUnderCursor() + end + + local function apply_folds_then_close_all(providerName) + require("async")(function() + local bufnr = vim.api.nvim_get_current_buf() + require("ufo").attach(bufnr) + local ranges = await(require("ufo").getFolds(bufnr, providerName)) + if not vim.tbl_isempty(ranges) then + if require("ufo").applyFolds(bufnr, ranges) then + require("ufo").closeAllFolds() + end + end + end) + end + + require("ufo").setup({ + provider_selector = function(bufnr, filetype, buftype) + return ftMap[filetype] or chain_selector + end, + fold_virt_text_handler = fold_virt_text_handler, + enable_get_fold_virt_text = true, + }) + + vim.keymap.set("n", "zM", require("ufo").closeAllFolds, { desc = "Close all folds" }) + vim.keymap.set("n", "zR", require("ufo").openAllFolds, { desc = "Open all folds" }) + vim.keymap.set("n", "zp", peek_or_hover, { desc = "Peek folded / LSP hover" }) + vim.keymap.set("n", "[z", go_prev_and_peek, { desc = "Prev fold & peek" }) + vim.keymap.set("n", "]z", go_next_and_peek, { desc = "Next fold & peek" }) + vim.keymap.set("n", "<leader>za", function() + apply_folds_then_close_all("lsp") + end, { desc = "Apply LSP folds & close all" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua new file mode 100644 index 0000000..69e7762 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua @@ -0,0 +1,132 @@ +return { + "axieax/urlview.nvim", + dependencies = "nvim-telescope/telescope.nvim", + event = "VeryLazy", + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n", "v" }, + { "<leader>u", group = "URLs" }, + { "<leader>uc", group = "Copy URLs" }, + }) + end, + config = function() + -- Define custom search for thesiah_urls + local thesiah = require("urlview.search") + thesiah["thesiah_urls"] = function() + local urls = {} + local files = { + vim.fn.expand("~/.local/share/thesiah/urls"), + vim.fn.expand("~/.local/share/thesiah/snippets"), + } + + -- Check if the file exists and read each file + for _, filepath in ipairs(files) do + if vim.fn.filereadable(filepath) == 1 then + local file = io.open(filepath, "r") + if file then + for line in file:lines() do + -- Match and capture URLs + for url in line:gmatch("https?://[%w%./%-_%%]+") do + table.insert(urls, url) + end + end + file:close() + else + vim.notify("Unable to open " .. filepath, vim.log.levels.ERROR) + end + else + vim.notify("File not found: " .. filepath, vim.log.levels.WARN) + end + end + + return urls + end + + local search = require("urlview.search") + local search_helpers = require("urlview.search.helpers") + + -- Custom search function for Tmux plugins + search["tmux_plugins"] = function() + local urls = {} + local filepath = vim.fn.expand("~/.config/tmux/tmux.conf") + + -- Check if the tmux.conf file exists + if vim.fn.filereadable(filepath) == 1 then + local file = io.open(filepath, "r") + if file then + for line in file:lines() do + -- Match lines that contain Tmux plugin URLs (TPM syntax) + -- Example: set -g @plugin 'tmux-plugins/tpm' + local url = line:match("@plugin%s+'([^']+)'") + if url then + -- Convert to full GitHub URL if not already a full URL + if not url:match("^https?://") then + url = "https://github.com/" .. url + end + table.insert(urls, url) + end + end + file:close() + else + vim.notify("Unable to open " .. filepath, vim.log.levels.ERROR) + end + else + vim.notify("File not found: " .. filepath, vim.log.levels.WARN) + end + + return urls + end + + -- Load urlview + require("urlview").setup({ + -- Prompt title (`<context> <default_title>`, e.g. `Buffer Links:`) + default_title = "Links:", + -- Default picker to display links with + -- Options: "native" (vim.ui.select) or "telescope" + default_picker = "native", + -- Set the default protocol for us to prefix URLs with if they don't start with http/https + default_prefix = "https://", + -- Command or method to open links with + -- Options: "netrw", "system" (default OS browser), "clipboard"; or "firefox", "chromium" etc. + -- By default, this is "netrw", or "system" if netrw is disabled + default_action = "system", + -- Set the register to use when yanking + -- Default: + (system clipboard) + default_register = "+", + -- Whether plugin URLs should link to the branch used by your package manager + default_include_branch = true, + -- Ensure links shown in the picker are unique (no duplicates) + unique = true, + -- Ensure links shown in the picker are sorted alphabetically + sorted = true, + -- Minimum log level (recommended at least `vim.log.levels.WARN` for error detection warnings) + log_level_min = vim.log.levels.INFO, + -- Keymaps for jumping to previous / next URL in buffer + jump = { + prev = "[u", + next = "]u", + }, + }) + + -- Add a keymap for the Tmux plugins search context + vim.keymap.set("n", "<leader>ub", "<Cmd>UrlView<cr>", { desc = "Buffer URLs" }) + vim.keymap.set("n", "<leader>ul", "<Cmd>UrlView lazy<cr>", { desc = "Lazy plugin URLs" }) + vim.keymap.set("n", "<leader>us", "<Cmd>UrlView thesiah_urls<cr>", { desc = "Bookmarks URLs" }) + vim.keymap.set("n", "<leader>ut", "<Cmd>UrlView tmux_plugins<cr>", { desc = "Tmux plugin URLs" }) + vim.keymap.set( + "n", + "<leader>ucb", + "<Cmd>UrlView thesiah_urls action=clipboard<cr>", + { desc = "clipboard bookmarks URLs" } + ) + vim.keymap.set("n", "<leader>ucl", "<Cmd>UrlView lazy action=clipboard<cr>", { desc = "Copy Lazy plugin URLs" }) + vim.keymap.set("n", "<leader>ucr", "<Cmd>UrlView action=clipboard<cr>", { desc = "Copy buffer URLs" }) + vim.keymap.set( + "n", + "<leader>uct", + "<Cmd>UrlView tmux_plugins action=clipboard<cr>", + { desc = "clipboard tmux plugin URLs" } + ) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/virt-column.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/virt-column.lua new file mode 100644 index 0000000..cadc77c --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/virt-column.lua @@ -0,0 +1,17 @@ +return { + "lukas-reineke/virt-column.nvim", + opts = { + -- char = "|", + -- char = "", + -- char = "┇", + -- char = "║", + -- char = "∶", + -- char = "∷", + char = "⋮", + -- char = "", + -- char = "", + -- char = "", + -- char = "", + virtcolumn = "80", + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua new file mode 100644 index 0000000..07a115c --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua @@ -0,0 +1,173 @@ +return { + { + "vimwiki/vimwiki", + cmd = { "VimwikiIndex" }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>w", group = "Vimwiki/Which-key" }, + { "<leader>w<leader>", group = "Diary" }, + }) + + -- Set up Vimwiki list + vim.g.vimwiki_list = { + { + path = vim.fn.expand("~/.local/share/vimwiki"), + template_path = vim.fn.expand("~/.local/share/vimwiki/templates"), + auto_toc = 1, + syntax = "markdown", + nested_syntaxes = { + python = "python", + ["c++"] = "cpp", + }, + ext = ".md", + }, + } + + vim.g.vimwiki_global_ext = 1 + + -- Ensure files are read with the desired filetype + vim.g.vimwiki_ext2syntax = { + [".Rmd"] = "markdown", + [".rmd"] = "markdown", + [".md"] = "markdown", + [".markdown"] = "markdown", + [".mdown"] = "markdown", + } + end, + keys = { + { "<leader>ww", ":VimwikiIndex<CR>", desc = "Vimwiki index" }, + { "<leader>wu", ":VimwikiUISelect<CR>", desc = "Vimwiki UI" }, + }, + }, + { + "tools-life/taskwiki", + ft = "vimwiki", + event = "VeryLazy", + dependencies = { + "vimwiki/vimwiki", + { + "powerman/vim-plugin-AnsiEsc", + config = function() + pcall(vim.keymap.del, "n", "<leader>swp") + pcall(vim.keymap.del, "n", "<leader>rwp") + end, + }, + "majutsushi/tagbar", + "farseer90718/vim-taskwarrior", + }, + config = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>tb", group = "Burndown" }, + { "<leader>tc", group = "Choose" }, + { "<leader>tG", group = "Ghistory" }, + { "<leader>th", group = "History" }, + }) + + vim.g.taskwiki_markup_syntax = "markdown" + vim.g.taskwiki_data_location = "~/.local/share/task" + end, + }, + { + "renerocksai/telekasten.nvim", + dependencies = { + "nvim-telescope/telescope.nvim", + { + "nvim-telekasten/calendar-vim", + init = function() + vim.g.calendar_diary = "~/.local/share/vimwiki/diary" + vim.g.calendar_no_mappings = 1 + end, + keys = { { "<leader>cA", "<Cmd>CalendarT<CR>", desc = "Open calendar" } }, + }, + }, + init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>n", group = "Notes" }, + }) + end, + config = function() + require("telekasten").setup({ + home = vim.fn.expand("~/.local/share/vimwiki"), -- Put the name of your notes directory here + }) + end, + keys = { + { + "<leader>fn", + function() + require("telekasten").find_notes() + end, + desc = "Find notes", + }, + { + "<leader>np", + function() + require("telekasten").panel() + end, + desc = "Open note panel", + }, + { + "<leader>sn", + function() + require("telekasten").search_notes() + end, + desc = "Search notes", + }, + { + "<leader>nt", + function() + require("telekasten").goto_today() + end, + desc = "Goto today notes", + }, + { + "<leader>nl", + function() + require("telekasten").follow_link() + end, + desc = "Follow link", + }, + { + "<leader>nn", + function() + require("telekasten").new_note() + end, + desc = "Open new note", + }, + { + "<leader>ca", + function() + require("telekasten").show_calendar() + end, + desc = "Show calendar", + }, + { + "<leader>nb", + function() + require("telekasten").show_backlinks() + end, + desc = "Show backlinks", + }, + { + "<leader>ii", + function() + require("telekasten").insert_img_link() + end, + desc = "Insert image link", + }, + { + "]]", + function() + require("telekasten").insert_link() + end, + mode = "i", + desc = "Insert link", + }, + }, + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua new file mode 100644 index 0000000..b41ee24 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua @@ -0,0 +1,270 @@ +return { + "mikavilpas/yazi.nvim", + version = "*", -- use the latest stable version + event = "VeryLazy", + dependencies = { + { "nvim-lua/plenary.nvim", lazy = true }, + { + "akinsho/toggleterm.nvim", + version = "*", + config = function() + require("toggleterm").setup({ + open_mapping = [[<leader><c-s>]], -- or { [[<c-\>]], [[<c-¥>]] } if you also use a Japanese keyboard. + }) + vim.keymap.set( + "n", + "<leader><C-\\>", + "<Cmd>ToggleTerm direction=float name=Terminal<cr>", + { desc = "Toggle float terminal" } + ) + vim.keymap.set( + "n", + "<leader><C-t>", + "<Cmd>ToggleTermToggleAll<cr>", + { desc = "Toggle all float terminals" } + ) + vim.keymap.set("n", "<leader><C-u>", "<Cmd>TermSelect<cr>", { desc = "Select float terminal" }) + + local function set_opfunc(opfunc) + _G._opfunc = opfunc -- Define the function globally + vim.go.operatorfunc = "v:lua._opfunc" -- Assign the global function + end + + local trim_spaces = false + vim.keymap.set("v", "<leader><C-l>", function() + require("toggleterm").send_lines_to_terminal("single_line", trim_spaces, { args = vim.v.count }) + end, { desc = "Send line to terminal" }) + -- Replace with these for the other two options + -- require("toggleterm").send_lines_to_terminal("visual_lines", trim_spaces, { args = vim.v.count }) + -- require("toggleterm").send_lines_to_terminal("visual_selection", trim_spaces, { args = vim.v.count }) + + -- For use as an operator map: + -- Send motion to terminal + vim.keymap.set("n", "<leader><C-l>", function() + set_opfunc(function(motion_type) + require("toggleterm").send_lines_to_terminal(motion_type, false, { args = vim.v.count }) + end) + vim.api.nvim_feedkeys("g@", "n", false) + end, { desc = "Send motions to terminal" }) + -- Double the command to send line to terminal + vim.keymap.set("n", "<leader><C-a>", function() + set_opfunc(function(motion_type) + require("toggleterm").send_lines_to_terminal(motion_type, false, { args = vim.v.count }) + end) + vim.api.nvim_feedkeys("g@_", "n", false) + end, { desc = "Send double command to terminal" }) + -- Send whole file + vim.keymap.set("n", "<leader><C-g>", function() + set_opfunc(function(motion_type) + require("toggleterm").send_lines_to_terminal(motion_type, false, { args = vim.v.count }) + end) + vim.api.nvim_feedkeys("ggg@G''", "n", false) + end, { desc = "Send whole file to terminal (clipboard)" }) + end, + }, + }, + keys = { + { + "<leader>ey", + mode = { "n", "v" }, + "<cmd>Yazi<cr>", + desc = "Open yazi at the current file", + }, + { + -- Open in the current working directory + "<leader>eY", + "<cmd>Yazi cwd<cr>", + desc = "Open the file manager in nvim's working directory", + }, + { + "zy", + "<cmd>Yazi toggle<cr>", + desc = "Resume the last yazi session", + }, + }, + ---@type YaziConfig | {} + opts = { + -- Below is the default configuration. It is optional to set these values. + -- You can customize the configuration for each yazi call by passing it to + -- yazi() explicitly + + -- enable this if you want to open yazi instead of netrw. + -- Note that if you enable this, you need to call yazi.setup() to + -- initialize the plugin. lazy.nvim does this for you in certain cases. + -- + -- If you are also using neotree, you may prefer not to bring it up when + -- opening a directory: + -- { + -- "nvim-neo-tree/neo-tree.nvim", + -- opts = { + -- filesystem = { + -- hijack_netrw_behavior = "disabled", + -- }, + -- }, + -- } + open_for_directories = false, + + -- open visible splits and quickfix items as yazi tabs for easy navigation + -- https://github.com/mikavilpas/yazi.nvim/pull/359 + open_multiple_tabs = false, + + -- when yazi is closed with no file chosen, change the Neovim working + -- directory to the directory that yazi was in before it was closed. Defaults + -- to being off (`false`) + change_neovim_cwd_on_close = false, + + highlight_groups = { + -- See https://github.com/mikavilpas/yazi.nvim/pull/180 + hovered_buffer = nil, + -- See https://github.com/mikavilpas/yazi.nvim/pull/351 + hovered_buffer_in_same_directory = nil, + }, + + -- the floating window scaling factor. 1 means 100%, 0.9 means 90%, etc. + floating_window_scaling_factor = 0.8, + + -- the transparency of the yazi floating window (0-100). See :h winblend + yazi_floating_window_winblend = 0, + + -- the type of border to use for the floating window. Can be many values, + -- including 'none', 'rounded', 'single', 'double', 'shadow', etc. For + -- more information, see :h nvim_open_win + yazi_floating_window_border = "single", + + -- the zindex of the yazi floating window. Can be used to make the yazi + -- window fullscreen. See `:h nvim_open_win()` for more information. + yazi_floating_window_zindex = nil, + + -- the log level to use. Off by default, but can be used to diagnose + -- issues. You can find the location of the log file by running + -- `:checkhealth yazi` in Neovim. Also check out the "reproducing issues" + -- section below + log_level = vim.log.levels.OFF, + + -- what Neovim should do a when a file was opened (selected) in yazi. + -- Defaults to simply opening the file. + open_file_function = function(chosen_file, config, state) end, + + -- customize the keymaps that are active when yazi is open and focused. The + -- defaults are listed below. Note that the keymaps simply hijack input and + -- they are never sent to yazi, so only try to map keys that are never + -- needed by yazi. + -- + -- Also: + -- - use e.g. `open_file_in_tab = false` to disable a keymap + -- - you can customize only some of the keymaps (not all of them) + -- - you can opt out of all keymaps by setting `keymaps = false` + keymaps = { + show_help = "<f1>", + open_file_in_vertical_split = "<c-v>", + open_file_in_horizontal_split = "<c-x>", + open_file_in_tab = "<c-t>", + grep_in_directory = "<c-s>", + replace_in_directory = "<c-g>", + cycle_open_buffers = "<tab>", + copy_relative_path_to_selected_files = "<c-y>", + send_to_quickfix_list = "<c-q>", + change_working_directory = "<c-\\>", + open_and_pick_window = "<c-o>", + }, + + -- completely override the keymappings for yazi. This function will be + -- called in the context of the yazi terminal buffer. + set_keymappings_function = function(yazi_buffer_id, config, context) end, + + -- some yazi.nvim commands copy text to the clipboard. This is the register + -- yazi.nvim should use for copying. Defaults to "*", the system clipboard + clipboard_register = "*", + + hooks = { + -- if you want to execute a custom action when yazi has been opened, + -- you can define it here. + yazi_opened = function(preselected_path, yazi_buffer_id, config) + -- you can optionally modify the config for this specific yazi + -- invocation if you want to customize the behaviour + end, + + -- when yazi was successfully closed + yazi_closed_successfully = function(chosen_file, config, state) end, + + -- when yazi opened multiple files. The default is to send them to the + -- quickfix list, but if you want to change that, you can define it here + yazi_opened_multiple_files = function(chosen_files, config, state) end, + + -- This function is called when yazi is ready to process events. + on_yazi_ready = function(buffer, config, process_api) end, + }, + + -- highlight buffers in the same directory as the hovered buffer + highlight_hovered_buffers_in_same_directory = true, + + integrations = { + --- What should be done when the user wants to grep in a directory + grep_in_directory = function(directory) + -- the default implementation uses telescope if available, otherwise nothing + end, + + grep_in_selected_files = function(selected_files) + -- similar to grep_in_directory, but for selected files + end, + + --- Similarly, search and replace in the files in the directory + replace_in_directory = function(directory) + -- default: grug-far.nvim + end, + + replace_in_selected_files = function(selected_files) + -- default: grug-far.nvim + end, + + -- `grealpath` on OSX, (GNU) `realpath` otherwise + resolve_relative_path_application = "", + + -- the way to resolve relative paths. The default_implementation can be + -- customized with a function. See + -- documentation/copy-relative-path-to-files.md for more information. + resolve_relative_path_implementation = function(args, get_relative_path) end, + + -- how to delete (close) a buffer. Defaults to a bundled version of + -- `snacks.bufdelete`, copied from https://github.com/folke/snacks.nvim, + -- which maintains the window layout. See the `types.lua` file for more + -- information for the available options. + bufdelete_implementation = "bundled-snacks", + + -- add an action to a file picker to copy the relative path to the + -- selected file(s). The implementation is the same as for the + -- `copy_relative_path_to_selected_files` yazi.nvim keymap. Currently + -- only snacks.nvim is supported. Documentation can be found in the + -- keybindings section of the readme. + -- + -- available options: + -- - nil (default, no action added) + -- - "snacks.picker" (snacks.nvim) + picker_add_copy_relative_path_action = nil, + }, + + future_features = { + -- use a file to store the last directory that yazi was in before it was + -- closed. Defaults to `true`. + use_cwd_file = true, + + -- use a new shell escaping implementation that is more robust and works + -- on more platforms. Defaults to `true`. If set to `false`, the old + -- shell escaping implementation will be used, which is less robust and + -- may not work on all platforms. + new_shell_escaping = true, + }, + }, + -- 👇 if you use `open_for_directories=true`, this is recommended + init = function() + -- mark netrw as loaded so it's not loaded at all. + -- + -- More details: https://github.com/mikavilpas/yazi.nvim/issues/802 + -- vim.g.loaded_netrwPlugin = 1 + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "<leader>ey", group = "Yazi" }, + }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua new file mode 100644 index 0000000..52b6656 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua @@ -0,0 +1,82 @@ +return { + "folke/zen-mode.nvim", + opts = {}, + config = function() + _G.ZenWinbar = function() + local bt = vim.bo.buftype + if bt ~= "" then + return "" -- scratch, terminal, help, quickfix 등은 숨김 + end + local name = vim.api.nvim_buf_get_name(0) + if name == nil or name == "" then + return "" -- 이름 없는 새 버퍼도 숨김 + end + return vim.fn.fnamemodify(name, ":t") -- 파일명만 + end + local function apply_winbar_for_current() + vim.wo.winbar = "%{%v:lua.ZenWinbar()%}" + end + local function apply_winbar_for_all() + for _, win in ipairs(vim.api.nvim_list_wins()) do + vim.api.nvim_set_option_value("winbar", "%{%v:lua.ZenWinbar()%}", { win = win }) + end + end + local function clear_winbar_for_all() + for _, win in ipairs(vim.api.nvim_list_wins()) do + vim.api.nvim_set_option_value("winbar", nil, { win = win }) + end + end + local aug = vim.api.nvim_create_augroup("ZenWinbar", { clear = true }) + + vim.keymap.set("n", "<leader>zz", function() + require("zen-mode").toggle({ + window = { + width = 90, + }, + -- callback where you can add custom code when the Zen window opens + on_open = function() + vim.wo.wrap = true + vim.wo.number = true + vim.wo.rnu = true + apply_winbar_for_all() + vim.api.nvim_create_autocmd({ "BufWinEnter", "WinEnter" }, { + group = aug, + callback = apply_winbar_for_current, + }) + end, + -- callback where you can add custom code when the Zen window closes + on_close = function() + vim.wo.wrap = false + vim.wo.number = true + vim.wo.rnu = true + vim.api.nvim_clear_autocmds({ group = aug }) + clear_winbar_for_all() + ColorMyPencils() + end, + }) + end, { desc = "Toggle zenmode" }) + + vim.keymap.set("n", "<leader>zZ", function() + require("zen-mode").toggle({ + window = { + width = 90, + }, + -- callback where you can add custom code when the Zen window opens + on_open = function() + vim.wo.wrap = true + vim.wo.number = false + vim.wo.rnu = false + vim.opt.colorcolumn = "0" + ColorMyPencils("seoul256") + end, + -- callback where you can add custom code when the Zen window closes + on_close = function() + vim.wo.wrap = false + vim.wo.number = true + vim.wo.rnu = true + ColorMyPencils() + end, + }) + end, { desc = "Toggle zenmode (goyo)" }) + end, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/journal.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/journal.lua new file mode 100644 index 0000000..22e0dad --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/journal.lua @@ -0,0 +1,119 @@ +local ls = require("luasnip") + +local s = ls.snippet +local i = ls.insert_node +local t = ls.text_node +local c = ls.choice_node +local f = ls.function_node + +local fmt = require("luasnip.extras.fmt").fmta + +-- get weather from wttr.in +local function get_weather() + local q = os.getenv("JOURNAL_WEATHER_QUERY") + local url = q and ("wttr.in/" .. q .. "?format=1") or "wttr.in/?format=1" + local handle = io.popen(("curl -m 2 -s '%s'"):format(url)) + if not handle then + return "" + end + local result = handle:read("*a") or "" + handle:close() + return (result:gsub("[\r\n]", "")) +end + +local journal_snippet = s( + "journal", + fmt( + [[--- +title: <title> +date: <date> +tags: [diary, journal] +mood: <mood> +weather: <weather> +--- + +# Daily Journal + +## Diary (Personal Events & Feelings) + +- What happened today? + <happened> +- How did I feel? + <feeling> +- Memorable moments + <moments> + +## Journal (Learning & Reflections) + +- What I learned today + <learned> +- Challenges faced + <challenges> +- Ideas & inspirations + <ideas> + +## Plans for Tomorrow + +- <plans> + +## Gratitude + +1. <gratitude1> +2. <gratitude2> +3. <gratitude3> +4. <gratitude4> +5. <gratitude5> +6. <gratitude6> +7. <gratitude7> +8. <gratitude8> +9. <gratitude9> +10. <gratitude10> +]], + { + title = i(1, "My Journal"), + date = f(function() + return os.date("%Y-%m-%d") + end, {}), + mood = c(2, { + i(nil, ""), -- default: manual input + t("😊 happy"), + t("😢 sad"), + t("😴 tired"), + t("😤 stressed"), + t("😌 relaxed"), + t("🤩 excited"), + t("😟 anxious"), + t("🎯 focused"), + t("😐 neutral"), + t("🙏 grateful"), + t("🤒 sick"), + t("😡 angry"), + t("🌊 calm"), + t("😵 overwhelmed"), + t("💪 motivated"), + t("🥱 bored"), + }), + weather = f(get_weather, {}), + happened = i(3), + feeling = i(4), + moments = i(5), + learned = i(6), + challenges = i(7), + ideas = i(8), + plans = i(9), + gratitude1 = i(10), + gratitude2 = i(11), + gratitude3 = i(12), + gratitude4 = i(13), + gratitude5 = i(14), + gratitude6 = i(15), + gratitude7 = i(16), + gratitude8 = i(17), + gratitude9 = i(18), + gratitude10 = i(19), + } + ) +) + +ls.add_snippets("markdown", { journal_snippet }) +ls.add_snippets("quarto", { journal_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/markdown.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/markdown.lua new file mode 100644 index 0000000..7d91fab --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/markdown.lua @@ -0,0 +1,187 @@ +local ls = require("luasnip") + +local s = ls.snippet +local t = ls.text_node +local i = ls.insert_node +local f = ls.function_node + +local function clipboard() + return vim.fn.getreg("+") +end + +-- ##################################################################### +-- Markdown +-- ##################################################################### + +-- Helper function to create code block snippets +local function create_code_block_snippet(lang) + return s(lang, { + t({ "```" .. lang, "" }), + i(1), + t({ "", "```" }), + }) +end + +-- Define languages for code blocks +local languages = { + "txt", + "lua", + "sql", + "go", + "regex", + "bash", + "markdown", + "markdown_inline", + "yaml", + "json", + "jsonc", + "cpp", + "csv", + "java", + "javascript", + "python", + "dockerfile", + "html", + "css", + "templ", + "php", +} + +-- Generate snippets for all languages +local snippets = {} + +for _, lang in ipairs(languages) do + table.insert(snippets, create_code_block_snippet(lang)) +end + +table.insert( + snippets, + s({ + trig = "chirpy", + name = "Disable markdownlint and prettier for chirpy", + }, { + t({ + " ", + "<!-- markdownlint-disable -->", + "<!-- prettier-ignore-start -->", + " ", + "<!-- tip=green, info=blue, warning=yellow, danger=red -->", + " ", + "> ", + }), + i(1), + t({ + "", + "{: .prompt-", + }), + -- In case you want to add a default value "tip" here, but I'm having + -- issues with autosave + -- i(2, "tip"), + i(2), + t({ + " }", + " ", + "<!-- prettier-ignore-end -->", + "<!-- markdownlint-restore -->", + }), + }) +) + +table.insert( + snippets, + s({ + trig = "markdownlint", + name = "Add markdownlint disable and restore headings", + }, { + t({ + " ", + "<!-- markdownlint-disable -->", + " ", + "> ", + }), + i(1), + t({ + " ", + " ", + "<!-- markdownlint-restore -->", + }), + }) +) + +table.insert( + snippets, + s({ + trig = "prettierignore", + name = "Add prettier ignore start and end headings", + }, { + t({ + " ", + "<!-- prettier-ignore-start -->", + " ", + "> ", + }), + i(1), + t({ + " ", + " ", + "<!-- prettier-ignore-end -->", + }), + }) +) + +table.insert( + snippets, + s({ + trig = "link", + name = "Add this -> []()", + }, { + t("["), + i(1), + t("]("), + i(2), + t(")"), + }) +) + +table.insert( + snippets, + s({ + trig = "linkt", + name = 'Add this -> [](){:target="_blank"}', + }, { + t("["), + i(1), + t("]("), + i(2), + t('){:target="_blank"}'), + }) +) + +table.insert( + snippets, + s({ + trig = "todo", + name = "Add TODO: item", + }, { + t("<!-- TODO: "), + i(1), + t(" -->"), + }) +) + +-- Paste clipboard contents in link section, move cursor to () +table.insert( + snippets, + s({ + trig = "linkclip", + name = "Paste clipboard as .md link", + }, { + t("["), + i(1), + t("]("), + f(clipboard, {}), + t(")"), + }) +) + +ls.add_snippets("markdown", snippets) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode1.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode1.lua new file mode 100644 index 0000000..85da742 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode1.lua @@ -0,0 +1,103 @@ +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep +local f = ls.function_node -- Import function_node for dynamic content + +-- Function to get the filename without the path +local function get_filename() + local filepath = vim.api.nvim_buf_get_name(0) + local filename = vim.fn.fnamemodify(filepath, ":t:r") -- Get filename without path and extension + return filename:gsub("_", " ") -- Replace underscores with spaces +end + +local neetcode_snippet = s( + "neetcode", + fmt( + [[ +""" +Question + +{1} +""" + + +from typing import Dict + +class Solution: + """ + A class to solve {file_name} from {2} + """ + def {3}(self, {4}) -> {5}: + """ + {file_name} from the input {parameters_type} using a {func_name} approach. + + Args: + {parameters_type}: {6} + + Returns: + {return_type}: {7} + """ + return {8} + + def print(self, examples: Dict[str, {parameters_type}]) -> None: + for name, example in examples.items(): + result = self.{3}(example) + print(f"{{name}}: {{result}}") + + def main(self): + cases = {{ + "case1" : {9}, + "case2" : {10}, + "case3" : {11}, + }} + + self.print(cases) + + +solution = Solution() +solution.main() + +""" +Solution + +url: {12} +video: {13} + +1. {func_name} +time: {14} +space: {15} +code: +```python +{16} +``` +""" +]], + { + i(1, '"Describe the question here"'), + file_name = f(get_filename), -- Insert the filename dynamicall + i(2, '"Describe the class here"'), + i(3, '"Function name"'), -- Primary insert node for method name + func_name = rep(3), -- Repeat the method name + i(4, '"parameters"'), + parameters_type = rep(4), + i(5, '"return_type"'), + return_type = rep(5), + i(6, '"parameters_desc"'), + i(7, '"return_type_desc"'), + i(8, '"return"'), + i(9, '"case1"'), + i(10, '"case2"'), + i(11, '"case3"'), + i(12, '"url"'), + i(13, '"video"'), + i(14, '"time_complexity"'), + i(15, '"space_complexity"'), + i(16, '"code"'), + } + ) +) + +-- Add the snippets for multiple filetypes +ls.add_snippets("python", { neetcode_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode2.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode2.lua new file mode 100644 index 0000000..98e7258 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/neetcode2.lua @@ -0,0 +1,104 @@ +local ls = require("luasnip") +local s = ls.snippet +local i = ls.insert_node +local fmt = require("luasnip.extras.fmt").fmt +local rep = require("luasnip.extras").rep +local f = ls.function_node -- Import function_node for dynamic content + +-- Function to get the filename without the path +local function get_filename() + local filepath = vim.api.nvim_buf_get_name(0) + local filename = vim.fn.fnamemodify(filepath, ":t:r") -- Get filename without path and extension + return filename:gsub("_", " ") -- Replace underscores with spaces +end + +local neetcode_snippet = s( + "neetcode", + fmt( + [[ +""" +Question + +{1} +""" + + +from typing import Dict + +class Solution: + """ + A class to solve {file_name} from {2} + """ + def {3}(self, {4}) -> {5}: + """ + {file_name} from the input {parameters_type} using a {func_name} approach. + + Args: + {parameters_type}: {6} + + Returns: + {return_type}: {7} + """ + return {8} + + def print(self, examples: Dict[str, {parameters_type}]) -> None: + for name, (param1, param2) in examples.items(): + result = self.{3}(param1, param2) + print(f"{{name}}: {{result}}") + + def main(self): + cases = {{ + "case1" : ({9}), + "case2" : ({10}), + "case3" : ({11}), + }} + + self.print(cases) + + + +solution = Solution() +solution.main() + +""" +Solution + +url: {12} +video: {13} + +1. {func_name} +time: {14} +space: {15} +code: +```python +{16} +``` +""" +]], + { + i(1, '"Describe the question here"'), + file_name = f(get_filename), -- Insert the filename dynamicall + i(2, '"Describe the class here"'), + i(3, '"Function name"'), -- Primary insert node for method name + func_name = rep(3), -- Repeat the method name + i(4, '"parameters"'), + parameters_type = rep(4), + i(5, '"return_type"'), + return_type = rep(5), + i(6, '"parameters_desc"'), + i(7, '"return_type_desc"'), + i(8, '"return"'), + i(9, '"case1"'), + i(10, '"case2"'), + i(11, '"case3"'), + i(12, '"url"'), + i(13, '"video"'), + i(14, '"time_complexity"'), + i(15, '"space_complexity"'), + i(16, '"code"'), + } + ) +) + +-- Add the snippets for multiple filetypes +ls.add_snippets("python", { neetcode_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/quarto.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/quarto.lua new file mode 100644 index 0000000..d990edc --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/quarto.lua @@ -0,0 +1,28 @@ +local ls = require("luasnip") + +local s = ls.snippet +local i = ls.insert_node +local t = ls.text_node +-- local d = ls.dynamic_node +local c = ls.choice_node +-- local f = ls.function_node +-- local r = ls.restore_node +local fmt = require("luasnip.extras.fmt").fmta +-- local h = require("TheSiahxyz.utils.snippet") + +local code_cell_snippet = s( + "`", + fmt( + [[```<lang> +<last> +``]], + { + lang = c(1, { t("python"), t("") }), + last = i(0), -- Place cursor here after expanding the snippet + } + ) +) + +-- Add the snippets for multiple filetypes +ls.add_snippets("markdown", { code_cell_snippet }) +ls.add_snippets("quarto", { code_cell_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/recordings.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/recordings.lua new file mode 100644 index 0000000..9ce9124 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/recordings.lua @@ -0,0 +1,30 @@ +local ls = require("luasnip") + +local s = ls.snippet +local i = ls.insert_node +local f = ls.function_node + +local fmt = require("luasnip.extras.fmt").fmta + +local recordings_snippet = s( + "recordings", + fmt( + [[--- +title: <title> +date: <date> +--- + +<story> +]], + { + title = i(1, "My Journal"), + date = f(function() + return os.date("%Y-%m-%d") + end, {}), + story = i(3), + } + ) +) + +ls.add_snippets("markdown", { recordings_snippet }) +ls.add_snippets("quarto", { recordings_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/whichkey.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/whichkey.lua new file mode 100644 index 0000000..fab5853 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/snippets/whichkey.lua @@ -0,0 +1,18 @@ +local ls = require("luasnip") + +-- Using parse_snippet instead of fmt to avoid curly brace issues +local whichkey_snippet = ls.parser.parse_snippet( + "whichkey", + [[ +init = function() + local wk = require("which-key") + wk.add({ + mode = { "n" }, + { "${1:Key}", group = "${2:Name}" }, + }) +end, +]] +) + +-- Add the snippets for the Lua filetype +ls.add_snippets("lua", { whichkey_snippet }) diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet.lua new file mode 100644 index 0000000..bc5b210 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet.lua @@ -0,0 +1,13 @@ +local options = { + cheatsheet = { + theme = "grid", -- Options: "simple" or "grid" + excluded_groups = { "terminal (t)", "autopairs", "Nvim", "Opens" }, -- Exclude specific groups + }, +} + +-- Define a keymap for opening the cheatsheet +vim.keymap.set("n", "<leader>skc", function() + require("TheSiahxyz.utils.cheatsheet.grid")() +end, { desc = "Open Cheatsheet" }) + +return options diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/grid.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/grid.lua new file mode 100644 index 0000000..0c2581f --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/grid.lua @@ -0,0 +1,105 @@ +local api = vim.api +local ch = require("TheSiahxyz.utils.cheatsheet.init") +local state = ch.state + +local ascii = { + " ", + " ", + "█▀▀ █░█ █▀▀ ▄▀█ ▀█▀ █▀ █░█ █▀▀ █▀▀ ▀█▀", + "█▄▄ █▀█ ██▄ █▀█ ░█░ ▄█ █▀█ ██▄ ██▄ ░█░", + " ", + " ", +} + +return function(buf, win, action) + action = action or "open" + + local ns = api.nvim_create_namespace("thesiah_cheatsheet") + + if action == "open" then + state.mappings_tb = ch.organize_mappings() + + buf = buf or api.nvim_create_buf(false, true) + win = win or api.nvim_get_current_win() + + api.nvim_set_current_win(win) + + -- Calculate maximum widths for lhs and rhs + local lhs_max_width, rhs_max_width = 0, 0 + for _, section in pairs(state.mappings_tb) do + for _, mapping in ipairs(section) do + lhs_max_width = math.max(lhs_max_width, vim.fn.strdisplaywidth(mapping[1])) + rhs_max_width = math.max(rhs_max_width, vim.fn.strdisplaywidth(mapping[2])) + end + end + + local total_width = lhs_max_width + rhs_max_width + 6 -- Add spacing for readability + local center_offset = math.floor((total_width - vim.fn.strdisplaywidth(ascii[1])) / 2) + + -- Align ASCII art to the center + local ascii_header = vim.tbl_values(ascii) + for i, line in ipairs(ascii_header) do + ascii_header[i] = string.rep(" ", center_offset) .. line + end + + -- Center-align the title + local title = "Cheatsheet" + local title_padding = math.floor((total_width - vim.fn.strdisplaywidth(title)) / 2) + local title_line = string.rep(" ", title_padding) .. title + + -- Prepare buffer lines + local lines = {} + for _, line in ipairs(ascii_header) do + table.insert(lines, line) + end + table.insert(lines, "") -- Blank line after ASCII art + table.insert(lines, title_line) + table.insert(lines, "") -- Blank line after title + + -- Add mappings grouped by section + for section_name, mappings in pairs(state.mappings_tb) do + -- Center-align the section name + local section_padding = math.floor((total_width - vim.fn.strdisplaywidth(section_name)) / 2) + table.insert(lines, string.rep(" ", section_padding) .. section_name) -- Section header + + -- Add mappings aligned to lhs and rhs + for _, mapping in ipairs(mappings) do + local lhs = mapping[1] + local rhs = mapping[2] + local lhs_padding = string.rep(" ", lhs_max_width - vim.fn.strdisplaywidth(lhs)) + local rhs_padding = string.rep(" ", rhs_max_width - vim.fn.strdisplaywidth(rhs)) + table.insert(lines, lhs .. lhs_padding .. " " .. rhs_padding .. rhs) + end + table.insert(lines, "") -- Blank line after each section + end + + -- Set lines into the buffer + api.nvim_buf_set_lines(buf, 0, -1, false, lines) + + -- Highlight ASCII art and title + for i = 1, #ascii_header do + vim.hl.range(buf, ns, "ThesiahAsciiHeader", { i - 1, 0 }, { i - 1, -1 }, {}) + end + vim.hl.range(buf, ns, "Title", { #ascii + 1, 0 }, { #ascii + 1, -1 }, {}) + + -- Highlight section headers + local current_line = #ascii + 3 -- Adjust for blank lines and title + for section_name, mappings in pairs(state.mappings_tb) do + vim.hl.range(buf, ns, "TheSiahSection", { current_line, 0 }, { current_line, -1 }, {}) + current_line = current_line + #mappings + 2 -- Count section header, mappings, and blank line + end + + -- Configure the buffer + vim.bo[buf].modifiable = false + vim.bo[buf].readonly = false + vim.bo[buf].buftype = "" + vim.bo[buf].buflisted = true + vim.bo[buf].filetype = "cheatsheet" + + -- Set up autocmds for the cheatsheet + ch.autocmds(buf, win) + + -- Focus on the cheatsheet buffer + api.nvim_set_current_buf(buf) + end +end diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/init.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/init.lua new file mode 100644 index 0000000..cf1dfe6 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/cheatsheet/init.lua @@ -0,0 +1,116 @@ +local M = {} +local api = vim.api +local config = require("TheSiahxyz.utils.cheatsheet") -- Load cheatsheet options + +local function capitalize(str) + return (str:gsub("^%l", string.upper)) +end + +M.get_mappings = function(mappings, tb_to_add) + local excluded_groups = config.cheatsheet.excluded_groups + + for _, v in ipairs(mappings) do + local desc = v.desc + + if not desc or (select(2, desc:gsub("%S+", "")) <= 1) or string.find(desc, "\n") then + goto continue + end + + local heading = desc:match("%S+") -- Get first word + heading = (v.mode ~= "n" and heading .. " (" .. v.mode .. ")") or heading + + if + vim.tbl_contains(excluded_groups, heading) + or vim.tbl_contains(excluded_groups, desc:match("%S+")) + or string.find(v.lhs, "<Plug>") + then + goto continue + end + + heading = capitalize(heading) + + if not tb_to_add[heading] then + tb_to_add[heading] = {} + end + + local keybind = string.sub(v.lhs, 1, 1) == " " and "<leader> +" .. v.lhs or v.lhs + + desc = v.desc:match("%s(.+)") -- Remove first word from description + desc = capitalize(desc) + + table.insert(tb_to_add[heading], { desc, keybind }) + + ::continue:: + end +end + +M.organize_mappings = function() + local tb_to_add = {} + local modes = { "n", "i", "v", "t" } + + for _, mode in ipairs(modes) do + local keymaps = api.nvim_get_keymap(mode) + M.get_mappings(keymaps, tb_to_add) + + local bufkeymaps = api.nvim_buf_get_keymap(0, mode) + M.get_mappings(bufkeymaps, tb_to_add) + end + + return tb_to_add +end + +M.rand_hlgroup = function() + local hlgroups = { + "blue", + "red", + "green", + "yellow", + "orange", + "baby_pink", + "purple", + "white", + "cyan", + "vibrant_green", + "teal", + } + + return "ThesiahHead" .. hlgroups[math.random(1, #hlgroups)] +end + +M.autocmds = function(buf, win) + -- Set buffer options to make it searchable and navigable + vim.bo[buf].buflisted = true + vim.bo[buf].buftype = "" -- Treat it as a regular buffer + vim.bo[buf].swapfile = false + vim.bo[buf].modifiable = false -- Prevent accidental edits + vim.bo[buf].readonly = false -- Enable navigation and search + vim.bo[buf].filetype = "cheatsheet" -- Optional, to customize behavior + + -- Create autocmd group for cheatsheet + local group_id = api.nvim_create_augroup("ThesiahCheatsheet", { clear = true }) + + -- Clean up when buffer is closed + api.nvim_create_autocmd("BufWinLeave", { + group = group_id, + buffer = buf, + callback = function() + vim.g.thesiah_cheatsheet_displayed = false + api.nvim_del_augroup_by_id(group_id) + end, + }) + + -- Keymaps for cheatsheet buffer + vim.keymap.set("n", "q", function() + api.nvim_buf_delete(buf, { force = true }) + end, { buffer = buf }) + + vim.keymap.set("n", "<ESC>", function() + api.nvim_buf_delete(buf, { force = true }) + end, { buffer = buf }) +end + +M.state = { + mappings_tb = {}, +} + +return M diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/icons.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/icons.lua new file mode 100644 index 0000000..22d5f2d --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/icons.lua @@ -0,0 +1,168 @@ +return { + diagnostics = { + Error = " ", + Hint = " ", + Information = " ", + Question = " ", + Warning = " ", + }, + documents = { + File = " ", + FileEmpty = " ", + Files = " ", + Folder = " ", + FolderEmpty = " ", + OpenFolder = " ", + OpenFolderEmpty = " ", + SymLink = " ", + SymlinkFolder = " ", + Import = " ", + }, + git = { + Add = " ", + AddAlt = " ", + Branch = " ", + Diff = " ", + DiffAlt = " ", + Ignore = "◌ ", + Mod = " ", + Octoface = " ", + Remove = " ", + RemoveAlt = " ", + Rename = " ", + Repo = " ", + Tag = " ", + Untrack = " ", + }, + kind = { + Class = " ", + Color = " ", + Constant = " ", + Constructor = " ", + Copilot = " ", + Enum = " ", + EnumMember = " ", + Event = " ", + Field = " ", + File = " ", + Folder = " ", + Function = " ", + Interface = " ", + Keyword = " ", + Language = " ", + Method = " ", + Module = "", + Operator = " ", + Property = " ", + Reference = " ", + Snippet = " ", + Struct = " ", + Text = " ", + TypeParameter = " ", + Unit = " ", + Value = " ", + Variable = " ", + }, + type = { + Array = " ", + Boolean = "⏻ ", + Number = " ", + Object = " ", + String = " ", + }, + ui = { + Arrow = " ", + ArrowClosed = " ", + ArrowLeft = " ", + ArrowOpen = " ", + ArrowRight = " ", + Bluetooth = " ", + Bookmark = " ", + Bug = " ", + Calendar = " ", + Camera = " ", + Check = " ", + ChevronRight = "", + Circle = " ", + CircleSmall = "● ", + CircleSmallEmpty = "○ ", + Clipboard = " ", + Close = " ", + Code = " ", + Collection = " ", + Color = " ", + Command = " ", + Comment = " ", + Copilot = " ", + CopilotError = " ", + Corner = "└ ", + Dashboard = " ", + Database = " ", + Download = " ", + Edit = " ", + Edge = "│ ", + Electric = " ", + Eye = " ", + Fire = " ", + Firefox = " ", + Flag = " ", + Game = " ", + Gear = " ", + GitHub = " ", + Heart = " ", + History = " ", + Home = " ", + Incoming = " ", + Jump = " ", + Keyboard = " ", + Ligthbulb = " ", + List = "", + Lock = " ", + Minus = "‒ ", + Music = " ", + Neovim = " ", + NewFile = " ", + None = " ", + Note = " ", + Outgoing = " ", + Package = " ", + Paint = " ", + Pause = " ", + Pencil = " ", + Person = " ", + Pin = " ", + Play = " ", + Plug = " ", + Plus = " ", + Power = " ", + PowerlineArrowLeft = "", + PowerlineArrowRight = "", + PowerlineLeftRound = "", + PowerlineRightRound = "", + Project = " ", + Question = " ", + Refresh = " ", + Reload = " ", + Rocket = " ", + Save = " ", + Search = " ", + Separator = "▊ ", + SeparatorLight = "▍", + SeparatorDashed = "┆", + SignIn = " ", + SignOut = " ", + Sleep = " ", + Star = " ", + Table = " ", + Telescope = " ", + Terminal = " ", + Test = " ", + Time = " ", + Topline = "‾", + Trash = " ", + User = " ", + Vim = " ", + Wifi = " ", + Windows = " ", + }, +} diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/markdown.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/markdown.lua new file mode 100644 index 0000000..1b1c591 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/markdown.lua @@ -0,0 +1,26 @@ +local M = {} + +-- foldtext for Neovim < 0.10.0 +function M.foldtext() + return vim.api.nvim_buf_get_lines(0, vim.v.lnum - 1, vim.v.lnum, false)[1] +end + +-- optimized treesitter foldexpr for Neovim >= 0.10.0 +function M.foldexpr() + local buf = vim.api.nvim_get_current_buf() + if vim.b[buf].ts_folds == nil then + -- as long as we don't have a filetype, don't bother + -- checking if treesitter is available (it won't) + if vim.bo[buf].filetype == "" then + return "0" + end + if vim.bo[buf].filetype:find("dashboard") then + vim.b[buf].ts_folds = false + else + vim.b[buf].ts_folds = pcall(vim.treesitter.get_parser, buf) + end + end + return vim.b[buf].ts_folds and vim.treesitter.foldexpr() or "0" +end + +return M diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/snippet.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/snippet.lua new file mode 100644 index 0000000..57bb211 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/snippet.lua @@ -0,0 +1,38 @@ +local ls = require("luasnip") +-- local s = ls.snippet +local i = ls.insert_node +local t = ls.text_node +-- local d = ls.dynamic_node +-- local f = ls.function_node +local c = ls.choice_node +-- local rep = require("luasnip.extras").rep +-- local k = require("luasnip.nodes.key_indexer").new_key +local r = ls.restore_node +local fmt = require("luasnip.extras.fmt").fmt + +local M = {} +M.i = 0 + +M.js_quotes = function(index) + M.i = M.i + 1 + return c(index, { fmt("'{}'", { r(1, M.i) }), fmt("`{}`", { r(1, M.i) }), fmt('"{}"', { r(1, M.i) }), t("") }) +end + +M.js_selector = function(index) + return c(index, { fmt("/{}/i", { i(1) }), fmt("'{}'", { i(1) }), fmt("`{}`", { i(1) }), t("") }) +end + +M.rtl_selector = function(index) + return c(index, { t("screen.get"), t("await screen.find"), t("screen.query") }) +end + +M.tracked_i_nodes = {} + +M.tin = function(index, key) + if not M.tracked_i_nodes[key] then + M.tracked_i_nodes[key] = i(index) + end + return M.tracked_i_nodes[key] +end + +return M diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tasks.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tasks.lua new file mode 100644 index 0000000..77f552c --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tasks.lua @@ -0,0 +1,227 @@ +-- ~/.config/nvim/lua/user_functions/tasks.lua +local M = {} + +-- Import the create_floating_scratch function from utils.lua +local utils = require("TheSiahxyz.utils.utils") + +function M.create_or_update_task() + local current_line = vim.fn.getline(".") + local cursor_pos = vim.fn.col(".") + local file_path = vim.fn.expand("%:p") -- Get full path of current file + local line_number = vim.fn.line(".") -- Get current line number + + -- Keywords we are looking for + local keywords = { "TODO", "HACK", "NOTE", "PERF", "TEST", "WARN" } + + for _, keyword in ipairs(keywords) do + local start_index, end_index = string.find(current_line, keyword) + if start_index then + local task_description = string.sub(current_line, end_index + 2, cursor_pos - 1) + task_description = string.gsub(task_description, "%(siah%)", "") + local task_tag = "+" .. string.lower(keyword) + + -- Ask for project and other tags + local project = vim.fn.input("Enter project name: ") + local additional_tags_input = vim.fn.input("Enter additional tags separated by spaces: ") + local additional_tags = {} + + -- Prefix each additional tag with a "+" + for tag in additional_tags_input:gmatch("%S+") do + table.insert(additional_tags, "+" .. tag) + end + + -- Prepare the task command + local task_cmd = string.format('task add %s "%s"', task_tag, task_description) + + -- Add additional tags if available + if #additional_tags > 0 then + task_cmd = task_cmd .. " " .. table.concat(additional_tags, " ") + end + + -- Add project if available + if project and #project > 0 then + task_cmd = task_cmd .. " project:" .. project + end + + -- Execute the task add command + local output = vim.fn.system(task_cmd) + print("Output: ", output) + + for line in output:gmatch("[^\r\n]+") do + local task_id = string.match(line, "Created task (%d+)%.") + if task_id then + print("Task ID extracted: ", task_id) + + -- Annotate task with filename and line number in the nvimline format + local annotation = string.format("nvimline:%s:%s", line_number, file_path) + local annotate_cmd = string.format('task %s annotate "%s"', task_id, annotation) + local annotate_output = vim.fn.system(annotate_cmd) + + print("Annotation output: ", annotate_output) + return + else + print("Failed to extract task ID") + end + end + end + end +end + +vim.api.nvim_set_keymap( + "i", + "<C-t>", + "<Cmd>lua require('TheSiahxyz.utils.tasks').create_or_update_task()<cr>", + { noremap = true, silent = true, desc = "Create/Update task" } +) + +function M.mark_task_done() + -- Get the current line and parse it + local line = vim.api.nvim_get_current_line() + print("Original line: ", line) + + -- Uncomment the line + vim.cmd("normal! gcc") + line = vim.api.nvim_get_current_line() + -- Remove (piotr1215) from the line + line = string.gsub(line, "%s*%(siah%)%s*", " ") + print("Uncommented line: ", line) + + local patterns = { "TODO:", "HACK:", "NOTE:", "PERF:", "TEST:", "WARN:" } + local taskDescription = nil + for _, pattern in ipairs(patterns) do + local start_idx = string.find(line, pattern) + if start_idx then + taskDescription = string.sub(line, start_idx + string.len(pattern) + 1) + break + end + end + print("Task description: ", taskDescription or "nil") + + -- If a task description was found, mark it as done + if taskDescription then + local output = vim.fn.system("yes | task description~'" .. taskDescription .. "' done") + print("Command output: ", output) + -- Check the command's output to make sure the task was marked done + if string.find(output, "Completed") then + -- Delete the current line + vim.cmd([[normal dd]]) + end + end +end + +vim.api.nvim_set_keymap( + "n", + "<localleader>td", + "<Cmd>lua require('TheSiahxyz.utils.tasks').mark_task_done()<CR>", + { noremap = true, silent = true, desc = "Mark task done" } +) + +function M.go_to_task_in_taskwarrior_tui() + -- Get the current line and save it as the original line + local original_line = vim.api.nvim_get_current_line() + + -- Uncomment the line + vim.cmd("normal! gcc") + local uncommented_line = vim.api.nvim_get_current_line() + + local patterns = { "TODO:", "HACK:", "NOTE:", "PERF:", "TEST:", "WARN:" } + local taskDescription = nil + + for _, pattern in ipairs(patterns) do + local start_idx = string.find(uncommented_line, pattern) + if start_idx then + taskDescription = string.sub(uncommented_line, start_idx + string.len(pattern) + 1) + taskDescription = string.sub(taskDescription, 1, 50) + break + end + end + + -- If a task description was found, use it to go to the task in taskwarrior-tui + if taskDescription then + -- print("Sleeping for 2 seconds before tmux switch...") + -- vim.cmd("sleep 2") -- sleep for 2 seconds + local output = vim.fn.system(" ~/.local/bin/opentasktui '" .. taskDescription .. "'") + end + + -- Replace the line back with the original + vim.api.nvim_set_current_line(original_line) +end + +vim.api.nvim_set_keymap( + "n", + "<localleader>tt", + "<Cmd>lua require('TheSiahxyz.utils.tasks').go_to_task_in_taskwarrior_tui()<CR>", + { noremap = true, silent = true, desc = "Open taskwarrior-tui" } +) + +function M.process_task_list(start_line, end_line, ...) + local args = { ... } + local modifiers = table.concat(args, " ") + local lines + + -- If no range is provided, use the entire buffer. + if not start_line or not end_line then + start_line, end_line = 1, vim.api.nvim_buf_line_count(0) + end + + lines = vim.api.nvim_buf_get_lines(0, start_line - 1, end_line, false) + + local new_lines = { "#!/bin/sh", "set -e" } + + for _, line in ipairs(lines) do + local trimmed_line = line:gsub("^[•*%-%+]+%s*", "") + local links = {} + + trimmed_line = trimmed_line:gsub("(https?://[%w%.%-%_/&%?=%~]+)", function(link) + table.insert(links, link) + return "" + end) + + if #trimmed_line > 0 then + -- No more "\n" before "# Adding task:"; instead, just ensure it's a new entry in the table. + table.insert(new_lines, "") -- Ensure there's an empty line before adding a new task if desired. + table.insert(new_lines, "# Adding task: " .. trimmed_line) + table.insert( + new_lines, + "output=$(task add " .. (modifiers ~= "" and modifiers .. " " or "") .. '"' .. trimmed_line .. '")' + ) + table.insert( + new_lines, + 'task_id=$(echo "$output" | grep -o "Created task [0-9]*." | cut -d " " -f 3 | tr -d ".")' + ) + + for _, link in ipairs(links) do + table.insert(new_lines, "task $task_id annotate -- " .. link) + end + end + end + + -- Call the create_floating_scratch function from utils.lua + utils.create_floating_scratch(new_lines) +end + +function M.my_custom_complete(arg_lead, cmd_line, cursor_pos) + -- This is your list of arguments. + local items = { "project:", "due:", "+next", "duration:" } + + -- Filter the items based on the argument lead. + local matches = {} + for _, item in ipairs(items) do + if item:find(arg_lead) == 1 then + table.insert(matches, item) + end + end + + return matches +end + +vim.api.nvim_create_user_command("ProcessTaskList", function(input) + M.process_task_list(1, vim.api.nvim_buf_line_count(0), unpack(input.fargs)) +end, { + nargs = "*", + complete = function(arg_lead, cmd_line, cursor_pos) + -- Call the custom completion function + return M.my_custom_complete(arg_lead, cmd_line, cursor_pos) + end, +}) +return M diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tmux.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tmux.lua new file mode 100644 index 0000000..41869f8 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/tmux.lua @@ -0,0 +1,63 @@ +local M = {} + +M.tmux_pane_function = function(dir) + -- NOTE: variable that controls the auto-cd behavior + local auto_cd_to_new_dir = true + -- NOTE: Variable to control pane direction: 'right' or 'bottom' + -- If you modify this, make sure to also modify TMUX_PANE_DIRECTION in the + -- zsh-vi-mode section on the .zshrc file + -- Also modify this in your tmux.conf file if you want it to work when in tmux + -- copy-mode + local pane_direction = vim.g.tmux_pane_direction or "right" + -- NOTE: Below, the first number is the size of the pane if split horizontally, + -- the 2nd number is the size of the pane if split vertically + local pane_size = (pane_direction == "right") and 60 or 15 + local move_key = (pane_direction == "right") and "C-l" or "" + local split_cmd = (pane_direction == "right") and "-h" or "-v" + -- if no dir is passed, use the current file's directory + local file_dir = dir or vim.fn.expand("%:p:h") + -- Simplified this, was checking if a pane existed + local has_panes = vim.fn.system("tmux list-panes | wc -l"):gsub("%s+", "") ~= "1" + -- Check if the current pane is zoomed (maximized) + local is_zoomed = vim.fn.system("tmux display-message -p '#{window_zoomed_flag}'"):gsub("%s+", "") == "1" + -- Escape the directory path for shell + local escaped_dir = file_dir:gsub("'", "'\\''") + -- If any additional pane exists + if has_panes then + if is_zoomed then + -- Compare the stored pane directory with the current file directory + if auto_cd_to_new_dir and vim.g.tmux_pane_dir ~= escaped_dir then + -- If different, cd into the new dir + vim.fn.system("tmux send-keys -t :.+ 'cd \"" .. escaped_dir .. "\"' Enter") + -- Update the stored directory to the new one + vim.g.tmux_pane_dir = escaped_dir + end + -- If zoomed, unzoom and switch to the correct pane + vim.fn.system("tmux resize-pane -Z") + vim.fn.system("tmux send-keys " .. move_key) + else + -- If not zoomed, zoom current pane + vim.fn.system("tmux resize-pane -Z") + end + else + -- Store the initial directory in a Neovim variable + if vim.g.tmux_pane_dir == nil then + vim.g.tmux_pane_dir = escaped_dir + end + -- If no pane exists, open it with zsh and DISABLE_PULL variable + vim.fn.system( + "tmux split-window " + .. split_cmd + .. " -l " + .. pane_size + .. " 'cd \"" + .. escaped_dir + .. "\" && DISABLE_PULL=1 zsh'" + ) + vim.fn.system("tmux send-keys " .. move_key) + end +end + +vim.keymap.set({ "n", "v", "i" }, "<M-\\>", M.tmux_pane_function, { desc = "Toggle terminal in tmux" }) + +return M diff --git a/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/utils.lua b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/utils.lua new file mode 100644 index 0000000..00a4457 --- /dev/null +++ b/debian/.config/TheSiahxyz/lua/TheSiahxyz/utils/utils.lua @@ -0,0 +1,147 @@ +-- ~/.config/nvim/lua/TheSiahxyz/utils/utils.lua +local M = {} + +function M.print_current_file_dir() + local dir = vim.fn.expand("%:p:h") + if dir ~= "" then + print(dir) + end +end + +function M.reload_module(name) + package.loaded[name] = nil + return require(name) +end + +-- Function to reload the current Lua file +function M.reload_current_file() + local current_file = vim.fn.expand("%:p") + + if current_file:match("%.lua$") then + vim.cmd("luafile " .. current_file) + print("Reloaded file: " .. current_file) + else + print("Current file is not a Lua file: " .. current_file) + end +end + +function M.insert_file_path() + local actions = require("telescope.actions") + local action_state = require("telescope.actions.state") + + require("telescope.builtin").find_files({ + cwd = vim.fn.getcwd(), -- Set the directory to search + attach_mappings = function(_, map) + map("i", "<CR>", function(prompt_bufnr) + local selected_file = action_state.get_selected_entry(prompt_bufnr).path + actions.close(prompt_bufnr) + + -- Replace the home directory with ~ + selected_file = selected_file:gsub(vim.fn.expand("$HOME"), "~") + + -- Ask the user if they want to insert the full path or just the file name + local choice = vim.fn.input("Insert full path or file name? (n[ame]/p[ath]): ") + local text_to_insert + if choice == "p" then + text_to_insert = selected_file + elseif choice == "n" then + text_to_insert = vim.fn.fnamemodify(selected_file, ":t") + end + + -- Move the cursor back one position + local col = vim.fn.col(".") - 1 + vim.fn.cursor(vim.fn.line("."), col) + + -- Insert the text at the cursor position + vim.api.nvim_put({ text_to_insert }, "c", true, true) + end) + return true + end, + }) +end + +vim.api.nvim_set_keymap( + "i", + "<C-v>", + "<Cmd>lua require('TheSiahxyz.utils.utils').insert_file_path()<cr>", + { noremap = true, silent = true, desc = "Insert file path/name" } +) +vim.api.nvim_set_keymap( + "n", + "<leader>vf", + "<Cmd>lua require('TheSiahxyz.utils.utils').insert_file_path()<cr>", + { noremap = true, silent = true, desc = "Insert file path/name" } +) +function M.create_floating_scratch(content) + -- Get editor dimensions + local width = vim.api.nvim_get_option_value("columns", {}) + local height = vim.api.nvim_get_option_value("lines", {}) + + -- Calculate the floating window size + local win_height = math.ceil(height * 0.8) + 2 -- Adding 2 for the border + local win_width = math.ceil(width * 0.8) + 2 -- Adding 2 for the border + + -- Calculate window's starting position + local row = math.ceil((height - win_height) / 2) + local col = math.ceil((width - win_width) / 2) + + -- Create a buffer and set it as a scratch buffer + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_set_option_value("buftype", "nofile", { buf = buf }) + vim.api.nvim_set_option_value("bufhidden", "wipe", { buf = buf }) + vim.api.nvim_set_option_value("filetype", "sh", { buf = buf }) -- for syntax highlighting + + -- Create the floating window with a border and set some options + local win = vim.api.nvim_open_win(buf, true, { + relative = "editor", + row = row, + col = col, + width = win_width, + height = win_height, + border = "single", -- You can also use 'double', 'rounded', or 'solid' + }) + + -- Check if we've got content to populate the buffer with + if content then + vim.api.nvim_buf_set_lines(buf, 0, -1, true, content) + else + vim.api.nvim_buf_set_lines(buf, 0, -1, true, { "This is a scratch buffer in a floating window." }) + end + + vim.api.nvim_set_option_value("wrap", false, { win = win }) + vim.api.nvim_set_option_value("cursorline", true, { win = win }) + + -- Map 'q' to close the buffer in this window + vim.api.nvim_buf_set_keymap(buf, "n", "q", ":q!<CR>", { noremap = true, silent = true }) +end + +function M.scrollRight(cols) + cols = cols or 10 + vim.wo.wrap = false + for _ = 1, cols do + vim.cmd("normal! zl") + end +end + +function M.scrollLeft(cols) + cols = cols or 10 + vim.wo.wrap = false + for _ = 1, cols do + vim.cmd("normal! zh") + end +end + +vim.api.nvim_set_keymap( + "n", + "H", + "<Cmd>lua require('TheSiahxyz.utils.utils').scrollLeft()<cr>", + { noremap = true, silent = true, desc = "Scroll left" } +) +vim.api.nvim_set_keymap( + "n", + "L", + "<Cmd>lua require('TheSiahxyz.utils.utils').scrollRight()<cr>", + { noremap = true, silent = true, desc = "Scroll right" } +) + +return M |
