diff --git a/lazy-lock.json b/lazy-lock.json index 708d9fd..565e269 100644 --- a/lazy-lock.json +++ b/lazy-lock.json @@ -22,6 +22,7 @@ "nvim-dap": { "branch": "master", "commit": "7891b01beedc37cef4eaf2e92563bd0a5b6e9c58" }, "nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" }, "nvim-lspconfig": { "branch": "master", "commit": "a3deebbd110016f50cc66b7b256120072f3804db" }, + "nvim-notify": { "branch": "master", "commit": "8701bece920b38ea289b457f902e2ad184131a5d" }, "nvim-tree.lua": { "branch": "master", "commit": "fefa335f1c8f690eb668a1efd18ee4fc6d64cd3e" }, "nvim-treesitter": { "branch": "master", "commit": "42fc28ba918343ebfd5565147a42a26580579482" }, "nvim-web-devicons": { "branch": "master", "commit": "f66cdfef5e84112045b9ebc3119fee9bddb3c687" }, diff --git a/lua/custom/chadrc.lua b/lua/custom/chadrc.lua index e1673c1..92e3002 100644 --- a/lua/custom/chadrc.lua +++ b/lua/custom/chadrc.lua @@ -7,8 +7,8 @@ M.ui = { hl_add = {}, hl_override = {}, changed_themes = {}, - theme_toggle = { "falcon", "one_light" }, - theme = "falcon", -- default theme + theme_toggle = { "tokyodark", "one_light" }, + theme = "tokyodark", -- default theme transparency = false, lsp_semantic_tokens = false, -- needs nvim v0.9, just adds highlight groups for lsp semantic tokens diff --git a/lua/custom/plugins.lua b/lua/custom/plugins.lua index 440f786..8f413a8 100644 --- a/lua/custom/plugins.lua +++ b/lua/custom/plugins.lua @@ -108,7 +108,7 @@ local plugins = { lazy = false, keys = { -- Will use Telescope if installed or a vim.ui.select picker otherwise - { "fs", "SessionSearch", desc = "Session search" }, + { "fs", "AutoSession search", desc = "Session search" }, { "ws", function() @@ -118,14 +118,14 @@ local plugins = { -- optionally check if the user provided something if session_name ~= nil and session_name ~= "" then -- construct the command with the chosen name - vim.cmd("SessionSave " .. session_name) + vim.cmd("AutoSession save " .. session_name) else print "No session name given. Session not saved." end end, desc = "Save session (prompts for name)", }, - { "wa", "SessionToggleAutoSave", desc = "Toggle autosave" }, + { "wa", "AutoSession ToggleAutoSave", desc = "Toggle autosave" }, }, ---enables autocomplete for opts ---@module "auto-session" @@ -195,6 +195,13 @@ local plugins = { lazy = true, ft = { "markdown", "tex" }, -- load only when editing Markdown/TeX }, + { + "rcarriga/nvim-notify", + lazy = false, + config = function() + vim.notify = require "notify" + end, + }, } return plugins diff --git a/lua/custom/taskwarrior.lua b/lua/custom/taskwarrior.lua index 289ddeb..23e5ac3 100644 --- a/lua/custom/taskwarrior.lua +++ b/lua/custom/taskwarrior.lua @@ -1,31 +1,89 @@ --- Taskwarrior integration for Neovim +-- Taskwarrior integration for Neovim with clean notifications -- Add this to your ~/.config/nvim/init.lua or create a separate plugin file +-- Helper function for clean error handling with notifications +local function run_task_command(cmd, success_msg, error_prefix) + local result = vim.fn.system(cmd) + if vim.v.shell_error == 0 then + if success_msg then + vim.notify(success_msg, vim.log.levels.INFO) + end + return true, result + else + vim.notify((error_prefix or "Error") .. ": " .. vim.trim(result), vim.log.levels.ERROR) + return false, result + end +end + -- Basic task management commands vim.api.nvim_create_user_command("TaskAdd", function(opts) local task_desc = opts.args if task_desc == "" then task_desc = vim.fn.input "Task description: " end - vim.fn.system("task add " .. vim.fn.shellescape(task_desc)) - print("Task added: " .. task_desc) + if task_desc ~= "" then + run_task_command("task add " .. task_desc, "Task added successfully", "Error adding task") + end end, { nargs = "*", desc = "Add a new task" }) vim.api.nvim_create_user_command("TaskList", function() - local output = vim.fn.system "task list" - vim.cmd "new" - vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n")) - vim.bo.buftype = "nofile" - vim.bo.bufhidden = "wipe" - vim.bo.modifiable = false - vim.wo.number = false - vim.wo.relativenumber = false -end, { desc = "Show task list in new buffer" }) + local success, output = run_task_command("task list", nil, "Error listing tasks") + if success then + vim.cmd "new" + vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n")) + vim.bo.buftype = "nofile" + vim.bo.bufhidden = "wipe" + vim.bo.modifiable = false + vim.wo.number = false + vim.wo.relativenumber = false + -- Set a descriptive buffer name + vim.api.nvim_buf_set_name(0, "TaskWarrior List (All)") + end +end, { desc = "Show all pending tasks in new buffer" }) vim.api.nvim_create_user_command("TaskNext", function() - local output = vim.fn.system "task next" - print(vim.trim(output)) -end, { desc = "Show next tasks" }) + local success, output = run_task_command("task next limit:10", nil, "Error getting next tasks") + if success then + local lines = vim.split(vim.trim(output), "\n") + -- Filter out empty lines + local clean_lines = {} + for _, line in ipairs(lines) do + if line ~= "" and not line:match "^%s*$" then + table.insert(clean_lines, line) + end + end + + if #clean_lines > 0 then + -- Create floating window for next tasks + local width = math.min(math.max(80, vim.o.columns - 20), 120) + local height = math.min(#clean_lines + 2, 25) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) + + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(buf, 0, -1, false, clean_lines) + + local opts = { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded", + title = " Next Tasks ", + title_pos = "center", + } + + vim.api.nvim_open_win(buf, true, opts) + vim.bo[buf].modifiable = false + vim.keymap.set("n", "q", "close", { buffer = buf }) + vim.keymap.set("n", "", "close", { buffer = buf }) + else + vim.notify("No pending tasks", vim.log.levels.WARN) + end + end +end, { desc = "Show next 10 highest priority tasks in floating window" }) vim.api.nvim_create_user_command("TaskEdit", function(opts) local task_id = opts.args @@ -33,8 +91,7 @@ vim.api.nvim_create_user_command("TaskEdit", function(opts) task_id = vim.fn.input "Task ID to edit: " end if task_id ~= "" then - vim.fn.system("task " .. task_id .. " edit") - print("Edited task " .. task_id) + run_task_command("task " .. task_id .. " edit", "Edited task " .. task_id, "Error editing task") end end, { nargs = "?", desc = "Edit a task by ID" }) @@ -44,8 +101,7 @@ vim.api.nvim_create_user_command("TaskDone", function(opts) task_id = vim.fn.input "Task ID to complete: " end if task_id ~= "" then - vim.fn.system("task " .. task_id .. " done") - print("Task " .. task_id .. " completed!") + run_task_command("task " .. task_id .. " done", "Task " .. task_id .. " completed!", "Error completing task") end end, { nargs = "?", desc = "Mark task as done" }) @@ -55,30 +111,85 @@ vim.api.nvim_create_user_command("TaskModify", function(opts) local task_id = vim.fn.input "Task ID: " local modification = vim.fn.input "Modification (e.g., 'priority:H', '+urgent'): " if task_id ~= "" and modification ~= "" then - vim.fn.system("task " .. task_id .. " modify " .. modification) - print("Modified task " .. task_id) + run_task_command( + "task " .. task_id .. " modify " .. modification, + "Modified task " .. task_id, + "Error modifying task" + ) end else local task_id = args[1] local modification = table.concat(args, " ", 2) - vim.fn.system("task " .. task_id .. " modify " .. modification) - print("Modified task " .. task_id .. " with: " .. modification) + run_task_command( + "task " .. task_id .. " modify " .. modification, + "Modified task " .. task_id, + "Error modifying task" + ) end end, { nargs = "*", desc = "Modify a task" }) +vim.api.nvim_create_user_command("TaskStart", function(opts) + local task_id = opts.args + if task_id == "" then + task_id = vim.fn.input "Task ID to start: " + end + if task_id ~= "" then + run_task_command("task " .. task_id .. " start", "Started task " .. task_id, "Error starting task") + end +end, { nargs = "?", desc = "Start working on a task" }) + +vim.api.nvim_create_user_command("TaskStop", function(opts) + local task_id = opts.args + if task_id == "" then + -- If no ID provided, stop the active task + local success, active_output = run_task_command("task +ACTIVE ids", nil, "Error finding active tasks") + if success then + local active_id = vim.trim(active_output) + if active_id ~= "" then + run_task_command("task " .. active_id .. " stop", "Stopped active task " .. active_id, "Error stopping task") + else + vim.notify("No active task to stop", vim.log.levels.WARN) + end + end + else + run_task_command("task " .. task_id .. " stop", "Stopped task " .. task_id, "Error stopping task") + end +end, { nargs = "?", desc = "Stop working on a task" }) + +vim.api.nvim_create_user_command("TaskActive", function() + local success, output = run_task_command("task +ACTIVE list", nil, "Error getting active tasks") + if success then + if vim.trim(output) == "" or output:match "No matches" then + vim.notify("No active tasks", vim.log.levels.WARN) + else + vim.cmd "new" + vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n")) + vim.bo.buftype = "nofile" + vim.bo.bufhidden = "wipe" + vim.bo.modifiable = false + vim.wo.number = false + vim.wo.relativenumber = false + end + end +end, { desc = "Show active tasks" }) + -- Project and context commands vim.api.nvim_create_user_command("TaskProject", function(opts) local project = opts.args if project == "" then - local output = vim.fn.system "task projects" - print(output) + local success, output = run_task_command("task projects", nil, "Error listing projects") + if success then + vim.notify(output, vim.log.levels.INFO) + end else - local output = vim.fn.system("task project:" .. project .. " list") - vim.cmd "new" - vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n")) - vim.bo.buftype = "nofile" - vim.bo.bufhidden = "wipe" - vim.bo.modifiable = false + local success, output = run_task_command("task project:" .. project .. " list", nil, "Error filtering by project") + if success then + vim.cmd "new" + vim.api.nvim_buf_set_lines(0, 0, -1, false, vim.split(output, "\n")) + vim.bo.buftype = "nofile" + vim.bo.bufhidden = "wipe" + vim.bo.modifiable = false + end end end, { nargs = "?", desc = "Show projects or filter by project" }) @@ -88,14 +199,15 @@ vim.keymap.set("v", "ta", function() local end_pos = vim.fn.getpos "'>" local lines = vim.api.nvim_buf_get_lines(0, start_pos[2] - 1, end_pos[2], false) local selected_text = table.concat(lines, " "):gsub("%s+", " ") - vim.fn.system("task add " .. vim.fn.shellescape(selected_text)) - print("Task added from selection: " .. selected_text) + if selected_text ~= "" then + run_task_command("task add " .. selected_text, "Task added from selection", "Error adding task from selection") + end end, { desc = "Add task from visual selection" }) -- Key mappings (using t prefix for taskwarrior) vim.keymap.set("n", "ta", ":TaskAdd", { desc = "Add task" }) -vim.keymap.set("n", "tl", ":TaskList", { desc = "List tasks" }) -vim.keymap.set("n", "tn", ":TaskNext", { desc = "Show next tasks" }) +vim.keymap.set("n", "tl", ":TaskList", { desc = "List all tasks" }) +vim.keymap.set("n", "tn", ":TaskNext", { desc = "Show next 10 tasks" }) vim.keymap.set("n", "te", ":TaskEdit", { desc = "Edit task" }) vim.keymap.set("n", "td", ":TaskDone", { desc = "Mark task done" }) vim.keymap.set("n", "tm", ":TaskModify", { desc = "Modify task" }) @@ -108,50 +220,61 @@ vim.keymap.set("n", "tA", ":TaskActive", { desc = "Show active tasks vim.keymap.set("n", "tH", function() local task_id = vim.fn.input "Task ID for high priority: " if task_id ~= "" then - vim.fn.system("task " .. task_id .. " modify priority:H") - print("Set task " .. task_id .. " to high priority") + run_task_command( + "task " .. task_id .. " modify priority:H", + "Set task " .. task_id .. " to high priority", + "Error setting priority" + ) end end, { desc = "Set task to high priority" }) vim.keymap.set("n", "tu", function() local task_id = vim.fn.input "Task ID to add urgent tag: " if task_id ~= "" then - vim.fn.system("task " .. task_id .. " modify +urgent") - print("Added urgent tag to task " .. task_id) + run_task_command( + "task " .. task_id .. " modify +urgent", + "Added urgent tag to task " .. task_id, + "Error adding urgent tag" + ) end end, { desc = "Add urgent tag to task" }) --- Show task summary in statusline or floating window +-- Show task summary in floating window vim.api.nvim_create_user_command("TaskSummary", function() - local output = vim.fn.system "task summary" - local lines = vim.split(output, "\n") + local success, output = run_task_command("task summary", nil, "Error getting task summary") + if success then + local lines = vim.split(output, "\n") - -- Create floating window - local width = 60 - local height = #lines + 2 - local row = math.floor((vim.o.lines - height) / 2) - local col = math.floor((vim.o.columns - width) / 2) + -- Create floating window + local width = 60 + local height = math.min(#lines + 2, 20) + local row = math.floor((vim.o.lines - height) / 2) + local col = math.floor((vim.o.columns - width) / 2) - local buf = vim.api.nvim_create_buf(false, true) - vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines) - local opts = { - relative = "editor", - width = width, - height = height, - row = row, - col = col, - style = "minimal", - border = "rounded", - title = " Task Summary ", - title_pos = "center", - } + local opts = { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = "rounded", + title = " Task Summary ", + title_pos = "center", + } - vim.api.nvim_open_win(buf, true, opts) - vim.bo[buf].modifiable = false - vim.keymap.set("n", "q", "close", { buffer = buf }) + vim.api.nvim_open_win(buf, true, opts) + vim.bo[buf].modifiable = false + vim.keymap.set("n", "q", "close", { buffer = buf }) + end end, { desc = "Show task summary in floating window" }) vim.keymap.set("n", "ts", ":TaskSummary", { desc = "Show task summary" }) -print "Taskwarrior integration loaded! Use t* commands or :Task* commands" +-- Use a timer to show the load message after everything initializes +vim.defer_fn(function() + vim.notify("Taskwarrior integration loaded! Use t* commands", vim.log.levels.INFO) +end, 100)