docs(v3.5.0): update README for integrated mg_dotfiles and security improvements

- Integrated mg_dotfiles as regular directory (not submodule)
- Added .zshrc.local.example template for local configs without secrets
- Added mg_dotfiles/zsh/.zshrc.local to .gitignore to protect API keys
- Updated README to reflect mg_dotfiles integration and new structure
- Added nvim configuration directory with LazyVim setup
This commit is contained in:
Marco Gallegos
2026-01-11 12:28:56 -06:00
parent 43df5316ed
commit 5ab59146a8
236 changed files with 1919986 additions and 21 deletions

View File

@@ -0,0 +1,3 @@
-- Autocmds are automatically loaded on the VeryLazy event
-- Default autocmds that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/autocmds.lua
-- Add any additional autocmds here

View File

@@ -0,0 +1,154 @@
-- https://github.com/EmmanuelOga/columns/blob/master/utils/color.lua
local M = {}
local hexChars = "0123456789abcdef"
function M.hex_to_rgb(hex)
hex = string.lower(hex)
local ret = {}
for i = 0, 2 do
local char1 = string.sub(hex, i * 2 + 2, i * 2 + 2)
local char2 = string.sub(hex, i * 2 + 3, i * 2 + 3)
local digit1 = string.find(hexChars, char1) - 1
local digit2 = string.find(hexChars, char2) - 1
ret[i + 1] = (digit1 * 16 + digit2) / 255.0
end
return ret
end
--[[
* Converts an RGB color value to HSL. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes r, g, and b are contained in the set [0, 255] and
* returns h, s, and l in the set [0, 1].
*
* @param Number r The red color value
* @param Number g The green color value
* @param Number b The blue color value
* @return Array The HSL representation
]]
function M.rgbToHsl(r, g, b)
local max, min = math.max(r, g, b), math.min(r, g, b)
local h = 0
local s = 0
local l = 0
l = (max + min) / 2
if max == min then
h, s = 0, 0 -- achromatic
else
local d = max - min
if l > 0.5 then
s = d / (2 - max - min)
else
s = d / (max + min)
end
if max == r then
h = (g - b) / d
if g < b then
h = h + 6
end
elseif max == g then
h = (b - r) / d + 2
elseif max == b then
h = (r - g) / d + 4
end
h = h / 6
end
return h * 360, s * 100, l * 100
end
--[[
* Converts an HSL color value to RGB. Conversion formula
* adapted from http://en.wikipedia.org/wiki/HSL_color_space.
* Assumes h, s, and l are contained in the set [0, 1] and
* returns r, g, and b in the set [0, 255].
*
* @param Number h The hue
* @param Number s The saturation
* @param Number l The lightness
* @return Array The RGB representation
]]
function M.hslToRgb(h, s, l)
local r, g, b
if s == 0 then
r, g, b = l, l, l -- achromatic
else
function hue2rgb(p, q, t)
if t < 0 then
t = t + 1
end
if t > 1 then
t = t - 1
end
if t < 1 / 6 then
return p + (q - p) * 6 * t
end
if t < 1 / 2 then
return q
end
if t < 2 / 3 then
return p + (q - p) * (2 / 3 - t) * 6
end
return p
end
local q
if l < 0.5 then
q = l * (1 + s)
else
q = l + s - l * s
end
local p = 2 * l - q
r = hue2rgb(p, q, h + 1 / 3)
g = hue2rgb(p, q, h)
b = hue2rgb(p, q, h - 1 / 3)
end
return r * 255, g * 255, b * 255
end
function M.hexToHSL(hex)
local hsluv = require("solarized-osaka.hsluv")
local rgb = M.hex_to_rgb(hex)
local h, s, l = M.rgbToHsl(rgb[1], rgb[2], rgb[3])
return string.format("hsl(%d, %d, %d)", math.floor(h + 0.5), math.floor(s + 0.5), math.floor(l + 0.5))
end
--[[
* Converts an HSL color value to RGB in Hex representation.
* @param Number h The hue
* @param Number s The saturation
* @param Number l The lightness
* @return String The hex representation
]]
function M.hslToHex(h, s, l)
local r, g, b = M.hslToRgb(h / 360, s / 100, l / 100)
return string.format("#%02x%02x%02x", r, g, b)
end
function M.replaceHexWithHSL()
-- Get the current line number
local line_number = vim.api.nvim_win_get_cursor(0)[1]
-- Get the line content
local line_content = vim.api.nvim_buf_get_lines(0, line_number - 1, line_number, false)[1]
-- Find hex code patterns and replace them
for hex in line_content:gmatch("#[0-9a-fA-F]+") do
local hsl = M.hexToHSL(hex)
line_content = line_content:gsub(hex, hsl)
end
-- Set the line content back
vim.api.nvim_buf_set_lines(0, line_number - 1, line_number, false, { line_content })
end
return M

View File

