diff options
17 files changed, 1672 insertions, 524 deletions
diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua index baab1f0..9fb46fc 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ai.lua @@ -1,206 +1,764 @@ return { { - "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, + "ravitemer/mcphub.nvim", + dependencies = { + "nvim-lua/plenary.nvim", + }, + build = "npm install -g mcp-hub@latest", -- Installs `mcp-hub` node binary globally 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" }, - }, + 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 }, - 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. + ---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 - -- 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, + -- Block access to private repos + if params.arguments.repo == "private" then + return "You can't access my private repo" -- Error message + 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, + -- 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 - -- 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, + -- 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 - -- 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, + 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 + }, }, - } - 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")) + --- 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", + }, + }) - 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")) + -- 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 - 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")) + -- Get diagnostics + local diagnostics = vim.diagnostic.get(buf_info.bufnr) - 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")) + -- Format header + local text = string.format("Diagnostics for: %s\n%s\n", buf_info.filename, string.rep("-", 40)) - -- 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)")) + -- 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 - 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")) + return res:text(text):send() + end, + }) - 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")) + 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)'") - 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")) + 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, + }) - 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")) + 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 - 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")) + -- Generate code overview + local overview = generate_overview(buf) - -- 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")) + 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, + }) - 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) ")) + mcphub.add_prompt("context", { + name = "explain_code", + handler = function(req, res) + -- Start with base behavior + res:system():text("You are a code explanation assistant.") - 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)")) + -- 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 - 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")) + -- Add example interactions + res:user():text("Explain this code"):llm():text("I'll explain the code in detail...") - 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")) + 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" }, + }, + }, + { + "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, + }, + }, + }, + ---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", diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua index 99f77bd..9c549d2 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/git.lua @@ -212,4 +212,17 @@ return { { 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/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua index 9c4f0d9..0ae3b88 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lualine.lua @@ -51,6 +51,26 @@ return { }, }, 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", @@ -129,6 +149,46 @@ return { lualine_x = { { 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 "" @@ -176,6 +236,19 @@ return { 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 = {}, diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua index 0b5fb5c..de16ca6 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/markdown.lua @@ -1,3 +1,16 @@ +local sysname = vim.loop.os_uname().sysname +local backend, build, processor + +if sysname == "Darwin" then + backend = "kitty" + processor = "magick_cli" + build = false +else + backend = "ueberzug" + processor = "magick_rock" + build = true +end + -- Select the current cell local function select_cell() local bufnr = vim.api.nvim_get_current_buf() @@ -176,6 +189,7 @@ return { return name:lower():match("%.ipynb$") ~= nil end, }) + vim.treesitter.language.register("markdown", "vimwiki") local opts = { noremap = true, silent = true } @@ -212,7 +226,7 @@ return { ft = { "markdown" }, build = function(plugin) if vim.fn.executable("npx") then - vim.cmd("!cd " .. plugin.dir .. " && cd app && npx --yes yarn install") + vim.cmd("!cd " .. plugin.dir .. " && cd app && npx install") else vim.cmd([[Lazy load markdown-preview.nvim]]) vim.fn["mkdp#util#install"]() @@ -337,11 +351,12 @@ return { { "benlubas/image-save.nvim", cmd = "SaveImage" }, { "3rd/image.nvim", + build = build, dependencies = { "leafo/magick", "vhyrro/luarocks.nvim" }, config = function() require("image").setup({ - backend = "ueberzug", -- or "kitty", whatever backend you would like to use - processor = "magick_rock", -- or "magick_cli" + backend = backend, -- "ueberzug" or "kitty", whatever backend you would like to use + processor = processor, -- "magick_rock" or "magick_cli" integrations = { markdown = { enabled = true, @@ -538,7 +553,7 @@ return { local venv_name = vim.fn.fnamemodify(venv_path, ":t") vim.cmd(("MoltenInit %s"):format(venv_name)) else - vim.cmd("MoltenInit python3") + vim.cmd("MoltenInit /opt/homebrew/bin/python@3.13") end end, { desc = "Init default molten" }) end, diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua index d9ea466..97878fb 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/mini.lua @@ -475,16 +475,16 @@ return { 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 - ]] +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 @@ -786,31 +786,46 @@ return { 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) + local function mapSymbols(status, is_symlink) local statusMap = { - -- stylua: ignore start - [" M"] = { symbol = "•", hlGroup = "GitSignsChange"}, -- Modified in the working directory - ["M "] = { symbol = "✹", hlGroup = "GitSignsChange"}, -- modified in index - ["MM"] = { symbol = "≠", hlGroup = "GitSignsChange"}, -- modified in both working tree and index - ["A "] = { symbol = "+", hlGroup = "GitSignsAdd" }, -- Added to the staging area, new file - ["AA"] = { symbol = "≈", hlGroup = "GitSignsAdd" }, -- file is added in both working tree and index - ["D "] = { symbol = "-", hlGroup = "GitSignsDelete"}, -- Deleted from the staging area - ["AM"] = { symbol = "⊕", hlGroup = "GitSignsChange"}, -- added in working tree, modified in index - ["AD"] = { symbol = "-•", hlGroup = "GitSignsChange"}, -- Added in the index and deleted in the working directory - ["R "] = { symbol = "→", hlGroup = "GitSignsChange"}, -- Renamed in the index - ["U "] = { symbol = "‖", hlGroup = "GitSignsChange"}, -- Unmerged path - ["UU"] = { symbol = "⇄", hlGroup = "GitSignsAdd" }, -- file is unmerged - ["UA"] = { symbol = "⊕", hlGroup = "GitSignsAdd" }, -- file is unmerged and added in working tree - ["??"] = { symbol = "?", hlGroup = "GitSignsDelete"}, -- Untracked files - ["!!"] = { symbol = "!", hlGroup = "GitSignsChange"}, -- Ignored files +-- 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" } - return result.symbol, result.hlGroup + 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 @@ -826,9 +841,13 @@ return { vim.system({ "git", "status", "--ignored", "--porcelain" }, { text = true, cwd = cwd }, on_exit) end - ---@param str string? + ---@param str string|nil + ---@return string local function escapePattern(str) - return str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1") + if not str then + return "" + end + return (str:gsub("([%^%$%(%)%%%.%[%]%*%+%-%?])", "%%%1")) end ---@param buf_id integer @@ -852,7 +871,8 @@ return { local status = gitStatusMap[relativePath] if status then - local symbol, hlGroup = mapSymbols(status) + 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 @@ -907,11 +927,11 @@ return { ---@param buf_id integer ---@return nil local function updateGitStatus(buf_id) - if not vim.fs.root(vim.uv.cwd(), ".git") then + local cwd = vim.uv.cwd() + if not cwd or not vim.fs.root(cwd, ".git") then return end - local cwd = vim.fn.expand("%:p:h") local currentTime = os.time() if gitStatusCache[cwd] and currentTime - gitStatusCache[cwd].time < cacheTimeout then updateMiniWithGit(buf_id, gitStatusCache[cwd].statusMap) @@ -939,12 +959,9 @@ return { autocmd("User", { group = augroup("start"), pattern = "MiniFilesExplorerOpen", + -- pattern = { "minifiles" }, callback = function() local bufnr = vim.api.nvim_get_current_buf() - local path = vim.api.nvim_buf_get_name(bufnr) - if path:match("^minifiles://") then - return - end updateGitStatus(bufnr) end, }) @@ -1063,7 +1080,7 @@ return { keys = { { "<leader>mo", "<Cmd>lua MiniMap.open()<cr>", desc = "Open map" }, { "<leader>mm", "<Cmd>lua MiniMap.refresh()<cr>", desc = "Refresh map" }, - { "<leader>mc", "<Cmd>lua MiniMap.close()<cr>", desc = "Close map" }, + { "<leader>mq", "<Cmd>lua MiniMap.close()<cr>", desc = "Close map" }, { "<leader>mtm", "<Cmd>lua MiniMap.toggle()<cr>", desc = "Toggle map" }, { "<leader>mts", "<Cmd>lua MiniMap.toggle_side()<cr>", desc = "Toggle side map" }, }, @@ -1079,14 +1096,14 @@ return { -- Move visual selection in Visual mode. Defaults are Alt (Meta) + hjkl. left = "<M-m>", right = "<M-/>", - down = "<M-,>", - up = "<M-.>", + -- down = "<M-,>", + -- up = "<M-.>", -- Move current line in Normal mode line_left = "<M-m>", line_right = "<M-/>", - line_down = "<M-,>", - line_up = "<M-.>", + -- line_down = "<M-,>", + -- line_up = "<M-.>", }, -- Options which control moving behavior @@ -1147,13 +1164,13 @@ return { require("mini.trailspace").setup() vim.keymap.set( "n", - "<leader>zt", + "<leader>zW", ":lua MiniTrailspace.trim()<cr>", { noremap = true, silent = true, desc = "Trim trailing whitespace" } ) vim.keymap.set( "n", - "<leader>zl", + "<leader>zL", ":lua MiniTrailspace.trim_last_lines()<cr>", { noremap = true, silent = true, desc = "Trim trailing empty lines" } ) diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua index 6666f2d..c05716d 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua @@ -1,141 +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 = { - -- hijack_netrw_behavior = "disabled", -- netrw disabled, opening a directory opens neo-tree - -- filesystem = { - -- 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, - -- }, - -- }, - -- }, - -- 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)", - -- }, - -- }, - -- }, + { + "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/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua index bacdd9b..75b1ce7 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/python.lua @@ -28,7 +28,6 @@ return { { "nvim-telescope/telescope.nvim", branch = "0.1.x", dependencies = { "nvim-lua/plenary.nvim" } }, }, lazy = false, - branch = "regexp", -- This is the regexp branch, use this for the new version ft = "python", init = function() local wk = require("which-key") diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua index 20cead1..b42a588 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/ssh.lua @@ -1,10 +1,118 @@ return { "amitds1997/remote-nvim.nvim", - version = "*", -- Pin to GitHub releases + version = "*", dependencies = { - "nvim-lua/plenary.nvim", -- For standard functions - "MunifTanjim/nui.nvim", -- To build the plugin UI - "nvim-telescope/telescope.nvim", -- For picking b/w different remote methods + "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 }, + }, } diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua index 98fd30a..ddb31de 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/telescope.lua @@ -264,6 +264,7 @@ return { wk.add({ mode = { "n", "v" }, { "<leader>f", group = "Find" }, + { "<leader>F", group = "Find (root)" }, { "<leader>fl", group = "Live grep" }, }) end, @@ -761,7 +762,7 @@ return { :find() end, { desc = "Find files with open markers" }) - vim.keymap.set("n", "<leader>fF", function() + vim.keymap.set("n", "<leader>FF", function() require("telescope.builtin").find_files({ cwd = vim.fn.expand("~"), find_command = { diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua index b1c72f4..69e7762 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/urlview.lua @@ -1,6 +1,7 @@ return { "axieax/urlview.nvim", dependencies = "nvim-telescope/telescope.nvim", + event = "VeryLazy", init = function() local wk = require("which-key") wk.add({ @@ -89,12 +90,12 @@ return { -- 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 = "netrw", + 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 = false, + 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 @@ -109,9 +110,9 @@ return { }) -- Add a keymap for the Tmux plugins search context - vim.keymap.set("n", "<leader>ub", "<Cmd>UrlView thesiah_urls<cr>", { desc = "Bookmarks URLs" }) + 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>ur", "<Cmd>UrlView<cr>", { desc = "Buffer 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", diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua index e856256..07a115c 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/wiki.lua @@ -1,6 +1,7 @@ return { { "vimwiki/vimwiki", + cmd = { "VimwikiIndex" }, init = function() local wk = require("which-key") wk.add({ diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua index 972ae71..b41ee24 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua @@ -4,6 +4,64 @@ return { 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 = { { @@ -26,10 +84,175 @@ return { }, ---@type YaziConfig | {} opts = { - -- if you want to open yazi instead of netrw, see below for more info + -- 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 @@ -37,7 +260,7 @@ return { -- 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 + -- vim.g.loaded_netrwPlugin = 1 local wk = require("which-key") wk.add({ mode = { "n" }, diff --git a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua index beb48f5..52b6656 100644 --- a/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua +++ b/ar/.config/TheSiahxyz/lua/TheSiahxyz/plugins/zenmode.lua @@ -2,19 +2,55 @@ 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, }) @@ -41,6 +77,6 @@ return { ColorMyPencils() end, }) - end, { desc = "Toggle zenmode (custom)" }) + end, { desc = "Toggle zenmode (goyo)" }) end, } diff --git a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lf.lua b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lf.lua deleted file mode 100644 index 3f82222..0000000 --- a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lf.lua +++ /dev/null @@ -1,121 +0,0 @@ -return { - "lmburns/lf.nvim", - dependencies = { - { - "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, - }, - }, - config = function() - vim.g.lf_netrw = 1 - local fn = vim.fn - - -- Defaults - require("lf").setup({ - default_action = "drop", -- Default action when `Lf` opens a file - default_actions = { - ["e"] = "tabedit", - ["<C-t>"] = "tab drop", - ["<C-v>"] = "vsplit", - ["<C-x>"] = "split", - }, - winblend = 0, -- Pseudotransparency level - direction = "float", -- Window type - border = "rounded", -- Border kind - height = fn.float2nr(fn.round(0.75 * vim.o.lines)), -- Height of the *floating* window - width = fn.float2nr(fn.round(0.75 * vim.o.columns)), -- Width of the *floating* window - escape_quit = true, -- Map escape to the quit command - focus_on_open = true, -- Focus the current file when opening Lf - mappings = true, -- Enable terminal buffer mapping - tmux = true, -- Tmux statusline can be disabled - disable_netrw_warning = true, -- Don't display a message when opening a directory - highlights = { - Normal = { link = "Normal" }, -- Use normal highlighting - NormalFloat = { link = "NormalFloat" }, -- Use float highlighting - FloatBorder = { link = "@constant" }, -- Use constant highlighting - }, - - -- Layout configurations - layout_mapping = "<M-r>", -- Resize window with this key - views = { - { width = 0.800, height = 0.800 }, - { width = 0.600, height = 0.600 }, - { width = 0.950, height = 0.950 }, - { width = 0.500, height = 0.500, col = 0, row = 0 }, - { width = 0.500, height = 0.500, col = 0, row = 0.5 }, - { width = 0.500, height = 0.500, col = 0.5, row = 0 }, - { width = 0.500, height = 0.500, col = 0.5, row = 0.5 }, - }, - }) - - vim.keymap.set("n", "<leader>el", "<Cmd>Lf<CR>") - - -- Autocommand to set key mapping in terminal buffer - vim.api.nvim_create_autocmd("User", { - pattern = "LfTermEnter", - callback = function(a) - vim.api.nvim_buf_set_keymap( - a.buf, - "t", - "q", - "<Cmd>q<CR>", - { nowait = true, noremap = true, silent = true } - ) - end, - }) - end, -} diff --git a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua index 4520597..b7b5812 100644 --- a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua +++ b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/lsp.lua @@ -101,7 +101,6 @@ return { -- "mutt_ls", "pyright", "ruff", - "sqls", "ts_ls", }, automatic_enable = true, @@ -213,11 +212,6 @@ return { -- }, }) end, - ["sqls"] = function() - lspconfig.sqls.setup({ - capabilities = capabilities, - }) - end, ["ts_ls"] = function() lspconfig.ruff.setup({ capabilities = capabilities, @@ -236,10 +230,6 @@ return { svelte = { "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 }) @@ -267,8 +257,6 @@ return { "ruff", -- python formatter "shellcheck", -- bash lint "shfmt", -- sh formatter - "sqlfluff", -- sql linter - "sql-formatter", -- sql formatter "stylua", -- lua formatter }, integrations = { @@ -347,7 +335,6 @@ return { markdown = { "prettier" }, python = { "ruff", "isort", "black" }, sh = { "shfmt" }, - sql = { "sql-formatter" }, svelte = { "prettier" }, -- typescript = { "prettier" }, -- typescriptreact = { "prettier" }, @@ -361,19 +348,7 @@ return { 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 } + return { lsp_format = "fallback", timeout_ms = 1000, async = false } end, }) diff --git a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua index c190df5..c05716d 100644 --- a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua +++ b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/neo-tree.lua @@ -31,8 +31,8 @@ return { ---@module "neo-tree" ---@type neotree.Config? opts = { - hijack_netrw_behavior = "disabled", -- netrw disabled, opening a directory opens neo-tree filesystem = { + hijack_netrw_behavior = "disabled", -- open_default, open_current follow_current_file = { enabled = false }, commands = { -- over write default 'delete' command to 'trash'. diff --git a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua index 972ae71..b41ee24 100644 --- a/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua +++ b/mac/.config/TheSiahxyz/lua/TheSiahxyz/plugins/yazi.lua @@ -4,6 +4,64 @@ return { 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 = { { @@ -26,10 +84,175 @@ return { }, ---@type YaziConfig | {} opts = { - -- if you want to open yazi instead of netrw, see below for more info + -- 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 @@ -37,7 +260,7 @@ return { -- 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 + -- vim.g.loaded_netrwPlugin = 1 local wk = require("which-key") wk.add({ mode = { "n" }, |
