|  |  | @ -6,137 +6,193 @@ local defaults = { | 
			
		
	
		
		
			
				
					
					|  |  |  | 	filetypes = { "markdown", "text", "norg" }, -- Filetypes to activate the plugin for |  |  |  | 	filetypes = { "markdown", "text", "norg" }, -- Filetypes to activate the plugin for | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- Helper: Parses line details for a given line number (1-based) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- Returns table: { line = str, indent = str, marker = str|nil, content = str, is_todo = bool } or nil | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | local function get_line_details(lnum) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   -- Use nvim_buf_get_lines which is 0-indexed for ranges | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local lines = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, false) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if not lines or #lines == 0 then return nil end -- Handle potential errors getting line | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local line = lines[1] | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local indent = string.match(line, "^%s*") or "" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   -- Pattern captures marker '-', '*', or '+' followed by at least one space | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   -- Returns: indent, marker, space_after_marker | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local marker_pattern = "^(%s*)([%-%*%+])(%s+)" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   -- Pattern captures marker, checkbox '[ ]' or '[x]', and optional space after checkbox | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local todo_pattern = "^%s*[%-%*%+]%s+%[([ x])%]%s*" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local _, marker_match, _ = string.match(line, marker_pattern) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local is_todo = (string.match(line, todo_pattern) ~= nil) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   local content = "" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if is_todo then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Content is everything after "[x] " or "[ ] " (including leading space) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     content = string.match(line, todo_pattern .. "(.*)") or "" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   elseif marker_match then | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Content is everything after "- " / "* " / "+ " | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     content = string.match(line, marker_pattern .. "(.*)") or "" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- No list marker, just the trimmed line content | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     content = vim.trim(line) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     line = line, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     indent = indent, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     marker = marker_match, -- '-', '*', '+', or nil | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     content = content, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     is_todo = is_todo, | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- Helper: Gets details for the current line | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | local function get_current_line_details() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local cursor_pos = vim.api.nvim_win_get_cursor(0) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local lnum = cursor_pos[1] -- 1-based line number | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     return get_line_details(lnum), lnum | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- <leader>ti: Convert line to TODO, cursor after "] " (Normal mode) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | local function add_todo_insert_mode() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local details, lnum = get_current_line_details() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Don't convert if already a TODO or if getting details failed | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if not details or details.is_todo then return end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local use_marker = details.marker or "-" -- Default to '-' if no list marker found | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local text_content = details.content -- Content already extracted correctly by get_line_details | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local new_line = details.indent .. use_marker .. " [ ] " .. text_content | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Replace current line (lnum is 1-based, set_lines is 0-based) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_buf_set_lines(0, lnum - 1, lnum, false, { new_line }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Set cursor position: 1-based row, 0-based byte column | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Position cursor right after the "] " | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local cursor_col_bytes = vim.fn.strbytes(details.indent .. use_marker .. " [ ] ") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_win_set_cursor(0, { lnum, cursor_col_bytes }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- <leader>ta: Convert line to TODO, cursor at end of line (Normal mode) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | local function add_todo_append_mode() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local details, lnum = get_current_line_details() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if not details or details.is_todo then return end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local use_marker = details.marker or "-" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local text_content = details.content | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local new_line = details.indent .. use_marker .. " [ ] " .. text_content | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_buf_set_lines(0, lnum - 1, lnum, false, { new_line }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Set cursor position: 1-based row, 0-based byte column | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Position cursor at the very end of the line content | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local cursor_col_bytes = vim.fn.strbytes(new_line) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_win_set_cursor(0, { lnum, cursor_col_bytes }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | -- <leader>to: Insert new TODO line below, cursor after "] " (Normal mode) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | local function add_todo_new_line_mode() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local details, lnum = get_current_line_details() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if not details then return end -- Should not happen usually, but check anyway | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Determine indent and marker based on current line, default to '-' if no marker | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local new_indent = details.indent | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local new_marker = details.marker or "-" | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local new_line_content = new_indent .. new_marker .. " [ ] " | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Insert after current line (lnum is 1-based, set_lines is 0-based for ranges) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_buf_set_lines(0, lnum, lnum, false, { new_line_content }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Set cursor position: 1-based row (lnum + 1), 0-based byte column | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- Position cursor at the end of the new line (after "] ") | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     local cursor_col_bytes = vim.fn.strbytes(new_line_content) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     vim.api.nvim_win_set_cursor(0, { lnum + 1, cursor_col_bytes }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | end | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | -- Internal function to set up buffer-local keymaps |  |  |  | -- Internal function to set up buffer-local keymaps | 
			
		
	
		
		
			
				
					
					|  |  |  | local function setup_buffer_keymaps() |  |  |  | local function setup_buffer_keymaps() | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- add new todo line when previous is already a todo |  |  |  | 	-- add new todo line when previous is already a todo (Will be refactored in Step 3) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	local function press_enter() |  |  |  | 	local function press_enter() | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local current_line = vim.api.nvim_get_current_line() |  |  |  | 		local current_line = vim.api.nvim_get_current_line() | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local index, spaces = string.find(current_line, "^%s*") |  |  |  | 		-- Check if the current line matches the pattern (Only checks '-' marker currently) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		local pattern = "^%s*%- %[[ x]%]%s*$" -- Simplified pattern to check if it's an empty-ish TODO line | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		-- Check if the current line matches the pattern |  |  |  |         local content_pattern = "^%s*%- %[[ x]%]%s+(.+)" -- Pattern to check if there's content | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		local pattern = "^%- %[[ x]%] .*$" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local match = string.match(current_line, pattern) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if match then |  |  |  | 		if string.match(current_line, content_pattern) then -- If it's a TODO with content | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			if string.len(current_line) >= 7 then |  |  |  |             local indent = string.match(current_line, "^%s*") or "" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys("\n- [ ] ", "n", true) |  |  |  | 			vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<CR>"..indent.."- [ ] ", true, false, true), "n", false) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			else |  |  |  | 		elseif string.match(current_line, pattern) then -- If it's an empty TODO line | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				-- go to normal mode before removing the content of the line |  |  |  | 			-- Current behavior: clear line and insert newline (will change in Step 3) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys(vim.api.nvim_eval('"\\<esc>"'), "n", true) |  |  |  | 			vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>S<CR>", true, false, true), "n", false) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys("_", "n", true) |  |  |  | 		else -- Not a TODO line | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys("C", "n", true) |  |  |  | 			vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<CR>", true, false, true), "n", false) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys("\n", "n", true) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				-- vim.api.nvim_set_current_line("") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		else |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_feedkeys("\n", "n", true) |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		end |  |  |  | 		end | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  | 	end | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- indent line if tab is pressed when line is a todo |  |  |  | 	-- indent line if tab is pressed when line is a todo (Will be refactored in Step 4) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	local function press_tab() |  |  |  | 	local function press_tab() | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local current_line = vim.api.nvim_get_current_line() |  |  |  | 		local current_line = vim.api.nvim_get_current_line() | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		-- Check if current line matches the patterns (Only checks '-' marker currently) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		-- Check if current line matches the patterns |  |  |  | 		local pattern = "^%s*%- %[[ x]%]" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		local openpattern = "%- %[[ ]%]" |  |  |  | 		if string.match(current_line, pattern) then | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		local closedpattern = "%- %[[x]%]" |  |  |  | 			-- print("tab pressed, allegedly") -- Removed print | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 			vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-t>", true, false, true), "i", false) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if string.match(current_line, openpattern) or string.match(current_line, closedpattern) then |  |  |  | 		else | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			print("tab pressed, allegedly") |  |  |  |             -- Return <Tab> to allow default behavior if expr=true is set on mapping | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_feedkeys("C-t", "i", true) |  |  |  |             return vim.api.nvim_replace_termcodes("<Tab>", true, false, true) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         end |  |  |  |         end | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  | 	end | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- indent line if shift tab is pressed when line is a todo |  |  |  | 	-- indent line if shift tab is pressed when line is a todo (Will be refactored in Step 4) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	local function press_shift_tab() |  |  |  | 	local function press_shift_tab() | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local current_line = vim.api.nvim_get_current_line() |  |  |  | 		local current_line = vim.api.nvim_get_current_line() | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 		-- Check if current line matches the patterns (Only checks '-' marker currently) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		-- Check if current line matches the patterns |  |  |  | 		local pattern = "^%s*%- %[[ x]%]" | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		local openpattern = "%- %[[ ]%]" |  |  |  | 		if string.match(current_line, pattern) then | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		local closedpattern = "%- %[[x]%]" |  |  |  | 			-- print("shift tab pressed, allegedly") -- Removed print | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 			vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<C-d>", true, false, true), "i", false) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 		if string.match(current_line, openpattern) or string.match(current_line, closedpattern) then |  |  |  | 		else | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			print("shift tab pressed, allegedly") |  |  |  |             -- Return <S-Tab> to allow default behavior if expr=true is set on mapping | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_feedkeys("C-d", "i", true) |  |  |  |             return vim.api.nvim_replace_termcodes("<S-Tab>", true, false, true) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |         end |  |  |  |         end | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  | 	end | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- function that checks if the current line starts with the string "- [ ]" or "- [x]" and toggles the x |  |  |  | 	-- function that checks if the current line starts with the string "- [ ]" or "- [x]" and toggles the x | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     -- (Will be updated in Step 2 to handle *, +) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	local function toggle_todo() |  |  |  | 	local function toggle_todo() | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local openpattern = "%- %[[ ]%]" |  |  |  | 		local openpattern = "%- %[[ ]%]" | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local closedpattern = "%- %[[x]%]" |  |  |  | 		local closedpattern = "%- %[[x]%]" | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local titleopenpattern = "# %[[ ]%]" |  |  |  | 		local titleopenpattern = "# %[[ ]%]" -- Keep title toggle for now? Or remove? Let's keep it. | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 		local titleclosedpattern = "# %[[x]%]" |  |  |  | 		local titleclosedpattern = "# %[[x]%]" | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local line = vim.api.nvim_get_current_line() |  |  |  | 		local line = vim.api.nvim_get_current_line() | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if string.match(line, openpattern) then |  |  |  | 		if string.match(line, openpattern) then | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, openpattern, "- [x]") |  |  |  | 			line = string.gsub(line, openpattern, "- [x]", 1) -- Replace only first instance | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_set_current_line(line) |  |  |  | 			vim.api.nvim_set_current_line(line) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		elseif string.match(line, closedpattern) then |  |  |  | 		elseif string.match(line, closedpattern) then | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, closedpattern, "- [ ]") |  |  |  | 			line = string.gsub(line, closedpattern, "- [ ]", 1) -- Replace only first instance | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_set_current_line(line) |  |  |  | 			vim.api.nvim_set_current_line(line) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		elseif string.match(line, titleopenpattern) then |  |  |  | 		elseif string.match(line, titleopenpattern) then | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, titleopenpattern, "# [x]") |  |  |  | 			line = string.gsub(line, titleopenpattern, "# [x]", 1) | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_set_current_line(line) |  |  |  | 			vim.api.nvim_set_current_line(line) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		elseif string.match(line, titleclosedpattern) then |  |  |  | 		elseif string.match(line, titleclosedpattern) then | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, titleclosedpattern, "# [ ]") |  |  |  | 			line = string.gsub(line, titleclosedpattern, "# [ ]", 1) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_set_current_line(line) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- function that checks if the current line doesn't start with the string "- [ ] " and, if it doesn't, adds the string at the beginning of the line |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	local function add_todo() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local openpattern = "^%s*%- %[[ ]%]" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local closedpattern = "^%s*%- %[[x]%]" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local line = vim.api.nvim_get_current_line() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local index, spaces = string.find(line, "^%s*") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if index == 1 and not string.match(line, openpattern) and not string.match(line, closedpattern) then |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			if index == 1 and spaces == 0 then |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				line = "- [ ] " .. line |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_set_current_line(line) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_feedkeys("A", "n", true) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			elseif index == 1 and spaces > 0 then |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				local trimedline = string.sub(line, spaces + 1) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				local spacestring = "" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				for x = 1, spaces, 1 do |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 					spacestring = spacestring .. " " |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				line = spacestring .. "- [ ] " .. trimedline |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 				vim.api.nvim_set_current_line(line) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- function that checks if the current line starts with the string "- [ ]" or "- [x]" and, if it does, removes that string from the line |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	local function remove_todo() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local openpattern = "%- %[[ ]%]" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local closedpattern = "%- %[[x]%]" |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		local line = vim.api.nvim_get_current_line() |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		-- local index, spaces = string.find(line, "^%s*") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 		if string.match(line, openpattern) or string.match(line, closedpattern) then |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			print("encontrado") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, openpattern, "") |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 			line = string.gsub(line, closedpattern, "") |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 			vim.api.nvim_set_current_line(line) |  |  |  | 			vim.api.nvim_set_current_line(line) | 
			
		
	
		
		
			
				
					
					|  |  |  | 		end |  |  |  | 		end | 
			
		
	
		
		
			
				
					
					|  |  |  | 	end |  |  |  | 	end | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- Set up buffer-local keymaps |  |  |  | 	-- Set up buffer-local keymaps | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- Use buffer = 0 to target the current buffer |  |  |  | 	-- Use buffer = 0 to target the current buffer | 
			
		
	
		
		
			
				
					
					|  |  |  | 	local map_opts = { noremap = true, silent = true, buffer = 0 } |  |  |  | 	-- Note: Setting expr = true for Tab/S-Tab allows returning keys for default behavior | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	local expr_map_opts = { noremap = true, expr = true, silent = true, buffer = 0 } |  |  |  | 	vim.keymap.set("n", "<leader>t", function() end, { desc = "+TODOs", buffer = 0 }) -- Placeholder | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 	vim.keymap.set("i", "<CR>", press_enter, { desc = "Todoer: Handle Enter", expr = true, buffer = 0 }) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("n", "<leader>t", function() end, { desc = "+TODOs", buffer = 0 }) -- Placeholder, keep silent=false if needed |  |  |  | 	vim.keymap.set("i", "<TAB>", press_tab, { desc = "Todoer: Handle Tab", expr = true, buffer = 0 }) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("i", "<CR>", press_enter, { desc = "Todoer: Handle Enter", expr = true, buffer = 0 }) -- Keep expr=true, noremap=true is default |  |  |  | 	vim.keymap.set("i", "<S-Tab>", press_shift_tab, { desc = "Todoer: Handle Shift-Tab", expr = true, buffer = 0 }) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("i", "<TAB>", press_tab, { desc = "Todoer: Handle Tab", expr = true, buffer = 0 }) -- Keep expr=true |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("i", "<S-Tab>", press_shift_tab, { desc = "Todoer: Handle Shift-Tab", expr = true, buffer = 0 }) -- Keep expr=true |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("n", "<leader>tt", toggle_todo, { desc = "Todoer: Toggle TODO", buffer = 0 }) |  |  |  | 	vim.keymap.set("n", "<leader>tt", toggle_todo, { desc = "Todoer: Toggle TODO", buffer = 0 }) | 
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("n", "<leader>ta", add_todo, { desc = "Todoer: Add TODO", buffer = 0 }) |  |  |  | 	-- New mappings for adding TODOs | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 	vim.keymap.set("n", "<leader>td", remove_todo, { desc = "Todoer: Remove TODO", buffer = 0 }) |  |  |  | 	vim.keymap.set("n", "<leader>ti", add_todo_insert_mode, { desc = "Todoer: Add TODO (cursor after marker)", buffer = 0, silent = true }) | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	vim.keymap.set("n", "<leader>ta", add_todo_append_mode, { desc = "Todoer: Add TODO (cursor at end)", buffer = 0, silent = true }) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 	vim.keymap.set("n", "<leader>to", add_todo_new_line_mode, { desc = "Todoer: Add new TODO line below", buffer = 0, silent = true }) | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- Optional: Notify that keymaps are set for this buffer |  |  |  | 	-- Optional: Notify that keymaps are set for this buffer | 
			
		
	
		
		
			
				
					
					|  |  |  | 	-- vim.notify("Todoer keymaps activated for this buffer", vim.log.levels.INFO) |  |  |  | 	-- vim.notify("Todoer keymaps activated for this buffer", vim.log.levels.INFO) | 
			
		
	
	
		
		
			
				
					|  |  | 
 |