From e50f7f0b43946c434358facecf34e821ed203e7d Mon Sep 17 00:00:00 2001 From: "borja (aider)" Date: Wed, 30 Apr 2025 15:56:04 +0200 Subject: [PATCH] refactor: replace feedkeys with direct buffer operations for tab indentation --- lua/todoer/init.lua | 72 ++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/lua/todoer/init.lua b/lua/todoer/init.lua index 9f1c2d9..97aac04 100644 --- a/lua/todoer/init.lua +++ b/lua/todoer/init.lua @@ -70,6 +70,13 @@ local function get_line_details(lnum) end +-- Helper: Creates proper indent string based on buffer settings +local function get_indent_string() + local sw = vim.bo.shiftwidth + local et = vim.bo.expandtab + return et and string.rep(" ", sw) or "\t" +end + -- Helper: Gets details for the current line including cursor position local function get_current_line_details_with_cursor() local cursor_pos = vim.api.nvim_win_get_cursor(0) @@ -266,35 +273,46 @@ local function setup_buffer_keymaps() end end - -- indent line if tab is pressed when line is a todo (Will be refactored in Step 4) - local function press_tab() - local current_line = vim.api.nvim_get_current_line() - -- Updated pattern to match -, *, + markers - local pattern = "^%s*[%-%*%+]%s+%[[ x]%]" - if string.match(current_line, pattern) then - -- Still using feedkeys for now, will be refactored later - vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("", true, false, true), "i", false) - return "" -- Action handled by feedkeys - else - -- Return to allow default behavior + -- Handle tab indentation for TODO lines + local function press_tab() + local details = get_line_details(vim.api.nvim_win_get_cursor(0)[1]) + if not details or not details.is_todo then return vim.api.nvim_replace_termcodes("", true, false, true) end - end - -- indent line if shift tab is pressed when line is a todo (Will be refactored in Step 4) - local function press_shift_tab() - local current_line = vim.api.nvim_get_current_line() - -- Updated pattern to match -, *, + markers - local pattern = "^%s*[%-%*%+]%s+%[[ x]%]" - if string.match(current_line, pattern) then - -- Still using feedkeys for now, will be refactored later - vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("", true, false, true), "i", false) - return "" -- Action handled by feedkeys - else - -- Return to allow default behavior + local indent_str = get_indent_string() + local new_line = details.indent .. indent_str .. + (details.marker or "-") .. " [ ] " .. details.content + vim.api.nvim_set_current_line(new_line) + + -- Calculate new cursor column (preserve relative position) + local cursor_col = vim.api.nvim_win_get_cursor(0)[2] + local new_col = cursor_col + #indent_str + vim.api.nvim_win_set_cursor(0, {vim.api.nvim_win_get_cursor(0)[1], new_col}) + + return "" -- Prevent default behavior + end + + -- Handle shift-tab outdentation for TODO lines + local function press_shift_tab() + local details = get_line_details(vim.api.nvim_win_get_cursor(0)[1]) + if not details or not details.is_todo or #details.indent == 0 then return vim.api.nvim_replace_termcodes("", true, false, true) end - end + + local sw = vim.bo.shiftwidth + local new_indent = details.indent:sub(1, -sw - 1) + local new_line = new_indent .. + (details.marker or "-") .. " [ ] " .. details.content + vim.api.nvim_set_current_line(new_line) + + -- Calculate new cursor column (preserve relative position) + local cursor_col = vim.api.nvim_win_get_cursor(0)[2] + local new_col = math.max(0, cursor_col - sw) + vim.api.nvim_win_set_cursor(0, {vim.api.nvim_win_get_cursor(0)[1], new_col}) + + return "" -- Prevent default behavior + end -- Toggles the checkbox [ ] <-> [x] for lines starting with -, *, +, or # local function toggle_todo() @@ -322,9 +340,9 @@ local function setup_buffer_keymaps() vim.keymap.set("n", "t", function() end, { desc = "+TODOs", buffer = 0 }) -- Placeholder -- Keep mapping without expr = true vim.keymap.set("i", "", press_enter, { desc = "Todoer: Handle Enter", buffer = 0 }) - -- Keep expr = true for Tab/S-Tab for now, until they are refactored - vim.keymap.set("i", "", press_tab, { desc = "Todoer: Handle Tab", expr = true, buffer = 0 }) - vim.keymap.set("i", "", press_shift_tab, { desc = "Todoer: Handle Shift-Tab", expr = true, buffer = 0 }) + -- Tab handling for TODO items + vim.keymap.set("i", "", press_tab, { desc = "Todoer: Handle Tab", buffer = 0 }) + vim.keymap.set("i", "", press_shift_tab, { desc = "Todoer: Handle Shift-Tab", buffer = 0 }) vim.keymap.set("n", "tt", toggle_todo, { desc = "Todoer: Toggle TODO", buffer = 0 }) -- New mappings for adding TODOs vim.keymap.set("n", "ti", add_todo_insert_mode, { desc = "Todoer: Add TODO (cursor after marker)", buffer = 0, silent = true })