@@ -0,0 +1,163 @@
-- This file contains custom key mappings for Neovim.
-- Keymaps are automatically loaded on the VeryLazy event
-- Default keymaps that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/keymaps.lua
-- Add any additional keymaps here
-- Map Ctrl+b in insert mode to delete to the end of the word without leaving insert mode
vim.keymap.set("i", "<C-b>", "<C-o>de")
-- Map Ctrl+c to escape from other modes
vim.keymap.set({ "i", "n", "v" }, "<C-c>", [[<C-\><C-n>]])
-- Screen Keys
vim.keymap.set({ "n" }, "<leader>uk", "<cmd>Screenkey<CR>")
----- Tmux Navigation ------
local nvim_tmux_nav = require("nvim-tmux-navigation")
vim.keymap.set("n", "<C-h>", nvim_tmux_nav.NvimTmuxNavigateLeft) -- Navigate to the left pane
vim.keymap.set("n", "<C-j>", nvim_tmux_nav.NvimTmuxNavigateDown) -- Navigate to the bottom pane
vim.keymap.set("n", "<C-k>", nvim_tmux_nav.NvimTmuxNavigateUp) -- Navigate to the top pane
vim.keymap.set("n", "<C-l>", nvim_tmux_nav.NvimTmuxNavigateRight) -- Navigate to the right pane
vim.keymap.set("n", "<C-\\>", nvim_tmux_nav.NvimTmuxNavigateLastActive) -- Navigate to the last active pane
vim.keymap.set("n", "<C-Space>", nvim_tmux_nav.NvimTmuxNavigateNext) -- Navigate to the next pane
----- OBSIDIAN -----
vim.keymap.set("n", "<leader>oc", "<cmd>ObsidianCheck<CR>", { desc = "Obsidian Check Checkbox" })
vim.keymap.set("n", "<leader>ot", "<cmd>ObsidianTemplate<CR>", { desc = "Insert Obsidian Template" })
vim.keymap.set("n", "<leader>oo", "<cmd>Obsidian Open<CR>", { desc = "Open in Obsidian App" })
vim.keymap.set("n", "<leader>ob", "<cmd>ObsidianBacklinks<CR>", { desc = "Show ObsidianBacklinks" })
vim.keymap.set("n", "<leader>ol", "<cmd>ObsidianLinks<CR>", { desc = "Show ObsidianLinks" })
vim.keymap.set("n", "<leader>on", "<cmd>ObsidianNew<CR>", { desc = "Create New Note" })
vim.keymap.set("n", "<leader>os", "<cmd>ObsidianSearch<CR>", { desc = "Search Obsidian" })
vim.keymap.set("n", "<leader>oq", "<cmd>ObsidianQuickSwitch<CR>", { desc = "Quick Switch" })
----- OIL -----
vim.keymap.set("n", "-", "<CMD>Oil<CR>", { desc = "Open parent directory" })
-- Delete all buffers but the current one
vim.keymap.set(
"n",
"<leader>bq",
'<Esc>:%bdelete|edit #|normal`"<Return>',
{ desc = "Delete other buffers but the current one" }
)
-- Disable key mappings in insert mode
vim.api.nvim_set_keymap("i", "<A-j>", "<Nop>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("i", "<A-k>", "<Nop>", { noremap = true, silent = true })
-- Disable key mappings in normal mode
vim.api.nvim_set_keymap("n", "<A-j>", "<Nop>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("n", "<A-k>", "<Nop>", { noremap = true, silent = true })
-- Disable key mappings in visual block mode
vim.api.nvim_set_keymap("x", "<A-j>", "<Nop>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("x", "<A-k>", "<Nop>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("x", "J", "<Nop>", { noremap = true, silent = true })
vim.api.nvim_set_keymap("x", "K", "<Nop>", { noremap = true, silent = true })
-- Redefine Ctrl+s to save with the custom function
vim.api.nvim_set_keymap("n", "<C-s>", ":lua SaveFile()<CR>", { noremap = true, silent = true })
-- Grep keybinding for visual mode - search selected text
vim.keymap.set("v", "<leader>sg", function()
-- Get the selected text
local start_pos = vim.fn.getpos("'<")
local end_pos = vim.fn.getpos("'>")
local lines = vim.fn.getline(start_pos[2], end_pos[2])
if #lines == 0 then
return
end
-- Handle single line selection
if #lines == 1 then
lines[1] = string.sub(lines[1], start_pos[3], end_pos[3])
else
-- Handle multi-line selection
lines[1] = string.sub(lines[1], start_pos[3])
lines[#lines] = string.sub(lines[#lines], 1, end_pos[3])
end
local selected_text = table.concat(lines, "\n")
-- Escape special characters for grep
selected_text = vim.fn.escape(selected_text, "\\.*[]^$()+?{}")
-- Use the selected text for grep
if pcall(require, "snacks") then
require("snacks").picker.grep({ search = selected_text })
elseif pcall(require, "fzf-lua") then
require("fzf-lua").live_grep({ search = selected_text })
else
vim.notify("No grep picker available", vim.log.levels.ERROR)
end
end, { desc = "Grep Selected Text" })
-- Grep keybinding for visual mode with G - search selected text at root level
vim.keymap.set("v", "<leader>sG", function()
-- Get git root or fallback to cwd
local git_root = vim.fn.system("git rev-parse --show-toplevel 2>/dev/null"):gsub("\n", "")
local root = vim.v.shell_error == 0 and git_root ~= "" and git_root or vim.fn.getcwd()
-- Get the selected text
local start_pos = vim.fn.getpos("'<")
local end_pos = vim.fn.getpos("'>")
local lines = vim.fn.getline(start_pos[2], end_pos[2])
if #lines == 0 then
return
end
-- Handle single line selection
if #lines == 1 then
lines[1] = string.sub(lines[1], start_pos[3], end_pos[3])
else
-- Handle multi-line selection
lines[1] = string.sub(lines[1], start_pos[3])
lines[#lines] = string.sub(lines[#lines], 1, end_pos[3])
end
local selected_text = table.concat(lines, "\n")
-- Escape special characters for grep
selected_text = vim.fn.escape(selected_text, "\\.*[]^$()+?{}")
-- Use the selected text for grep at root level
if pcall(require, "snacks") then
require("snacks").picker.grep({ search = selected_text, cwd = root })
elseif pcall(require, "fzf-lua") then
require("fzf-lua").live_grep({ search = selected_text, cwd = root })
else
vim.notify("No grep picker available", vim.log.levels.ERROR)
end
end, { desc = "Grep Selected Text (Root Dir)" })
-- Delete all marks
vim.keymap.set("n", "<leader>md", function()
vim.cmd("delmarks!")
vim.cmd("delmarks A-Z0-9")
vim.notify("All marks deleted")
end, { desc = "Delete all marks" })
-- Custom save function
function SaveFile()
-- Check if a buffer with a file is open
if vim.fn.empty(vim.fn.expand("%:t")) == 1 then
vim.notify("No file to save", vim.log.levels.WARN)
return
end
local filename = vim.fn.expand("%:t") -- Get only the filename
local success, err = pcall(function()
vim.cmd("silent! write") -- Try to save the file without showing the default message
end)
if success then
vim.notify(filename .. " Saved!") -- Show only the custom message if successful
else
vim.notify("Error: " .. err, vim.log.levels.ERROR) -- Show the error message if it fails
end
end

View File

@@ -0,0 +1,107 @@
-- This file contains the configuration for setting up the lazy.nvim plugin manager in Neovim.
-- Node.js configuration - always use latest stable version
vim.g.node_host_prog = vim.fn.exepath("node") or "/usr/local/bin/node"
-- Spell-checking
vim.opt.spell = true -- activa spell checker
vim.opt.spelllang = { "en" }
-- Define the path to the lazy.nvim plugin
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
-- Check if the lazy.nvim plugin is not already installed
if not vim.loop.fs_stat(lazypath) then
-- Bootstrap lazy.nvim by cloning the repository
-- stylua: ignore
vim.fn.system({ "git", "clone", "--filter=blob:none", "https://github.com/folke/lazy.nvim.git", "--branch=stable",
lazypath })
end
-- Prepend the lazy.nvim path to the runtime path
vim.opt.rtp:prepend(vim.env.LAZY or lazypath)
-- Fix copy and paste in WSL (Windows Subsystem for Linux)
vim.opt.clipboard = "unnamedplus" -- Use the system clipboard for all operations
if vim.fn.has("wsl") == 1 then
vim.g.clipboard = {
name = "win32yank", -- Use win32yank for clipboard operations
copy = {
["+"] = "win32yank.exe -i --crlf", -- Command to copy to the system clipboard
["*"] = "win32yank.exe -i --crlf", -- Command to copy to the primary clipboard
},
paste = {
["+"] = "win32yank.exe -o --lf", -- Command to paste from the system clipboard
["*"] = "win32yank.exe -o --lf", -- Command to paste from the primary clipboard
},
cache_enabled = false, -- Disable clipboard caching
}
end
-- Setup lazy.nvim with the specified configuration
require("lazy").setup({
spec = {
-- Add LazyVim and import its plugins
{ "LazyVim/LazyVim", import = "lazyvim.plugins" },
-- Import any extra modules here
-- Editor plugins
{ import = "lazyvim.plugins.extras.editor.harpoon2" },
{ import = "lazyvim.plugins.extras.editor.mini-files" },
-- { import = "lazyvim.plugins.extras.editor.snacks_explorer" },
{ import = "lazyvim.plugins.extras.editor.snacks_picker" },
-- Debgugging plugins
{ import = "lazyvim.plugins.extras.dap.core" },
-- Formatting plugins
{ import = "lazyvim.plugins.extras.formatting.biome" },
{ import = "lazyvim.plugins.extras.formatting.prettier" },
-- Linting plugins
{ import = "lazyvim.plugins.extras.linting.eslint" },
-- Language support plugins
{ import = "lazyvim.plugins.extras.lang.json" },
{ import = "lazyvim.plugins.extras.lang.markdown" },
-- Coding plugins
{ import = "lazyvim.plugins.extras.coding.mini-surround" },
{ import = "lazyvim.plugins.extras.editor.mini-diff" },
{ import = "lazyvim.plugins.extras.coding.blink" },
-- Utility plugins
{ import = "lazyvim.plugins.extras.util.mini-hipatterns" },
-- AI plugins
{ import = "lazyvim.plugins.extras.ai.copilot" },
-- Import/override with your plugins
{ import = "plugins" },
},
defaults = {
-- By default, only LazyVim plugins will be lazy-loaded. Your custom plugins will load during startup.
-- If you know what you're doing, you can set this to `true` to have all your custom plugins lazy-loaded by default.
lazy = false,
-- It's recommended to leave version=false for now, since a lot of the plugins that support versioning
-- have outdated releases, which may break your Neovim install.
version = false, -- Always use the latest git commit
-- version = "*", -- Try installing the latest stable version for plugins that support semver
},
install = { colorscheme = { "tokyonight", "habamax" } }, -- Specify colorschemes to install
checker = { enabled = true }, -- Automatically check for plugin updates
performance = {
rtp = {
-- Disable some runtime path plugins to improve performance
disabled_plugins = {
"gzip",
-- "matchit",
-- "matchparen",
-- "netrwPlugin",
"tarPlugin",
"tohtml",
"tutor",
"zipPlugin",
},
},
},
})

View File

@@ -0,0 +1,241 @@
-- Node.js configuration for Neovim
-- This ensures Neovim uses the SYSTEM Node.js, not project-specific versions
-- This prevents issues when working with old projects that use Node < 18
local M = {}
-- Function to get system Node.js path (avoiding project-specific versions)
local function get_system_node()
-- Priority order for system Node.js (avoiding project overrides)
local system_paths = {
"/opt/homebrew/bin/node", -- Homebrew on Apple Silicon
"/usr/local/bin/node", -- Homebrew on Intel Mac or standard install
vim.fn.expand("~/.volta/bin/node"), -- Volta's global Node
vim.fn.expand("~/.nvm/versions/node/*/bin/node"), -- NVM default version
vim.fn.expand("~/.nix-profile/bin/node"), -- Nix
"/usr/bin/node", -- System default
}
-- First try to find a system Node.js directly
for _, path in ipairs(system_paths) do
-- Handle glob patterns (for nvm)
if path:match("%*") then
local expanded = vim.fn.glob(path, false, true)
if #expanded > 0 then
-- Get the latest version from nvm
table.sort(expanded, function(a, b)
return a > b
end)
path = expanded[1]
else
goto continue
end
end
if vim.fn.executable(path) == 1 then
return path
end
::continue::
end
-- Fallback to whatever is in PATH (but warn if it might be project-specific)
return vim.fn.exepath("node")
end
-- Function to setup Node.js for Neovim
local function setup_nodejs()
-- Get system Node.js, avoiding project-specific versions
local node_path = get_system_node()
if node_path ~= "" then
local version_output = vim.fn.system(node_path .. " --version 2>/dev/null")
if vim.v.shell_error == 0 then
-- Clean version string: remove newlines, ANSI escape codes, and 'v' prefix
local version = version_output
:gsub("\r", "") -- Remove carriage returns
:gsub("\n", "") -- Remove newlines
:gsub("\27%[[%d;]*%a", "") -- Remove ANSI escape sequences
:gsub("^v", "") -- Remove 'v' prefix
:match("(%d+%.%d+%.%d+)") -- Extract version number pattern
if version then
local major_version = tonumber(version:match("^(%d+)"))
if major_version and major_version >= 18 then
-- Set the Node.js host program
vim.g.node_host_prog = node_path
-- Set npm path
local npm_path = vim.fn.exepath("npm")
if npm_path ~= "" then
vim.g.npm_host_prog = npm_path
end
if vim.g.debug_nodejs or vim.env.DEBUG_NODEJS then
print("✓ Node.js for Neovim: " .. node_path .. " (v" .. version .. ")")
-- Detect which manager is being used
if node_path:match("%.volta/") then
print(" Using Volta-managed Node.js")
elseif node_path:match("%.nvm/") then
print(" Using NVM-managed Node.js")
elseif node_path:match("%.nix%-profile/") then
print(" Using Nix-managed Node.js")
elseif node_path:match("/homebrew/") then
print(" Using Homebrew-managed Node.js")
else
print(" Using system Node.js")
end
end
return true, version
else
-- Provide specific upgrade instructions based on the detected manager
local upgrade_msg = "⚠️ Node.js version "
.. version
.. " is too old. Neovim requires v18+ (v22+ recommended).\n\n"
if node_path:match("/homebrew/") then
upgrade_msg = upgrade_msg .. "To upgrade with Homebrew:\n brew upgrade node"
elseif node_path:match("%.volta/") then
upgrade_msg = upgrade_msg .. "To upgrade with Volta:\n volta install node@latest"
elseif node_path:match("%.nvm/") then
upgrade_msg = upgrade_msg .. "To upgrade with NVM:\n nvm install --lts\n nvm alias default lts/*"
elseif node_path:match("%.nix%-profile/") then
upgrade_msg = upgrade_msg .. "To upgrade with Nix:\n nix profile upgrade nixpkgs#nodejs"
else
upgrade_msg = upgrade_msg .. "Please upgrade Node.js to v18 or higher using your package manager."
end
upgrade_msg = upgrade_msg .. "\n\nNote: Neovim uses the SYSTEM Node.js, not project-specific versions."
vim.notify(upgrade_msg, vim.log.levels.WARN)
vim.g.node_host_prog = node_path
return true, version
end
else
-- Handle case where version parsing failed
vim.notify(
"⚠️ Could not parse Node.js version from: "
.. version_output
.. "\nPlease ensure Node.js is properly installed.",
vim.log.levels.ERROR
)
return false, nil
end
end
end
vim.notify(
"⚠️ Node.js not found! Some plugins may not work correctly.\nInstall Node.js with:\n brew install node",
vim.log.levels.ERROR
)
return false, nil
end
-- Function to check if we're using a recent Node.js version
local function check_node_version()
if not vim.g.node_host_prog then
return
end
local version_output = vim.fn.system(vim.g.node_host_prog .. " --version 2>/dev/null")
if vim.v.shell_error ~= 0 then
return
end
local version = version_output:gsub("\n", ""):gsub("v", "")
local major_version = tonumber(version:match("^(%d+)"))
if major_version then
if major_version >= 18 and major_version < 22 then
if vim.g.debug_nodejs then
vim.notify(
" Node.js v" .. version .. " works but v22+ is recommended for optimal performance.",
vim.log.levels.INFO
)
end
elseif major_version < 18 then
vim.notify(
"⚠️ Node.js version " .. version .. " is too old. Neovim requires v18+ (v22+ recommended).",
vim.log.levels.WARN
)
end
end
end
-- Main setup function
function M.setup(opts)
opts = opts or {}
-- Setup Node.js
local success, version = setup_nodejs()
if success and not opts.silent then
check_node_version()
end
return success
end
-- Function to get current Node.js info
function M.info()
if not vim.g.node_host_prog then
print("Node.js: Not configured")
return
end
local version_output = vim.fn.system(vim.g.node_host_prog .. " --version 2>/dev/null")
if vim.v.shell_error ~= 0 then
print("Node.js: Error getting version")
return
end
local version = version_output:gsub("\n", ""):gsub("v", "")
print("Node.js for Neovim: " .. vim.g.node_host_prog .. " (v" .. version .. ")")
-- Detect source
if vim.g.node_host_prog:match("%.volta/") then
print("Source: Volta-managed")
elseif vim.g.node_host_prog:match("%.nvm/") then
print("Source: NVM-managed")
elseif vim.g.node_host_prog:match("%.nix%-profile/") then
print("Source: Nix-managed")
elseif vim.g.node_host_prog:match("/homebrew/") then
print("Source: Homebrew-managed")
else
print("Source: System")
end
if vim.g.npm_host_prog then
print("npm: " .. vim.g.npm_host_prog)
end
if vim.g.debug_nodejs then
print("\nPATH: " .. (vim.env.PATH or "not set"))
end
end
-- Command to manually refresh Node.js configuration
vim.api.nvim_create_user_command("NodeRefresh", function()
M.setup({ silent = false })
M.info()
end, { desc = "Refresh Node.js configuration" })
-- Command to show Node.js info
vim.api.nvim_create_user_command("NodeInfo", function()
M.info()
end, { desc = "Show Node.js configuration info" })
-- Command to debug Node.js PATH issues
vim.api.nvim_create_user_command("NodeDebug", function()
vim.g.debug_nodejs = true
print("=== Node.js Debug Mode Enabled ===")
M.setup({ silent = false })
M.info()
print("=== End Debug Info ===")
vim.g.debug_nodejs = false
end, { desc = "Debug Node.js configuration and PATH" })
return M

View File

@@ -0,0 +1,3 @@
-- Options are automatically loaded before lazy.nvim startup
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here

View File

@@ -0,0 +1,240 @@
return {
{
"yetone/avante.nvim",
-- if you want to build from source then do `make BUILD_FROM_SOURCE=true`
-- ⚠️ must add this setting! ! !
build = function()
-- conditionally use the correct build system for the current OS
if vim.fn.has("win32") == 1 then
return "powershell -ExecutionPolicy Bypass -File Build.ps1 -BuildFromSource false"
else
return "make"
end
end,
event = "VeryLazy",
version = false, -- Never set this value to "*"! Never!
---@module 'avante'
---@type avante.Config
opts = function(_, opts)
-- Track avante's internal state during resize
local in_resize = false
local original_cursor_win = nil
local avante_filetypes = { "Avante", "AvanteInput", "AvanteAsk", "AvanteSelectedFiles" }
-- Check if current window is avante
local function is_in_avante_window()
local win = vim.api.nvim_get_current_win()
local buf = vim.api.nvim_win_get_buf(win)
local ft = vim.api.nvim_buf_get_option(buf, "filetype")
for _, avante_ft in ipairs(avante_filetypes) do
if ft == avante_ft then
return true, win, ft
end
end
return false
end
-- Temporarily move cursor away from avante during resize
local function temporarily_leave_avante()
local is_avante, avante_win, avante_ft = is_in_avante_window()
if is_avante and not in_resize then
in_resize = true
original_cursor_win = avante_win
-- Find a non-avante window to switch to
local target_win = nil
for _, win in ipairs(vim.api.nvim_list_wins()) do
local buf = vim.api.nvim_win_get_buf(win)
local ft = vim.api.nvim_buf_get_option(buf, "filetype")
local is_avante_ft = false
for _, aft in ipairs(avante_filetypes) do
if ft == aft then
is_avante_ft = true
break
end
end
if not is_avante_ft and vim.api.nvim_win_is_valid(win) then
target_win = win
break
end
end
-- Switch to non-avante window if found
if target_win then
vim.api.nvim_set_current_win(target_win)
return true
end
end
return false
end
-- Restore cursor to original avante window
local function restore_cursor_to_avante()
if in_resize and original_cursor_win and vim.api.nvim_win_is_valid(original_cursor_win) then
-- Small delay to ensure resize is complete
vim.defer_fn(function()
pcall(vim.api.nvim_set_current_win, original_cursor_win)
in_resize = false
original_cursor_win = nil
end, 50)
end
end
-- Prevent duplicate windows cleanup
local function cleanup_duplicate_avante_windows()
local seen_filetypes = {}
local windows_to_close = {}
for _, win in ipairs(vim.api.nvim_list_wins()) do
local buf = vim.api.nvim_win_get_buf(win)
local ft = vim.api.nvim_buf_get_option(buf, "filetype")
-- Special handling for Ask and Select Files panels
if ft == "AvanteAsk" or ft == "AvanteSelectedFiles" then
if seen_filetypes[ft] then
-- Found duplicate, mark for closing
table.insert(windows_to_close, win)
else
seen_filetypes[ft] = win
end
end
end
-- Close duplicate windows
for _, win in ipairs(windows_to_close) do
if vim.api.nvim_win_is_valid(win) then
pcall(vim.api.nvim_win_close, win, true)
end
end
end
-- Create autocmd group for resize fix
vim.api.nvim_create_augroup("AvanteResizeFix", { clear = true })
-- Main resize handler for Resize
vim.api.nvim_create_autocmd({ "VimResized" }, {
group = "AvanteResizeFix",
callback = function()
-- Move cursor away from avante before resize processing
local moved = temporarily_leave_avante()
if moved then
-- Let resize happen, then restore cursor
vim.defer_fn(function()
restore_cursor_to_avante()
-- Force a clean redraw
vim.cmd("redraw!")
end, 100)
end
-- Cleanup duplicates after resize completes
vim.defer_fn(cleanup_duplicate_avante_windows, 150)
end,
})
-- Prevent avante from responding to scroll/resize events during resize
vim.api.nvim_create_autocmd({ "WinScrolled", "WinResized" }, {
group = "AvanteResizeFix",
pattern = "*",
callback = function(args)
local buf = args.buf
if buf and vim.api.nvim_buf_is_valid(buf) then
local ft = vim.api.nvim_buf_get_option(buf, "filetype")
for _, avante_ft in ipairs(avante_filetypes) do
if ft == avante_ft then
-- Prevent event propagation for avante buffers during resize
if in_resize then
return true -- This should stop the event
end
break
end
end
end
end,
})
-- Additional cleanup on focus events
vim.api.nvim_create_autocmd("FocusGained", {
group = "AvanteResizeFix",
callback = function()
-- Reset resize state on focus gain
in_resize = false
original_cursor_win = nil
-- Clean up any duplicate windows
vim.defer_fn(cleanup_duplicate_avante_windows, 100)
end,
})
return {
-- add any opts here
-- for example
provider = "copilot",
providers = {
copilot = {
model = "claude-sonnet-4",
},
},
cursor_applying_provider = "copilot",
auto_suggestions_provider = "copilot",
behaviour = {
enable_cursor_planning_mode = true,
},
-- File selector configuration
--- @alias FileSelectorProvider "native" | "fzf" | "mini.pick" | "snacks" | "telescope" | string
file_selector = {
provider = "snacks", -- Avoid native provider issues
provider_opts = {},
},
windows = {
---@type "right" | "left" | "top" | "bottom" | "smart"
position = "left", -- 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 = false,
},
input = {
prefix = "> ",
height = 8, -- Height of the input window in vertical layout
},
edit = {
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
---@type "ours" | "theirs"
focus_on_apply = "ours", -- which diff to focus after applying
},
},
system_prompt = "Este GPT es un clon del usuario, un arquitecto líder frontend especializado en Angular y React, con experiencia en arquitectura limpia, arquitectura hexagonal y separación de lógica en aplicaciones escalables. Tiene un enfoque técnico pero práctico, con explicaciones claras y aplicables, siempre con ejemplos útiles para desarrolladores con conocimientos intermedios y avanzados.\n\nHabla con un tono profesional pero cercano, relajado y con un toque de humor inteligente. Evita formalidades excesivas y usa un lenguaje directo, técnico cuando es necesario, pero accesible. Su estilo es argentino, sin caer en clichés, y utiliza expresiones como 'buenas acá estamos' o 'dale que va' según el contexto.\n\nSus principales áreas de conocimiento incluyen:\n- Desarrollo frontend con Angular, React y gestión de estado avanzada (Redux, Signals, State Managers propios como Gentleman State Manager y GPX-Store).\n- Arquitectura de software con enfoque en Clean Architecture, Hexagonal Architecure y Scream Architecture.\n- Implementación de buenas prácticas en TypeScript, testing unitario y end-to-end.\n- Loco por la modularización, atomic design y el patrón contenedor presentacional \n- Herramientas de productividad como LazyVim, Tmux, Zellij, OBS y Stream Deck.\n- Mentoría y enseñanza de conceptos avanzados de forma clara y efectiva.\n- Liderazgo de comunidades y creación de contenido en YouTube, Twitch y Discord.\n\nA la hora de explicar un concepto técnico:\n1. Explica el problema que el usuario enfrenta.\n2. Propone una solución clara y directa, con ejemplos si aplica.\n3. Menciona herramientas o recursos que pueden ayudar.\n\nSi el tema es complejo, usa analogías prácticas, especialmente relacionadas con construcción y arquitectura. Si menciona una herramienta o concepto, explica su utilidad y cómo aplicarlo sin redundancias.\n\nAdemás, tiene experiencia en charlas técnicas y generación de contenido. Puede hablar sobre la importancia de la introspección, có...",
}
end,
dependencies = {
"MunifTanjim/nui.nvim",
{
-- 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,
},
},
},
},
},
}

View File

@@ -0,0 +1,36 @@
return {
"saghen/blink.cmp",
lazy = true,
dependencies = { "saghen/blink.compat" },
opts = {
sources = {
default = { "avante_commands", "avante_mentions", "avante_files" },
compat = {
"avante_commands",
"avante_mentions",
"avante_files",
},
-- LSP score_offset is typically 60
providers = {
avante_commands = {
name = "avante_commands",
module = "blink.compat.source",
score_offset = 90,
opts = {},
},
avante_files = {
name = "avante_files",
module = "blink.compat.source",
score_offset = 100,
opts = {},
},
avante_mentions = {
name = "avante_mentions",
module = "blink.compat.source",
score_offset = 1000,
opts = {},
},
},
},
},
}

View File

@@ -0,0 +1,33 @@
return {
"coder/claudecode.nvim",
dependencies = { "folke/snacks.nvim" },
opts = {
terminal = {
split_side = "left",
split_width_percentage = 0.30,
provider = "snacks",
},
},
keys = {
{ "<leader>a", nil, desc = "AI/Claude Code" },
{ "<leader>ac", "<cmd>ClaudeCode<cr>", desc = "Toggle Claude" },
{ "<leader>af", "<cmd>ClaudeCodeFocus<cr>", desc = "Focus Claude" },
{ "<leader>ar", "<cmd>ClaudeCode --resume<cr>", desc = "Resume Claude" },
{ "<leader>aC", "<cmd>ClaudeCode --continue<cr>", desc = "Continue Claude" },
{ "<leader>am", "<cmd>ClaudeCodeSelectModel<cr>", desc = "Select Claude model" },
{ "<leader>ab", "<cmd>ClaudeCodeAdd %<cr>", desc = "Add current buffer" },
{ "<leader>as", "<cmd>ClaudeCodeSend<cr>", mode = "v", desc = "Send to Claude" },
{
"<leader>as",
"<cmd>ClaudeCodeTreeAdd<cr>",
desc = "Add file",
ft = { "NvimTree", "neo-tree", "oil", "minifiles" },
},
-- Diff management
{ "<leader>aa", "<cmd>ClaudeCodeDiffAccept<cr>", desc = "Accept diff" },
{ "<leader>ad", "<cmd>ClaudeCodeDiffDeny<cr>", desc = "Deny diff" },
-- Preserved existing keymaps
{ "<leader>at", "<cmd>ClaudeCodeContinue<cr>", desc = "Continue recent conversation" },
{ "<leader>av", "<cmd>ClaudeCodeVerbose<cr>", desc = "Verbose logging" },
},
}

View File

@@ -0,0 +1,173 @@
return {
"olimorris/codecompanion.nvim",
init = function()
vim.cmd([[cab cc CodeCompanion]])
require("plugins.codecompanion.codecompanion-notifier"):init()
local group = vim.api.nvim_create_augroup("CodeCompanionHooks", {})
vim.api.nvim_create_autocmd({ "User" }, {
pattern = "CodeCompanionInlineFinished",
group = group,
callback = function(request)
vim.lsp.buf.format({ bufnr = request.buf })
end,
})
end,
cmd = {
"CodeCompanion",
"CodeCompanionActions",
"CodeCompanionChat",
"CodeCompanionCmd",
},
keys = {
{ "<leader>ac", "<cmd>CodeCompanionChat Toggle<cr>", mode = { "n", "v" }, desc = "AI Toggle [C]hat" },
{ "<leader>an", "<cmd>CodeCompanionChat<cr>", mode = { "n", "v" }, desc = "AI [N]ew Chat" },
{ "<leader>aa", "<cmd>CodeCompanionActions<cr>", mode = { "n", "v" }, desc = "AI [A]ction" },
{ "ga", "<cmd>CodeCompanionChat Add<CR>", mode = { "v" }, desc = "AI [A]dd to Chat" },
-- prompts
{ "<leader>ae", "<cmd>CodeCompanion /explain<cr>", mode = { "v" }, desc = "AI [E]xplain" },
},
config = true,
opts = {
adapters = {
copilot_4o = function()
return require("codecompanion.adapters").extend("copilot", {
schema = {
model = {
default = "gpt-4o",
},
},
})
end,
copilot_41 = function()
return require("codecompanion.adapters").extend("copilot", {
schema = {
model = {
default = "gpt-4.1",
},
},
})
end,
copilot_gemini_25_pro = function()
return require("codecompanion.adapters").extend("copilot", {
schema = {
model = {
default = "gemini-2.5-pro",
},
},
})
end,
},
display = {
diff = {
enabled = true,
close_chat_at = 240, -- Close an open chat buffer if the total columns of your display are less than...
layout = "vertical", -- vertical|horizontal split for default provider
opts = { "internal", "filler", "closeoff", "algorithm:patience", "followwrap", "linematch:120" },
provider = "default", -- default|mini_diff
},
chat = {
window = {
position = "left",
},
},
},
strategies = {
inline = {
keymaps = {
accept_change = {
modes = { n = "ga" },
description = "Accept the suggested change",
},
reject_change = {
modes = { n = "gr" },
description = "Reject the suggested change",
},
},
},
chat = {
slash_commands = {
["git_files"] = {
description = "List git files",
---@param chat CodeCompanion.Chat
callback = function(chat)
local handle = io.popen("git ls-files")
if handle ~= nil then
local result = handle:read("*a")
handle:close()
chat:add_reference({ role = "user", content = result }, "git", "<git_files>")
else
return vim.notify("No git files available", vim.log.levels.INFO, { title = "CodeCompanion" })
end
end,
opts = {
contains_code = false,
},
},
},
keymaps = {
send = {
modes = { n = "<CR>", i = "<C-s>" },
},
close = {
modes = { n = "<C-c>", i = "<C-c>" },
},
-- Add further custom keymaps here
},
adapter = "copilot",
roles = {
---The header name for the LLM's messages
---@type string|fun(adapter: CodeCompanion.Adapter): string
llm = function(adapter)
return "AI (" .. adapter.formatted_name .. ")"
end,
---The header name for your messages
---@type string
user = "Vos",
},
tools = {
groups = {
["full_stack_dev"] = {
description = "Full Stack Developer - Can run code, edit code and modify files",
system_prompt = "**DO NOT** make any assumptions about the dependencies that a user has installed. If you need to install any dependencies to fulfil the user's request, do so via the Command Runner tool. If the user doesn't specify a path, use their current working directory.",
tools = {
"cmd_runner",
"editor",
"files",
},
},
["gentleman"] = {
description = "The Gentleman",
system_prompt = "Este GPT es un clon del usuario, un arquitecto líder frontend especializado en Angular y React, con experiencia en arquitectura limpia, arquitectura hexagonal y separación de lógica en aplicaciones escalables. Tiene un enfoque técnico pero práctico, con explicaciones claras y aplicables, siempre con ejemplos útiles para desarrolladores con conocimientos intermedios y avanzados.\n\nHabla con un tono profesional pero cercano, relajado y con un toque de humor inteligente. Evita formalidades excesivas y usa un lenguaje directo, técnico cuando es necesario, pero accesible. Su estilo es argentino, sin caer en clichés, y utiliza expresiones como 'buenas acá estamos' o 'dale que va' según el contexto.\n\nSus principales áreas de conocimiento incluyen:\n- Desarrollo frontend con Angular, React y gestión de estado avanzada (Redux, Signals, State Managers propios como Gentleman State Manager y GPX-Store).\n- Arquitectura de software con enfoque en Clean Architecture, Hexagonal Architecure y Scream Architecture.\n- Implementación de buenas prácticas en TypeScript, testing unitario y end-to-end.\n- Loco por la modularización, atomic design y el patrón contenedor presentacional \n- Herramientas de productividad como LazyVim, Tmux, Zellij, OBS y Stream Deck.\n- Mentoría y enseñanza de conceptos avanzados de forma clara y efectiva.\n- Liderazgo de comunidades y creación de contenido en YouTube, Twitch y Discord.\n\nA la hora de explicar un concepto técnico:\n1. Explica el problema que el usuario enfrenta.\n2. Propone una solución clara y directa, con ejemplos si aplica.\n3. Menciona herramientas o recursos que pueden ayudar.\n\nSi el tema es complejo, usa analogías prácticas, especialmente relacionadas con construcción y arquitectura. Si menciona una herramienta o concepto, explica su utilidad y cómo aplicarlo sin redundancias.\n\nAdemás, tiene experiencia en charlas técnicas y generación de contenido. Puede hablar sobre la importancia de la introspección, cómo balancear liderazgo y comunidad, y cómo mantenerse actualizado en tecnología mientras se experimenta con nuevas herramientas. Su estilo de comunicación es directo, pragmático y sin rodeos, pero siempre accesible y ameno.\n\nEsta es una transcripción de uno de sus vídeos para que veas como habla:\n\nLe estaba contando la otra vez que tenía una condición Que es de adulto altamente calificado no sé si lo conocen pero no es bueno el oto lo está hablando con mi mujer y y a mí cuando yo era chico mi mamá me lo dijo en su momento que a mí me habían encontrado una condición Que ti un iq muy elevado cuando era muy chico eh pero muy elevado a nivel de que estaba 5 años o 6 años por delante de un niño",
tools = {
"cmd_runner",
"editor",
"files",
},
},
},
["cmd_runner"] = {
callback = "strategies.chat.agents.tools.cmd_runner",
description = "Run shell commands initiated by the LLM",
opts = {
requires_approval = true,
},
},
["editor"] = {
callback = "strategies.chat.agents.tools.editor",
description = "Update a buffer with the LLM's response",
},
["files"] = {
callback = "strategies.chat.agents.tools.files",
description = "Update the file system with the LLM's response",
opts = {
requires_approval = true,
},
},
},
},
},
},
}

View File

@@ -0,0 +1,119 @@
local M = {}
local uv = vim.uv
local api = vim.api
local active = {} -- dictionary of active requests
local S = {
frames = { "", "", "", "", "", "", "", "", "", "" },
speed = 80, -- milliseconds per frame
}
local function spinner_frame()
local time = math.floor(uv.hrtime() / (1e6 * S.speed))
local idx = time % #S.frames + 1
local frame = S.frames[idx]
return frame
end
local function refresh_notifications(key)
return function()
local req = active[key]
if not req then
return
end
vim.notify(req.msg, vim.log.levels.INFO, {
id = "cc_progress",
title = req.adapter,
opts = function(notif)
local icon = ""
if not req.done then
icon = spinner_frame()
end
notif.icon = icon
end,
})
end
end
local function request_key(data)
local adapter = data.adapter or {}
local name = adapter.formatted_name or adapter.name or "unknown"
return string.format("%s:%s", name, data.id or "???")
end
local function start(ev)
local data = ev.data or {}
local key = request_key(data)
local adapter = data.adapter and data.adapter.name or "CodeCompanion"
local refresh = refresh_notifications(key)
local timer = uv.new_timer()
local req = {
adapter = adapter,
done = false,
msg = "Thinking...",
refresh = refresh,
timer = timer,
}
active[key] = req
timer:start(0, 150, vim.schedule_wrap(refresh))
refresh()
end
local function finished(ev)
local data = ev.data or {}
local key = request_key(data)
local req = active[key]
if not req then
return
end
req.done = true
if data.status == "success" then
req.msg = "Done."
elseif data.status == "error" then
req.msg = "Error!"
else
req.msg = "Cancelled."
end
req.refresh()
-- clear the finished request
active[key] = nil
if req.timer then
req.timer:stop()
req.timer:close()
end
end
function M.setup()
local group = vim.api.nvim_create_augroup("CodeCompanionSnacks", { clear = true })
vim.api.nvim_create_autocmd("User", {
pattern = "CodeCompanionRequestStarted",
group = group,
callback = start,
})
vim.api.nvim_create_autocmd("User", {
pattern = "CodeCompanionRequestFinished",
group = group,
callback = finished,
})
end
function M.init()
M.setup()
end
return M

View File

@@ -0,0 +1,113 @@
return {
{
-- {
-- "xiyaowong/transparent.nvim",
-- config = function()
-- require("transparent").setup({
-- extra_groups = { -- table/string: additional groups that should be cleared
-- "Normal",
-- "NormalNC",
-- "Comment",
-- "Constant",
-- "Special",
-- "Identifier",
-- "Statement",
-- "PreProc",
-- "Type",
-- "Underlined",
-- "Todo",
-- "String",
-- "Function",
-- "Conditional",
-- "Repeat",
-- "Operator",
-- "Structure",
-- "LineNr",
-- "NonText",
-- "SignColumn",
-- "CursorLineNr",
-- "EndOfBuffer",
-- },
-- exclude_groups = {}, -- table: groups you don't want to clear
-- })
-- end,
-- },
{
"catppuccin/nvim",
name = "catppuccin",
priority = 1000,
opts = {
flavour = "mocha", -- latte, frappe, macchiato, mocha
transparent_background = true, -- disables setting the background color.
term_colors = true, -- sets terminal colors (e.g. `g:terminal_color_0`)
},
},
{
"Gentleman-Programming/gentleman-kanagawa-blur",
name = "gentleman-kanagawa-blur",
priority = 1000,
},
{
"Alan-TheGentleman/oldworld.nvim",
lazy = false,
priority = 1000,
opts = {},
},
{
"rebelot/kanagawa.nvim",
priority = 1000,
lazy = true,
config = function()
require("kanagawa").setup({
compile = false, -- enable compiling the colorscheme
undercurl = true, -- enable undercurls
commentStyle = { italic = true },
functionStyle = {},
keywordStyle = { italic = true },
statementStyle = { bold = true },
typeStyle = {},
transparent = true, -- do not set background color
dimInactive = false, -- dim inactive window `:h hl-NormalNC`
terminalColors = true, -- define vim.g.terminal_color_{0,17}
colors = { -- add/modify theme and palette colors
palette = {},
theme = {
wave = {},
lotus = {},
dragon = {},
all = {
ui = {
bg_gutter = "none", -- set bg color for normal background
bg_sidebar = "none", -- set bg color for sidebar like nvim-tree
bg_float = "none", -- set bg color for floating windows
},
},
},
},
overrides = function(colors) -- add/modify highlights
return {
LineNr = { bg = "none" },
NormalFloat = { bg = "none" },
FloatBorder = { bg = "none" },
FloatTitle = { bg = "none" },
TelescopeNormal = { bg = "none" },
TelescopeBorder = { bg = "none" },
LspInfoBorder = { bg = "none" },
}
end,
theme = "wave", -- Load "wave" theme
background = { -- map the value of 'background' option to a theme
dark = "wave", -- try "dragon" !
light = "lotus",
},
})
end,
},
{
"LazyVim/LazyVim",
opts = {
colorscheme = "gentleman-kanagawa-blur",
},
},
},
}

View File

@@ -0,0 +1,129 @@
-- This file contains the configuration for integrating GitHub Copilot and Copilot Chat plugins in Neovim.
-- Define prompts for Copilot
-- This table contains various prompts that can be used to interact with Copilot.
local prompts = {
Explain = "Please explain how the following code works.", -- Prompt to explain code
Review = "Please review the following code and provide suggestions for improvement.", -- Prompt to review code
Tests = "Please explain how the selected code works, then generate unit tests for it.", -- Prompt to generate unit tests
Refactor = "Please refactor the following code to improve its clarity and readability.", -- Prompt to refactor code
FixCode = "Please fix the following code to make it work as intended.", -- Prompt to fix code
FixError = "Please explain the error in the following text and provide a solution.", -- Prompt to fix errors
BetterNamings = "Please provide better names for the following variables and functions.", -- Prompt to suggest better names
Documentation = "Please provide documentation for the following code.", -- Prompt to generate documentation
JsDocs = "Please provide JsDocs for the following code.", -- Prompt to generate JsDocs
DocumentationForGithub = "Please provide documentation for the following code ready for GitHub using markdown.", -- Prompt to generate GitHub documentation
CreateAPost = "Please provide documentation for the following code to post it in social media, like Linkedin, it has be deep, well explained and easy to understand. Also do it in a fun and engaging way.", -- Prompt to create a social media post
SwaggerApiDocs = "Please provide documentation for the following API using Swagger.", -- Prompt to generate Swagger API docs
SwaggerJsDocs = "Please write JSDoc for the following API using Swagger.", -- Prompt to generate Swagger JsDocs
Summarize = "Please summarize the following text.", -- Prompt to summarize text
Spelling = "Please correct any grammar and spelling errors in the following text.", -- Prompt to correct spelling and grammar
Wording = "Please improve the grammar and wording of the following text.", -- Prompt to improve wording
Concise = "Please rewrite the following text to make it more concise.", -- Prompt to make text concise
}
-- Plugin configuration
-- This table contains the configuration for various plugins used in Neovim.
return {
{
-- Copilot Chat plugin configuration
"CopilotC-Nvim/CopilotChat.nvim",
branch = "main",
cmd = "CopilotChat",
opts = {
prompts = prompts,
system_prompt = "Este GPT es un clon del usuario, un arquitecto líder frontend especializado en Angular y React, con experiencia en arquitectura limpia, arquitectura hexagonal y separación de lógica en aplicaciones escalables. Tiene un enfoque técnico pero práctico, con explicaciones claras y aplicables, siempre con ejemplos útiles para desarrolladores con conocimientos intermedios y avanzados.\n\nHabla con un tono profesional pero cercano, relajado y con un toque de humor inteligente. Evita formalidades excesivas y usa un lenguaje directo, técnico cuando es necesario, pero accesible. Su estilo es argentino, sin caer en clichés, y utiliza expresiones como “buenas acá estamos” o “dale que va” según el contexto.\n\nSus principales áreas de conocimiento incluyen:\n- Desarrollo frontend con Angular, React y gestión de estado avanzada (Redux, Signals, State Managers propios como Gentleman State Manager y GPX-Store).\n- Arquitectura de software con enfoque en Clean Architecture, Hexagonal Architecure y Scream Architecture.\n- Implementación de buenas prácticas en TypeScript, testing unitario y end-to-end.\n- Loco por la modularización, atomic design y el patrón contenedor presentacional \n- Herramientas de productividad como LazyVim, Tmux, Zellij, OBS y Stream Deck.\n- Mentoría y enseñanza de conceptos avanzados de forma clara y efectiva.\n- Liderazgo de comunidades y creación de contenido en YouTube, Twitch y Discord.\n\nA la hora de explicar un concepto técnico:\n1. Explica el problema que el usuario enfrenta.\n2. Propone una solución clara y directa, con ejemplos si aplica.\n3. Menciona herramientas o recursos que pueden ayudar.\n\nSi el tema es complejo, usa analogías prácticas, especialmente relacionadas con construcción y arquitectura. Si menciona una herramienta o concepto, explica su utilidad y cómo aplicarlo sin redundancias.\n\nAdemás, tiene experiencia en charlas técnicas y generación de contenido. Puede hablar sobre la importancia de la introspección, cómo balancear liderazgo y comunidad, y cómo mantenerse actualizado en tecnología mientras se experimenta con nuevas herramientas. Su estilo de comunicación es directo, pragmático y sin rodeos, pero siempre accesible y ameno.\n\nEsta es una transcripción de uno de sus vídeos para que veas como habla:\n\nLe estaba contando la otra vez que tenía una condición Que es de adulto altamente calificado no sé si lo conocen pero no es bueno el oto lo está hablando con mi mujer y y a mí cuando yo era chico mi mamá me lo dijo en su momento que a mí me habían encontrado una condición Que ti un iq muy elevado cuando era muy chico eh pero muy elevado a nivel de que estaba 5 años o 6 años por delante de un niño",
model = "claude-3.5-sonnet",
answer_header = "󱗞 The Gentleman 󱗞 ",
auto_insert_mode = true,
window = {
layout = "horizontal",
},
mappings = {
complete = {
insert = "<Tab>",
},
close = {
normal = "q",
insert = "<C-c>",
},
reset = {
normal = "<C-l>",
insert = "<C-l>",
},
submit_prompt = {
normal = "<CR>",
insert = "<C-s>",
},
toggle_sticky = {
normal = "grr",
},
clear_stickies = {
normal = "grx",
},
accept_diff = {
normal = "<C-y>",
insert = "<C-y>",
},
jump_to_diff = {
normal = "gj",
},
quickfix_answers = {
normal = "gqa",
},
quickfix_diffs = {
normal = "gqd",
},
yank_diff = {
normal = "gy",
register = '"', -- Default register to use for yanking
},
show_diff = {
normal = "gd",
full_diff = false, -- Show full diff instead of unified diff when showing diff window
},
show_info = {
normal = "gi",
},
show_context = {
normal = "gc",
},
show_help = {
normal = "gh",
},
},
},
config = function(_, opts)
local chat = require("CopilotChat")
vim.api.nvim_create_autocmd("BufEnter", {
pattern = "copilot-chat",
callback = function()
vim.opt_local.relativenumber = true
vim.opt_local.number = false
end,
})
chat.setup(opts)
end,
},
-- Blink integration
{
"saghen/blink.cmp",
optional = true,
---@module 'blink.cmp'
---@type blink.cmp.Config
opts = {
sources = {
providers = {
path = {
-- Path sources triggered by "/" interfere with CopilotChat commands
enabled = function()
return vim.bo.filetype ~= "copilot-chat"
end,
},
},
},
},
},
}

View File

@@ -0,0 +1,20 @@
return {
"zbirenbaum/copilot.lua",
optional = true,
opts = function()
require("copilot.api").status = require("copilot.status")
require("copilot.api").filetypes = {
filetypes = {
yaml = false,
markdown = false,
help = false,
gitcommit = false,
gitrebase = false,
hgcommit = false,
svn = false,
cvs = false,
["."] = false,
},
}
end,
}

View File

@@ -0,0 +1,46 @@
-- This file contains the configuration for disabling specific Neovim plugins.
return {
{
-- Plugin: bufferline.nvim
-- URL: https://github.com/akinsho/bufferline.nvim
-- Description: A snazzy buffer line (with tabpage integration) for Neovim.
"akinsho/bufferline.nvim",
enabled = false, -- Disable this plugin
},
{
-- Plugin para mejorar la experiencia de edición en Neovim
-- URL: https://github.com/yetone/avante.nvim
-- Description: Este plugin ofrece una serie de mejoras y herramientas para optimizar la edición de texto en Neovim.
"yetone/avante.nvim",
enabled = false,
},
{
"CopilotC-Nvim/CopilotChat.nvim",
enabled = false,
},
{
"NickvanDyke/opencode.nvim",
enabled = true,
},
{
"olimorris/codecompanion.nvim",
enabled = false,
},
{
"tris203/precognition.nvim",
enabled = false,
},
{
"sphamba/smear-cursor.nvim",
enabled = false,
},
{
-- Plugin: claude-code.nvim
-- URL: https://github.com/greggh/claude-code.nvim
-- Description: Neovim integration for Claude Code AI assistant
"coder/claudecode.nvim",
enabled = false,
},
}

View File

@@ -0,0 +1,84 @@
-- This file contains the configuration for various Neovim plugins related to the editor.
return {
{
-- Plugin: goto-preview
-- URL: https://github.com/rmagatti/goto-preview
-- Description: Provides preview functionality for definitions, declarations, implementations, type definitions, and references.
"rmagatti/goto-preview",
event = "BufEnter", -- Load the plugin when a buffer is entered
config = true, -- Enable default configuration
keys = {
{
"gpd",
"<cmd>lua require('goto-preview').goto_preview_definition()<CR>",
noremap = true, -- Do not allow remapping
desc = "goto preview definition", -- Description for the keybinding
},
{
"gpD",
"<cmd>lua require('goto-preview').goto_preview_declaration()<CR>",
noremap = true,
desc = "goto preview declaration",
},
{
"gpi",
"<cmd>lua require('goto-preview').goto_preview_implementation()<CR>",
noremap = true,
desc = "goto preview implementation",
},
{
"gpy",
"<cmd>lua require('goto-preview').goto_preview_type_definition()<CR>",
noremap = true,
desc = "goto preview type definition",
},
{
"gpr",
"<cmd>lua require('goto-preview').goto_preview_references()<CR>",
noremap = true,
desc = "goto preview references",
},
{
"gP",
"<cmd>lua require('goto-preview').close_all_win()<CR>",
noremap = true,
desc = "close all preview windows",
},
},
},
{
-- Plugin: mini.hipatterns
-- URL: https://github.com/nvim-mini/mini.hipatterns
-- Description: Provides highlighter patterns for various text patterns.
"nvim-mini/mini.hipatterns",
event = "BufReadPre", -- Load the plugin before reading a buffer
opts = {
highlighters = {
hsl_color = {
pattern = "hsl%(%d+,? %d+,? %d+%)", -- Pattern to match HSL color values
group = function(_, match)
local utils = require("config.gentleman.utils")
local h, s, l = match:match("hsl%((%d+),? (%d+),? (%d+)%)")
h, s, l = tonumber(h), tonumber(s), tonumber(l)
local hex_color = utils.hslToHex(h, s, l)
return MiniHipatterns.compute_hex_color_group(hex_color, "bg")
end,
},
},
},
},
{
-- Plugin: git.nvim
-- URL: https://github.com/dinhhuy258/git.nvim
-- Description: Provides Git integration for Neovim.
"dinhhuy258/git.nvim",
event = "BufReadPre", -- Load the plugin before reading a buffer
opts = {
keymaps = {
blame = "<Leader>gb", -- Keybinding to open blame window
browse = "<Leader>go", -- Keybinding to open file/folder in git repository
},
},
},
}

View File

@@ -0,0 +1,31 @@
return {
"dmtrKovalenko/fff.nvim",
build = function()
-- this will download prebuild binary or try to use existing rustup toolchain to build from source
-- (if you are using lazy you can use gb for rebuilding a plugin if needed)
require("fff.download").download_or_build_binary()
end,
-- if you are using nixos
-- build = "nix run .#release",
opts = { -- (optional)
debug = {
enabled = true, -- we expect your collaboration at least during the beta
show_scores = true, -- to help us optimize the scoring system, feel free to share your scores!
},
preview = {
line_numbers = true,
},
},
-- No need to lazy-load with lazy.nvim.
-- This plugin initializes itself lazily.
lazy = false,
keys = {
{
"ff", -- try it if you didn't it is a banger keybinding for a picker
function()
require("fff").find_files()
end,
desc = "FFFind files",
},
},
}

View File

@@ -0,0 +1,5 @@
return {
"ibhagwan/fzf-lua",
dependencies = { "nvim-tree/nvim-web-devicons" },
opts = {},
}

View File

@@ -0,0 +1,6 @@
return {
"jonroosevelt/gemini-cli.nvim",
config = function()
require("gemini").setup()
end,
}

View File

@@ -0,0 +1,21 @@
return {
"MeanderingProgrammer/render-markdown.nvim",
dependencies = { "nvim-treesitter/nvim-treesitter", "nvim-mini/mini.nvim" }, -- if you use the mini.nvim suite
---@module 'render-markdown'
---@type render.md.UserConfig
opts = {
heading = {
enabled = true,
sign = true,
style = "full",
icons = { "", "", "", "", "", "" },
left_pad = 1,
},
bullet = {
enabled = true,
icons = { "", "", "", "" },
right_pad = 1,
highlight = "render-markdownBullet",
},
},
}

View File

@@ -0,0 +1,10 @@
-- This file contains the configuration for the vim-multiple-cursors plugin in Neovim.
return {
{
-- Plugin: vim-multiple-cursors
-- URL: https://github.com/terryma/vim-multiple-cursors
-- Description: A Vim plugin that allows multiple cursors for simultaneous editing.
"terryma/vim-multiple-cursors",
},
}

View File

@@ -0,0 +1,212 @@
-- This file contains the configuration for the nvim-dap plugin in Neovim.
return {
{
-- Plugin: nvim-dap
-- URL: https://github.com/mfussenegger/nvim-dap
-- Description: Debug Adapter Protocol client implementation for Neovim.
"mfussenegger/nvim-dap",
recommended = true, -- Recommended plugin
desc = "Debugging support. Requires language specific adapters to be configured. (see lang extras)",
dependencies = {
-- Plugin: nvim-dap-ui
-- URL: https://github.com/rcarriga/nvim-dap-ui
-- Description: A UI for nvim-dap.
"rcarriga/nvim-dap-ui",
-- Plugin: nvim-dap-virtual-text
-- URL: https://github.com/theHamsta/nvim-dap-virtual-text
-- Description: Virtual text for the debugger.
{
"theHamsta/nvim-dap-virtual-text",
opts = {}, -- Default options
},
},
-- Keybindings for nvim-dap
keys = {
{ "<leader>d", "", desc = "+debug", mode = { "n", "v" } }, -- Group for debug commands
{
"<leader>dB",
function()
require("dap").set_breakpoint(vim.fn.input("Breakpoint condition: "))
end,
desc = "Breakpoint Condition",
},
{
"<leader>db",
function()
require("dap").toggle_breakpoint()
end,
desc = "Toggle Breakpoint",
},
{
"<leader>dc",
function()
require("dap").continue()
end,
desc = "Continue",
},
{
"<leader>da",
function()
require("dap").continue({ before = get_args })
end,
desc = "Run with Args",
},
{
"<leader>dC",
function()
require("dap").run_to_cursor()
end,
desc = "Run to Cursor",
},
{
"<leader>dg",
function()
require("dap").goto_()
end,
desc = "Go to Line (No Execute)",
},
{
"<leader>di",
function()
require("dap").step_into()
end,
desc = "Step Into",
},
{
"<leader>dj",
function()
require("dap").down()
end,
desc = "Down",
},
{
"<leader>dk",
function()
require("dap").up()
end,
desc = "Up",
},
{
"<leader>dl",
function()
require("dap").run_last()
end,
desc = "Run Last",
},
{
"<leader>do",
function()
require("dap").step_out()
end,
desc = "Step Out",
},
{
"<leader>dO",
function()
require("dap").step_over()
end,
desc = "Step Over",
},
{
"<leader>dp",
function()
require("dap").pause()
end,
desc = "Pause",
},
{
"<leader>dr",
function()
require("dap").repl.toggle()
end,
desc = "Toggle REPL",
},
{
"<leader>ds",
function()
require("dap").session()
end,
desc = "Session",
},
{
"<leader>dt",
function()
require("dap").terminate()
end,
desc = "Terminate",
},
{
"<leader>dw",
function()
require("dap.ui.widgets").hover()
end,
desc = "Widgets",
},
},
config = function()
local dap = require("dap")
-- Load mason-nvim-dap if available
if LazyVim.has("mason-nvim-dap.nvim") then
require("mason-nvim-dap").setup(LazyVim.opts("mason-nvim-dap.nvim"))
end
-- Set highlight for DapStoppedLine
vim.api.nvim_set_hl(0, "DapStoppedLine", { default = true, link = "Visual" })
-- Define signs for DAP
for name, sign in pairs(LazyVim.config.icons.dap) do
sign = type(sign) == "table" and sign or { sign }
vim.fn.sign_define(
"Dap" .. name,
{ text = sign[1], texthl = sign[2] or "DiagnosticInfo", linehl = sign[3], numhl = sign[3] }
)
end
-- Setup DAP configuration using VsCode launch.json file
local vscode = require("dap.ext.vscode")
local json = require("plenary.json")
vscode.json_decode = function(str)
return vim.json.decode(json.json_strip_comments(str))
end
-- Load launch configurations from .vscode/launch.json if it exists
if vim.fn.filereadable(".vscode/launch.json") then
vscode.load_launchjs()
end
-- Function to load environment variables
local function load_env_variables()
local variables = {}
for k, v in pairs(vim.fn.environ()) do
variables[k] = v
end
-- Load variables from .env file manually
local env_file_path = vim.fn.getcwd() .. "/.env"
local env_file = io.open(env_file_path, "r")
if env_file then
for line in env_file:lines() do
for key, value in string.gmatch(line, "([%w_]+)=([%w_]+)") do
variables[key] = value
end
end
env_file:close()
else
print("Error: .env file not found in " .. env_file_path)
end
return variables
end
-- Add the env property to each existing Go configuration
for _, config in pairs(dap.configurations.go or {}) do
config.env = load_env_variables
end
end,
},
}

View File

@@ -0,0 +1,54 @@
return {
"obsidian-nvim/obsidian.nvim",
version = "*", -- recommended, use latest release instead of latest commit
lazy = false,
enabled = function()
-- Disable Obsidian when running from Oil Simple (to avoid path issues in Zed context)
return not vim.g.disable_obsidian
end,
dependencies = {
-- Required.
"nvim-lua/plenary.nvim",
},
opts = {
workspaces = {
{
name = "GentlemanNotes", -- Name of the workspace
path = os.getenv("HOME") .. "/.config/obsidian", -- Path to the notes directory
},
},
completition = {
cmp = true,
},
picker = {
-- Set your preferred picker. Can be one of 'telescope.nvim', 'fzf-lua', 'mini.pick' or 'snacks.pick'.
name = "snacks.pick",
},
-- Optional, define your own callbacks to further customize behavior.
callbacks = {
-- Runs anytime you enter the buffer for a note.
enter_note = function(client, note)
-- Setup keymaps for obsidian notes
vim.keymap.set("n", "gf", function()
return require("obsidian").util.gf_passthrough()
end, { buffer = note.bufnr, expr = true, desc = "Obsidian follow link" })
vim.keymap.set("n", "<leader>ch", function()
return require("obsidian").util.toggle_checkbox()
end, { buffer = note.bufnr, desc = "Toggle checkbox" })
vim.keymap.set("n", "<cr>", function()
return require("obsidian").util.smart_action()
end, { buffer = note.bufnr, expr = true, desc = "Obsidian smart action" })
end,
},
-- Settings for templates
templates = {
subdir = "templates", -- Subdirectory for templates
date_format = "%Y-%m-%d-%a", -- Date format for templates
gtime_format = "%H:%M", -- Time format for templates
tags = "", -- Default tags for templates
},
},
}

View File

@@ -0,0 +1,178 @@
-- Oil.nvim: Edit your filesystem like a buffer
-- URL: https://github.com/stevearc/oil.nvim
return {
"stevearc/oil.nvim",
-- Load Oil when opening a directory or when using the keymap
lazy = false,
keys = {
{ "-", "<CMD>Oil<CR>", desc = "Open Oil (parent dir)" },
{ "<leader>E", "<CMD>Oil --float<CR>", desc = "Open Oil (floating)" },
},
opts = {
-- Oil will take over directory buffers (e.g. `vim .` or `:e src/`)
default_file_explorer = true,
-- Restore window options to previous values when leaving an oil buffer
restore_win_options = true,
-- Skip the confirmation popup for simple operations
skip_confirm_for_simple_edits = false,
-- Selecting a new/moved/renamed file or directory will prompt you to save changes first
prompt_save_on_select_new_entry = true,
-- Keymaps in oil buffer. Can be any value that `vim.keymap.set` accepts OR a table of keymap
keymaps = {
["g?"] = "actions.show_help",
["<CR>"] = "actions.select",
["<C-s>"] = { "actions.select", opts = { vertical = true }, desc = "Open in vertical split" },
["<C-v>"] = { "actions.select", opts = { horizontal = true }, desc = "Open in horizontal split" },
["<C-t>"] = { "actions.select", opts = { tab = true }, desc = "Open in new tab" },
["<C-p>"] = "actions.preview",
["<C-c>"] = "actions.close",
["<C-r>"] = "actions.refresh",
["-"] = "actions.parent",
["_"] = "actions.open_cwd",
["`"] = "actions.cd",
["~"] = { "actions.cd", opts = { scope = "tab" }, desc = ":tcd to the current oil directory" },
["gs"] = "actions.change_sort",
["gx"] = "actions.open_external",
["g."] = "actions.toggle_hidden",
["g\\"] = "actions.toggle_trash",
-- Quick quit
["q"] = "actions.close",
},
-- Set to false to disable all of the above keymaps
use_default_keymaps = false,
view_options = {
-- Show files and directories that start with "." by default
show_hidden = true,
-- This function defines what is considered a "hidden" file
is_hidden_file = function(name, bufnr)
return vim.startswith(name, ".")
end,
-- This function defines what will never be shown, even when `show_hidden` is set
is_always_hidden = function(name, bufnr)
return name == ".." or name == ".git"
end,
-- Natural sort order for files and directories
natural_order = true,
case_insensitive = false,
sort = {
-- sort order can be "asc" or "desc"
-- see :help oil-columns to see which columns are sortable
{ "type", "asc" },
{ "name", "asc" },
},
},
-- Configuration for the floating window in oil.open_float
float = {
-- Padding around the floating window
padding = 2,
max_width = 100,
max_height = 30,
border = "rounded",
win_options = {
winblend = 0,
},
-- preview_split: Split direction: "auto", "left", "right", "above", "below".
preview_split = "auto",
-- This is the config that will be passed to nvim_open_win.
-- Change values here to customize the layout
override = function(conf)
return conf
end,
},
-- Configuration for the actions floating preview window
preview = {
-- Width dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
-- min_width and max_width can be a single value or a list of mixed integer/float types.
max_width = 0.9,
-- min_width = {40, 0.4} means "at least 40 columns, or at least 40% of total"
min_width = { 40, 0.4 },
-- optionally define an integer/float for the exact width of the preview window
width = nil,
-- Height dimensions can be integers or a float between 0 and 1 (e.g. 0.4 for 40%)
max_height = 0.9,
min_height = { 5, 0.1 },
-- optionally define an integer/float for the exact height of the preview window
height = nil,
border = "rounded",
win_options = {
winblend = 0,
},
-- Whether the preview window is automatically updated when the cursor is moved
update_on_cursor_moved = true,
},
-- Configuration for the floating progress window
progress = {
max_width = 0.9,
min_width = { 40, 0.4 },
width = nil,
max_height = { 10, 0.9 },
min_height = { 5, 0.1 },
height = nil,
border = "rounded",
minimized_border = "none",
win_options = {
winblend = 0,
},
},
-- Configuration for the floating SSH window
ssh = {
border = "rounded",
},
},
dependencies = {
"nvim-tree/nvim-web-devicons",
},
config = function(_, opts)
require("oil").setup(opts)
-- Custom autocmds for Oil
vim.api.nvim_create_autocmd("FileType", {
pattern = "oil",
callback = function()
-- Set local options for oil buffers
vim.opt_local.colorcolumn = ""
vim.opt_local.signcolumn = "no"
-- Auto-save when leaving oil buffer with changes
vim.api.nvim_create_autocmd("BufLeave", {
buffer = 0,
callback = function()
if vim.bo.modified then
vim.cmd("silent! write")
end
end,
})
end,
})
-- Global keymap to open Oil in current buffer's directory
vim.keymap.set("n", "<leader>-", function()
local oil = require("oil")
local current_buf = vim.api.nvim_get_current_buf()
local current_file = vim.api.nvim_buf_get_name(current_buf)
if current_file and current_file ~= "" then
local dir = vim.fn.fnamemodify(current_file, ":h")
oil.open(dir)
else
oil.open()
end
end, { desc = "Open Oil in current file's directory" })
end,
}

View File

@@ -0,0 +1,117 @@
return {
"NickvanDyke/opencode.nvim",
dependencies = {
{ "folke/snacks.nvim", opts = { input = {}, picker = {}, terminal = {} } },
},
keys = {
{
"<leader>aa",
function()
require("opencode").toggle()
end,
mode = { "n" },
desc = "Toggle OpenCode",
},
{
"<leader>as",
function()
require("opencode").select({ submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode select",
},
{
"<leader>ai",
function()
require("opencode").ask("", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode ask",
},
{
"<leader>aI",
function()
require("opencode").ask("@this: ", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode ask with context",
},
{
"<leader>ab",
function()
require("opencode").ask("@file ", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode ask about buffer",
},
{
"<leader>ap",
function()
require("opencode").prompt("@this", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode prompt",
},
-- Built-in prompts
{
"<leader>ape",
function()
require("opencode").prompt("explain", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode explain",
},
{
"<leader>apf",
function()
require("opencode").prompt("fix", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode fix",
},
{
"<leader>apd",
function()
require("opencode").prompt("diagnose", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode diagnose",
},
{
"<leader>apr",
function()
require("opencode").prompt("review", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode review",
},
{
"<leader>apt",
function()
require("opencode").prompt("test", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode test",
},
{
"<leader>apo",
function()
require("opencode").prompt("optimize", { submit = true })
end,
mode = { "n", "x" },
desc = "OpenCode optimize",
},
},
config = function()
vim.g.opencode_opts = {
provider = {
snacks = {
win = {
position = "left",
},
},
},
}
vim.o.autoread = true
end,
}

View File

@@ -0,0 +1,55 @@
-- This file contains the configuration overrides for specific Neovim plugins.
return {
-- Change configuration for trouble.nvim
{
-- Plugin: trouble.nvim
-- URL: https://github.com/folke/trouble.nvim
-- Description: A pretty list for showing diagnostics, references, telescope results, quickfix and location lists.
"folke/trouble.nvim",
-- Options to be merged with the parent specification
opts = { use_diagnostic_signs = true }, -- Use diagnostic signs for trouble.nvim
},
-- Add symbols-outline.nvim plugin
{
-- Plugin: symbols-outline.nvim
-- URL: https://github.com/simrat39/symbols-outline.nvim
-- Description: A tree like view for symbols in Neovim using the Language Server Protocol.
"simrat39/symbols-outline.nvim",
cmd = "SymbolsOutline", -- Command to open the symbols outline
keys = { { "<leader>cs", "<cmd>SymbolsOutline<cr>", desc = "Symbols Outline" } }, -- Keybinding to open the symbols outline
config = true, -- Use default configuration
},
-- Remove inlay hints from default configuration
{
-- Plugin: nvim-lspconfig
-- URL: https://github.com/neovim/nvim-lspconfig
-- Description: Quickstart configurations for the Neovim LSP client.
"neovim/nvim-lspconfig",
event = "VeryLazy", -- Load this plugin on the 'VeryLazy' event
opts = {
inlay_hints = { enabled = false }, -- Disable inlay hints
servers = {
angularls = {
-- Configuration for Angular Language Server
root_dir = function(fname)
return require("lspconfig.util").root_pattern("angular.json", "project.json")(fname)
end,
},
nil_ls = {
-- Configuration for nil (Nix Language Server), already installed via nix
cmd = { "nil" },
autostart = true,
mason = false, -- Explicitly disable mason management for nil_ls
settings = {
["nil"] = {
formatting = { command = { "nixpkgs-fmt" } },
},
},
},
},
},
},
}

View File

@@ -0,0 +1,3 @@
return {
"tris203/precognition.nvim",
}

View File

@@ -0,0 +1,22 @@
-- This file contains the configuration for the nvim-rip-substitute plugin in Neovim.
return {
-- Plugin: nvim-rip-substitute
-- URL: https://github.com/chrisgrieser/nvim-rip-substitute
-- Description: A Neovim plugin for performing substitutions with ripgrep.
"chrisgrieser/nvim-rip-substitute",
cmd = "RipSubstitute", -- Command to trigger the plugin
keys = {
{
-- Keybinding to perform a ripgrep substitution
"<leader>fs",
function()
require("rip-substitute").sub() -- Call the substitution function from the plugin
end,
mode = { "n", "x" }, -- Enable the keybinding in normal and visual modes
desc = " rip substitute", -- Description for the keybinding
},
},
}

View File

@@ -0,0 +1,5 @@
return {
"NStefan002/screenkey.nvim",
lazy = false,
version = "*", -- or branch = "dev", to use the latest commit
}

View File

@@ -0,0 +1,4 @@
return {
"sphamba/smear-cursor.nvim",
opts = {},
}

View File

@@ -0,0 +1,8 @@
-- This file contains the configuration for the twilight.nvim plugin in Neovim.
return {
-- Plugin: twilight.nvim
-- URL: https://github.com/folke/twilight.nvim
-- Description: A Neovim plugin for dimming inactive portions of the code you're editing.
"folke/twilight.nvim",
}

View File

@@ -0,0 +1,281 @@
local mode = {
"mode",
fmt = function(s)
local mode_map = {
["NORMAL"] = "N",
["O-PENDING"] = "N?",
["INSERT"] = "I",
["VISUAL"] = "V",
["V-BLOCK"] = "VB",
["V-LINE"] = "VL",
["V-REPLACE"] = "VR",
["REPLACE"] = "R",
["COMMAND"] = "!",
["SHELL"] = "SH",
["TERMINAL"] = "T",
["EX"] = "X",
["S-BLOCK"] = "SB",
["S-LINE"] = "SL",
["SELECT"] = "S",
["CONFIRM"] = "Y?",
["MORE"] = "M",
}
return mode_map[s] or s
end,
}
local function codecompanion_adapter_name()
local chat = require("codecompanion").buf_get_chat(vim.api.nvim_get_current_buf())
if not chat then
return nil
end
return "" .. chat.adapter.formatted_name
end
local function codecompanion_current_model_name()
local chat = require("codecompanion").buf_get_chat(vim.api.nvim_get_current_buf())
if not chat then
return nil
end
return chat.settings.model
end
-- This file contains the configuration for various UI-related plugins in Neovim.
return {
-- Plugin: folke/todo-comments.nvim
-- URL: https://github.com/folke/todo-comments.nvim
-- Description: Plugin to highlight and search for TODO, FIX, HACK, etc. comments in your code.
-- IMPORTANT: using version "*" to fix a bug
{ "folke/todo-comments.nvim", version = "*" },
-- Plugin: folke/which-key.nvim
-- URL: https://github.com/folke/which-key.nvim
-- Description: Plugin to show a popup with available keybindings.
-- IMPORTANT: using event "VeryLazy" to optimize loading time
{
"folke/which-key.nvim",
event = "VeryLazy",
opts = {
preset = "classic",
win = { border = "single" },
},
},
-- Plugin: nvim-docs-view
-- URL: https://github.com/amrbashir/nvim-docs-view
-- Description: A Neovim plugin for viewing documentation.
{
"amrbashir/nvim-docs-view",
lazy = true, -- Load this plugin lazily
cmd = "DocsViewToggle", -- Command to toggle the documentation view
opts = {
position = "right", -- Position the documentation view on the right
width = 60, -- Set the width of the documentation view
},
},
-- Plugin: lualine.nvim
-- URL: https://github.com/nvim-lualine/lualine.nvim
-- Description: A blazing fast and easy to configure Neovim statusline plugin.
{
"nvim-lualine/lualine.nvim",
event = "VeryLazy", -- Load this plugin on the 'VeryLazy' event
requires = { "nvim-tree/nvim-web-devicons", opt = true }, -- Optional dependency for icons
opts = {
options = {
theme = "gentleman-kanagawa-blur", -- Set the theme for lualine
icons_enabled = true, -- Enable icons in the statusline
},
sections = {
lualine_a = {
{
"mode", -- Display the current mode
icon = "󱗞", -- Set the icon for the mode
},
},
},
extensions = {
"quickfix",
{
filetypes = { "oil" },
sections = {
lualine_a = {
mode,
},
lualine_b = {
function()
local ok, oil = pcall(require, "oil")
if not ok then
return ""
end
---@diagnostic disable-next-line: param-type-mismatch
local path = vim.fn.fnamemodify(oil.get_current_dir(), ":~")
return path .. " %m"
end,
},
},
},
{
filetypes = { "codecompanion" },
sections = {
lualine_a = {
mode,
},
lualine_b = {
codecompanion_adapter_name,
},
lualine_c = {
codecompanion_current_model_name,
},
lualine_x = {},
lualine_y = {
"progress",
},
lualine_z = {
"location",
},
},
inactive_sections = {
lualine_a = {},
lualine_b = {
codecompanion_adapter_name,
},
lualine_c = {},
lualine_x = {},
lualine_y = {
"progress",
},
lualine_z = {},
},
},
},
},
},
-- Plugin: incline.nvim
-- URL: https://github.com/b0o/incline.nvim
-- Description: A Neovim plugin for showing the current filename in a floating window.
{
"b0o/incline.nvim",
event = "BufReadPre", -- Load this plugin before reading a buffer
priority = 1200, -- Set the priority for loading this plugin
config = function()
require("incline").setup({
window = { margin = { vertical = 0, horizontal = 1 } }, -- Set the window margin
hide = {
cursorline = true, -- Hide the incline window when the cursorline is active
},
render = function(props)
local filename = vim.fn.fnamemodify(vim.api.nvim_buf_get_name(props.buf), ":t") -- Get the filename
if vim.bo[props.buf].modified then
filename = "[+] " .. filename -- Indicate if the file is modified
end
local icon, color = require("nvim-web-devicons").get_icon_color(filename) -- Get the icon and color for the file
return { { icon, guifg = color }, { " " }, { filename } } -- Return the rendered content
end,
})
end,
},
-- Plugin: zen-mode.nvim
-- URL: https://github.com/folke/zen-mode.nvim
-- Description: A Neovim plugin for distraction-free coding.
{
"folke/zen-mode.nvim",
cmd = "ZenMode", -- Command to toggle Zen Mode
opts = {
plugins = {
gitsigns = true, -- Enable gitsigns integration
tmux = true, -- Enable tmux integration
kitty = { enabled = false, font = "+2" }, -- Disable kitty integration and set font size
twilight = { enabled = true }, -- Enable twilight integration
},
},
keys = { { "<leader>z", "<cmd>ZenMode<cr>", desc = "Zen Mode" } }, -- Keybinding to toggle Zen Mode
},
-- Plugin: snacks.nvim
-- URL: https://github.com/folke/snacks.nvim/tree/main
-- Description: A Neovim plugin for creating a customizable dashboard.
{
"folke/snacks.nvim",
keys = {
{
"<leader>fb",
function()
Snacks.picker.buffers()
end,
desc = "Find Buffers",
},
},
opts = {
notifier = {},
image = {},
picker = {
exclude = {
".git",
"node_modules",
},
matcher = {
fuzzy = true,
smartcase = true,
ignorecase = true,
filename_bonus = true,
},
sources = {
-- explorer = {
-- matcher = {
-- fuzzy = true, -- Enables fuzzy matching, so you can be a bit imprecise with your search terms
-- smartcase = true, -- If your search term has uppercase letters, the search becomes case-sensitive
-- ignorecase = true, -- Ignores case when searching, unless smartcase is triggered
-- filename_bonus = true, -- Gives a higher priority to matches in filenames
-- sort_empty = false, -- If no matches are found, it won't sort the results
-- },
-- },
},
},
dashboard = {
sections = {
{ section = "header" },
{ icon = "", title = "Keymaps", section = "keys", indent = 2, padding = 1 },
{ icon = "", title = "Recent Files", section = "recent_files", indent = 2, padding = 1 },
{ icon = "", title = "Projects", section = "projects", indent = 2, padding = 1 },
{ section = "startup" },
},
preset = {
header = [[
░░░░░░ ░░░░░░
░░░░░░░░░░ ░░░░░░░░░░
░░░░░░░░░░░░░░░░░░░░░░░░░░
░░░░░░░░░░▒▒▒▒░░▒▒▒▒░░░░░░░░░░
░░░░ ░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░ ░░░░
▒▒░░ ░░░░░░▒▒▒▒▒▒▒▒▒▒██▒▒██▒▒▒▒▒▒▒▒▒▒░░░░░░ ▒▒░░
▒▒░░ ░░░░░░░░▒▒▒▒▒▒▒▒▒▒████▒▒████▒▒▒▒▒▒▒▒▒▒░░░░░░░░ ▒▒░░▒
▒▒▒▒░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒██████▒▒██████▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░▒▒▒
██▒▒▒▒▒▒▒▒▒▒▒▒▒▒██▒▒▒▒██████▓▓██▒▒██████▒▒▓▓██▒▒▒▒▒▒▒▒▒▒▒▒▒▒█
████▒▒▒▒▒▒████▒▒▒▒██████████ ██████████▒▒▒▒████▒▒▒▒▒▒▒▒██
████████████████████████ ████████████████████████
██████████████████ ██████████████████
██████████ ██████████
]],
-- stylua: ignore
---@type snacks.dashboard.Item[]
keys = {
{ icon = "", key = "f", desc = "Find File", action = ":lua Snacks.dashboard.pick('files')" },
{ icon = "", key = "n", desc = "New File", action = ":ene | startinsert" },
{ icon = "", key = "g", desc = "Find Text", action = ":lua Snacks.dashboard.pick('live_grep')" },
{ icon = "", key = "r", desc = "Recent Files", action = ":lua Snacks.dashboard.pick('oldfiles')" },
{ icon = "", key = "c", desc = "Config", action = ":lua Snacks.dashboard.pick('files', {cwd = vim.fn.stdpath('config')})" },
{ icon = "", key = "s", desc = "Restore Session", section = "session" },
{ icon = "", key = "x", desc = "Lazy Extras", action = ":LazyExtras" },
{ icon = "󰒲 ", key = "l", desc = "Lazy", action = ":Lazy" },
{ icon = "", key = "q", desc = "Quit", action = ":qa" },
},
},
},
},
},
}

View File

@@ -0,0 +1,8 @@
-- This file contains the configuration for the vim-be-good plugin in Neovim.
return {
-- Plugin: vim-be-good
-- URL: https://github.com/ThePrimeagen/vim-be-good
-- Description: A Neovim plugin designed to help you improve your Vim skills through various exercises and games.
"ThePrimeagen/vim-be-good",
}

View File

@@ -0,0 +1,8 @@
-- This file contains the configuration for the nvim-tmux-navigation plugin in Neovim.
return {
-- Plugin: nvim-tmux-navigation
-- URL: https://github.com/alexghergh/nvim-tmux-navigation
-- Description: A Neovim plugin that allows seamless navigation between Neovim and tmux panes.
"alexghergh/nvim-tmux-navigation",
}

View File

@@ -0,0 +1,31 @@
-- This file contains the configuration for the which-key.nvim plugin in Neovim.
return {
-- Plugin: which-key.nvim
-- URL: https://github.com/folke/which-key.nvim
-- Description: A Neovim plugin that displays a popup with possible keybindings of the command you started typing.
"folke/which-key.nvim",
event = "VeryLazy", -- Load this plugin on the 'VeryLazy' event
init = function()
-- Set the timeout for key sequences
vim.o.timeout = true
vim.o.timeoutlen = 300 -- Set the timeout length to 300 milliseconds
end,
keys = {
{
-- Keybinding to show which-key popup
"<leader>?",
function()
require("which-key").show({ global = false }) -- Show the which-key popup for local keybindings
end,
},
{
-- Define a group for Obsidian-related commands
"<leader>o",
group = "Obsidian",
},
},
}