473 lines
16 KiB
Lua
473 lines
16 KiB
Lua
-- 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
|
|
|
|
-- KEYMAPS SPIDER
|
|
vim.keymap.set({ "n", "o", "x" }, "w", "<cmd>lua require('spider').motion('w')<CR>", { desc = "Spider-w" })
|
|
vim.keymap.set({ "n", "o", "x" }, "e", "<cmd>lua require('spider').motion('e')<CR>", { desc = "Spider-e" })
|
|
vim.keymap.set({ "n", "o", "x" }, "b", "<cmd>lua require('spider').motion('b')<CR>", { desc = "Spider-b" })
|
|
vim.keymap.set({ "n", "o", "x" }, "C-D", "<PageDown>", { desc = "page down" })
|
|
|
|
local bm = require("bookmarks")
|
|
local map = vim.keymap.set
|
|
map("n", "<leader>mm", bm.bookmark_toggle, { desc = "Toggle bookmark" })
|
|
map("n", "<leader>mi", bm.bookmark_ann, { desc = "Edit annotation" })
|
|
map("n", "<leader>mc", bm.bookmark_clean, { desc = "Clean marks" })
|
|
map("n", "<leader>mn", bm.bookmark_next, { desc = "Next mark" })
|
|
map("n", "<leader>mp", bm.bookmark_prev, { desc = "Prev mark" })
|
|
map("n", "<leader>ml", "<cmd>Telescope bookmarks list<CR>", { desc = "List marks" })
|
|
map("n", "<leader>mx", bm.bookmark_clear_all, { desc = "Clear all bookmarks" })
|
|
map("n", "<leader>srf", function()
|
|
local file_path = vim.api.nvim_buf_get_name(0)
|
|
print(file_path)
|
|
require("grug-far").open({
|
|
transient = true,
|
|
prefills = {
|
|
paths = file_path,
|
|
},
|
|
})
|
|
end, { desc = "Search n replace in file" })
|
|
map("n", "<leader>ff", "<cmd>FzfLua<cr>", { desc = "FZF commands" })
|
|
-- tab to accept copilot suggestion
|
|
map("i", "<Tab>", function()
|
|
require("copilot.suggestion").accept()
|
|
end, { desc = "Accept Copilot suggestion" })
|
|
-- -- Terminal Mappings
|
|
-- map("t", "<C-/>", "<cmd>close<cr>", { desc = "Hide Terminal" })
|
|
-- map("t", "<c-_>", "<cmd>close<cr>", { desc = "which_key_ignore" })
|
|
map("n", "<leader>qw", "<cmd>wq<cr>", { desc = "save & quit" })
|
|
|
|
vim.keymap.set("n", "\\", function()
|
|
vim.cmd("!tmux-td")
|
|
end, { desc = "Toggle TD CLI floating terminal and run tmux-td" })
|
|
-- vim.keymap.set("t", "<C-\\>", "<cmd>ToggleTerm<cr>", { noremap = true, silent = true })
|
|
--
|
|
--
|
|
local harpoon = require("harpoon")
|
|
vim.keymap.set("n", "<leader>H", function()
|
|
harpoon:list("file_with_line"):add()
|
|
end, { desc = "Harpoon add" })
|
|
vim.keymap.set("n", "<leader>h", function()
|
|
harpoon.ui:toggle_quick_menu(harpoon:list("file_with_line"))
|
|
end, { desc = "Harpoon list" })
|
|
|
|
-- DIFFVIEW
|
|
local function diffOpenWithInput()
|
|
local user_input = vim.fn.input("Revision to Open: ")
|
|
vim.cmd("DiffviewOpen " .. user_input)
|
|
end
|
|
|
|
local function diffOpenFileHistory()
|
|
local user_input = vim.fn.input("Files to Open: ")
|
|
vim.cmd("DiffviewFileHistory" .. user_input)
|
|
end
|
|
local function command(cmd)
|
|
return function()
|
|
vim.cmd(cmd)
|
|
end
|
|
end
|
|
|
|
require("which-key").add({
|
|
{ "<leader>gvf", diffOpenFileHistory, desc = "Open DiffView on Files" },
|
|
{ "<leader>gvt", command("DiffviewToggleFiles"), desc = "toggle diffviewfiles" },
|
|
{ "<leader>gvc", command("DiffviewClose"), desc = "Open DiffView on Files" },
|
|
{
|
|
"<leader>gvh",
|
|
function()
|
|
print("gvf with . opens commit wise history of entire codebase.")
|
|
print("gvf with % opens commit wise history of current file.")
|
|
print("gvf with <any file path> opens commit wise history of that file.")
|
|
print("gvo with HEAD opens diff of latest commit.")
|
|
print("gvo with HEAD~3 opens diff of last 3 commits.")
|
|
print("gvo with master..HEAD opens changes of your feature branch.")
|
|
end,
|
|
desc = "gvo help",
|
|
},
|
|
{ "<leader>gvo", diffOpenWithInput, desc = "Open DiffView" },
|
|
})
|
|
--
|
|
--
|
|
vim.api.nvim_set_keymap("c", "<C-j>", "<Down>", { noremap = true, silent = true })
|
|
vim.api.nvim_set_keymap("c", "<C-k>", "<Up>", { noremap = true, silent = true })
|
|
print("dupsko")
|
|
-- exec lua
|
|
|
|
map("v", "<leader>ce", "<cmd>'<,'>lua<cr>", { desc = "exec Lua" })
|
|
|
|
-- GP
|
|
map("n", "<leader>agf", "<cmd>GpChatFinder<cr>", { desc = "gp chat finder" })
|
|
map("n", "<leader>agt", "<cmd>GpChatToggle<cr>", { desc = "gp chat toggle" })
|
|
map("n", "<leader>agn", "<cmd>GpChatNew<cr>", { desc = "gp chat new " })
|
|
map("n", "<leader>agr", "<cmd>GpChatRespond<cr>", { desc = "gp chat respond" })
|
|
|
|
-- JSON FORMAT
|
|
map("n", "<leader>cjf", "<cmd>%!jq .<cr>", { desc = "Json Format" })
|
|
vim.keymap.set("n", "s", "<Plug>(leap-anywhere)")
|
|
|
|
local function jump_to_file_line()
|
|
local line = vim.api.nvim_get_current_line()
|
|
local file, linenum = string.match(line, "([^:%s]+):(%d+)")
|
|
if file and linenum then
|
|
vim.cmd("edit " .. file)
|
|
vim.cmd(linenum)
|
|
else
|
|
print("No valid file:line pattern found on the current line.")
|
|
end
|
|
end
|
|
|
|
-- Map it to <leader>j (typically \j)
|
|
vim.keymap.set("n", "<leader>j", jump_to_file_line, { noremap = true, silent = true, desc = "Jump to file:line" })
|
|
|
|
-- Function to insert TODO comment with task number
|
|
function insert_todo_comment()
|
|
-- Get the current branch name
|
|
local handle = io.popen("git branch --show-current 2>/dev/null")
|
|
local branch
|
|
if handle then
|
|
branch = handle:read("*a"):match("%S+")
|
|
handle:close()
|
|
end
|
|
|
|
-- Extract the task number (e.g., HS-4798) from the branch name
|
|
local task_number = branch and branch:match("HS%-%d+")
|
|
|
|
-- If a task number is found, insert the TODO comment
|
|
if task_number then
|
|
local todo_comment = "# TODO: " .. task_number
|
|
vim.api.nvim_put({ todo_comment }, "l", true, true)
|
|
else
|
|
print("Task number not found in branch name!")
|
|
end
|
|
end
|
|
|
|
-- Keybind for inserting TODO comment
|
|
vim.api.nvim_set_keymap("n", "<leader>t", "<cmd>lua insert_todo_comment()<CR>", { noremap = true, silent = true })
|
|
|
|
local function git_output(args)
|
|
local output = vim.fn.system(args)
|
|
if vim.v.shell_error ~= 0 then
|
|
return nil
|
|
end
|
|
return vim.split(output, "\n", { trimempty = true })
|
|
end
|
|
|
|
local function branch_todos_base()
|
|
if vim.g.branch_todos_base then
|
|
return vim.g.branch_todos_base
|
|
end
|
|
|
|
for _, ref in ipairs({ "origin/main", "origin/master", "main", "master" }) do
|
|
if git_output({ "git", "rev-parse", "--verify", ref }) then
|
|
return ref
|
|
end
|
|
end
|
|
end
|
|
|
|
local function branch_todos_entries()
|
|
local base = branch_todos_base()
|
|
if not base then
|
|
return { "No git base found. Set vim.g.branch_todos_base." }
|
|
end
|
|
|
|
local merge_base = git_output({ "git", "merge-base", base, "HEAD" })
|
|
if not merge_base or not merge_base[1] then
|
|
return { "Could not find merge-base against " .. base .. "." }
|
|
end
|
|
|
|
local lines = git_output({ "git", "diff", "--unified=0", merge_base[1] })
|
|
if not lines then
|
|
return { "Could not read git diff against " .. base .. "." }
|
|
end
|
|
|
|
local added_lines = {}
|
|
local file
|
|
local new_line
|
|
local todo_keywords = { "TODO", "FIXME", "HACK", "XXX", "BUG", "BUGS" }
|
|
|
|
for _, line in ipairs(lines) do
|
|
local diff_file = line:match("^%+%+%+ b/(.+)$")
|
|
if diff_file then
|
|
file = diff_file
|
|
new_line = nil
|
|
else
|
|
local hunk_start = line:match("^@@ %-%d+,?%d* %+(%d+),?%d* @@")
|
|
if hunk_start then
|
|
new_line = tonumber(hunk_start)
|
|
elseif new_line and line:sub(1, 1) == "+" and not line:match("^%+%+%+") then
|
|
local text = line:sub(2)
|
|
if file then
|
|
table.insert(added_lines, { file = file, line = new_line, text = text })
|
|
end
|
|
new_line = new_line + 1
|
|
elseif new_line and line:sub(1, 1) ~= "-" then
|
|
new_line = new_line + 1
|
|
end
|
|
end
|
|
end
|
|
|
|
local function has_todo_keyword(text)
|
|
local upper_text = text:upper()
|
|
for _, keyword in ipairs(todo_keywords) do
|
|
local start = 1
|
|
while true do
|
|
local match_start, match_end = upper_text:find(keyword, start, true)
|
|
if not match_start then
|
|
break
|
|
end
|
|
|
|
local before = match_start > 1 and upper_text:sub(match_start - 1, match_start - 1) or ""
|
|
local after = match_end < #upper_text and upper_text:sub(match_end + 1, match_end + 1) or ""
|
|
if not before:match("[%w_]") and not after:match("[%w_]") then
|
|
return true
|
|
end
|
|
|
|
start = match_end + 1
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function list_depth_delta(text)
|
|
local _, opens = text:gsub("%[", "")
|
|
local _, closes = text:gsub("%]", "")
|
|
return opens - closes
|
|
end
|
|
|
|
local entries = {}
|
|
local index = 1
|
|
while index <= #added_lines do
|
|
local item = added_lines[index]
|
|
if has_todo_keyword(item.text) then
|
|
table.insert(entries, string.format("%s:%d", item.file, item.line))
|
|
table.insert(entries, item.text)
|
|
|
|
if item.text:lower():match('todo:%s*"""') and not item.text:match('""".*"""') then
|
|
index = index + 1
|
|
while index <= #added_lines do
|
|
local next_item = added_lines[index]
|
|
if next_item.file ~= item.file then
|
|
break
|
|
end
|
|
table.insert(entries, next_item.text)
|
|
if next_item.text:find('"""', 1, true) then
|
|
break
|
|
end
|
|
index = index + 1
|
|
end
|
|
elseif item.text:match("[=:]%s*%[") and list_depth_delta(item.text) > 0 then
|
|
local depth = list_depth_delta(item.text)
|
|
index = index + 1
|
|
while index <= #added_lines do
|
|
local next_item = added_lines[index]
|
|
if next_item.file ~= item.file then
|
|
break
|
|
end
|
|
|
|
table.insert(entries, next_item.text)
|
|
depth = depth + list_depth_delta(next_item.text)
|
|
if depth <= 0 then
|
|
break
|
|
end
|
|
|
|
index = index + 1
|
|
end
|
|
elseif item.text:match("^%s*#") then
|
|
index = index + 1
|
|
while index <= #added_lines do
|
|
local next_item = added_lines[index]
|
|
if next_item.file ~= item.file or not next_item.text:match("^%s*#") then
|
|
break
|
|
end
|
|
table.insert(entries, next_item.text)
|
|
index = index + 1
|
|
end
|
|
index = index - 1
|
|
end
|
|
|
|
table.insert(entries, "")
|
|
end
|
|
|
|
index = index + 1
|
|
end
|
|
|
|
if #entries == 0 then
|
|
return { "No TODOs added on this branch against " .. base .. "." }
|
|
end
|
|
|
|
return entries
|
|
end
|
|
|
|
local function jump_to_branch_todo()
|
|
local line = vim.api.nvim_get_current_line()
|
|
local file, linenum = line:match("([^:%s]+):(%d+)")
|
|
if not file then
|
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
|
for row = cursor[1] - 1, 1, -1 do
|
|
local previous_line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1] or ""
|
|
file, linenum = previous_line:match("([^:%s]+):(%d+)")
|
|
if file then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
if file and linenum then
|
|
local current_win = vim.api.nvim_get_current_win()
|
|
vim.cmd("wincmd h")
|
|
if current_win == vim.api.nvim_get_current_win() then
|
|
vim.api.nvim_set_current_win(current_win)
|
|
end
|
|
|
|
vim.cmd("edit " .. vim.fn.fnameescape(file))
|
|
vim.api.nvim_win_set_cursor(0, { tonumber(linenum), 0 })
|
|
if vim.api.nvim_win_is_valid(current_win) and current_win ~= vim.api.nvim_get_current_win() then
|
|
vim.api.nvim_set_current_win(current_win)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function refresh_branch_todos(buf)
|
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
|
vim.bo[buf].modifiable = true
|
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, branch_todos_entries())
|
|
vim.bo[buf].modifiable = false
|
|
|
|
local line_count = vim.api.nvim_buf_line_count(buf)
|
|
vim.api.nvim_win_set_cursor(0, { math.min(cursor[1], line_count), cursor[2] })
|
|
end
|
|
|
|
local function open_branch_todos()
|
|
local name = "branch-todos"
|
|
local buf = vim.fn.bufnr(name)
|
|
if buf == -1 then
|
|
buf = vim.api.nvim_create_buf(true, false)
|
|
vim.api.nvim_buf_set_name(buf, name)
|
|
end
|
|
|
|
vim.api.nvim_set_current_buf(buf)
|
|
vim.bo[buf].buftype = "nofile"
|
|
vim.bo[buf].bufhidden = "hide"
|
|
vim.bo[buf].swapfile = false
|
|
vim.bo[buf].filetype = "branch-todos"
|
|
|
|
refresh_branch_todos(buf)
|
|
|
|
vim.keymap.set("n", "<CR>", jump_to_branch_todo, { buffer = buf, desc = "Jump to branch TODO" })
|
|
vim.keymap.set("n", "r", function()
|
|
refresh_branch_todos(buf)
|
|
end, { buffer = buf, desc = "Refresh branch TODOs" })
|
|
vim.keymap.set("n", "q", "<cmd>bdelete<CR>", { buffer = buf, desc = "Close branch TODOs" })
|
|
end
|
|
|
|
vim.api.nvim_create_user_command("BranchTodos", open_branch_todos, {})
|
|
vim.keymap.set("n", "<leader>xb", open_branch_todos, { desc = "Branch TODOs" })
|
|
|
|
-- floating NOTES
|
|
function open_notes()
|
|
local notes_file = vim.env.HOME .. "/git/notes/todo.md" -- Path to your notes file
|
|
|
|
-- Check if the file exists, create it if not
|
|
if vim.fn.filereadable(notes_file) == 0 then
|
|
vim.fn.writefile({}, notes_file) -- Create an empty file
|
|
end
|
|
|
|
-- Create a buffer linked to the notes file
|
|
local buf = vim.fn.bufadd(notes_file)
|
|
vim.fn.bufload(buf)
|
|
|
|
-- Configure floating window size and position
|
|
local width = math.floor(vim.o.columns * 0.8) -- 80% of the screen width
|
|
local height = math.floor(vim.o.lines * 0.8) -- 80% of the screen height
|
|
local row = math.floor((vim.o.lines - height) / 2) -- Center the window vertically
|
|
local col = math.floor((vim.o.columns - width) / 2) -- Center the window horizontally
|
|
|
|
-- Create the window
|
|
local win = vim.api.nvim_open_win(buf, true, {
|
|
relative = "editor",
|
|
width = width,
|
|
height = height,
|
|
row = row,
|
|
col = col,
|
|
style = "minimal",
|
|
border = "rounded",
|
|
})
|
|
|
|
-- Enable saving and other standard buffer options
|
|
vim.api.nvim_buf_set_option(buf, "modifiable", true)
|
|
vim.api.nvim_buf_set_option(buf, "buftype", "")
|
|
vim.api.nvim_buf_set_option(buf, "filetype", "markdown")
|
|
-- vim.api.nvim_buf_set_option(buf, "fil", "text")
|
|
-- Scroll to the end of the file
|
|
local last_line = vim.api.nvim_buf_line_count(buf)
|
|
vim.api.nvim_win_set_cursor(win, { last_line, 0 })
|
|
|
|
-- Close the popup with 'q'
|
|
vim.api.nvim_buf_set_keymap(
|
|
buf,
|
|
"n",
|
|
"q",
|
|
"<cmd>lua vim.api.nvim_win_close(" .. win .. ", true)<CR>",
|
|
{ noremap = true, silent = true }
|
|
)
|
|
end
|
|
|
|
-- Keybind for opening the notes file in a floating window
|
|
vim.api.nvim_set_keymap("n", "<leader>n", "<cmd>lua open_notes()<CR>", { noremap = false, silent = true })
|
|
|
|
-- Define the function to start the timer
|
|
function start_timer(duration)
|
|
local timer = vim.loop.new_timer()
|
|
timer:start(
|
|
duration * 60000,
|
|
0,
|
|
vim.schedule_wrap(function()
|
|
vim.api.nvim_out_write("Time's up!\n")
|
|
|
|
os.execute('osascript -e "display notification \\"Times up\\" with title \\"Timer"" ')
|
|
end)
|
|
)
|
|
end
|
|
|
|
-- Define the function to prompt the user for the desired time using fzf-lua
|
|
function choose_timer()
|
|
local times = { 1, 3, 5, 10 }
|
|
require("fzf-lua").fzf_exec(times, {
|
|
prompt = "Choose timer duration (minutes): ",
|
|
actions = {
|
|
["default"] = function(selected)
|
|
local duration = tonumber(selected[1])
|
|
if duration then
|
|
start_timer(duration)
|
|
else
|
|
vim.api.nvim_out_write("Invalid choice. Please choose a valid duration.\n")
|
|
end
|
|
end,
|
|
},
|
|
})
|
|
end
|
|
|
|
vim.api.nvim_set_keymap("n", "<leader>T", "<cmd>lua choose_timer()<CR>", { noremap = true, silent = true })
|
|
|
|
-- Remap arrow keys to hjkl in Normal and Visual modes
|
|
vim.keymap.set({ "n", "v" }, "<Up>", "k", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<Down>", "j", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<Left>", "h", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<Right>", "l", { noremap = true, silent = true })
|
|
|
|
vim.keymap.set({ "n", "v" }, "<C-Up>", "k", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<C-Down>", "j", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<C-Left>", "h", { noremap = true, silent = true })
|
|
vim.keymap.set({ "n", "v" }, "<C-Right>", "l", { noremap = true, silent = true })
|
|
|
|
-- map leader u v c to CsvViewEnable display_mode=border with description `CSV View (commas)`
|
|
vim.keymap.set("n", "<leader>uvc", "<cmd>CsvViewEnable display_mode=border<CR>", { desc = "CSV View (commas)" })
|
|
-- map leader u v t to CsvViewEnable delimiter=\t display_mode=border with description `CSV View (tabs)`
|
|
vim.keymap.set(
|
|
"n",
|
|
"<leader>uvt",
|
|
"<cmd>CsvViewEnable delimiter=\\t display_mode=border<CR>",
|
|
{ desc = "CSV View (tabs)" }
|
|
)
|
|
-- map leader u v d to CsvViewDisable with description `CSV View Disable`
|
|
vim.keymap.set("n", "<leader>uvd", "<cmd>CsvViewDisable<CR>", { desc = "CSV View Disable" })
|