diff --git a/lua/r/run.lua b/lua/r/run.lua index 03cd3580..0a81355e 100644 --- a/lua/r/run.lua +++ b/lua/r/run.lua @@ -433,13 +433,84 @@ M.insert = function(cmd, type) end M.insert_commented = function() - local lin = vim.api.nvim_get_current_line() - local cleanl = lin:gsub('".-"', "") - if cleanl:find(";") then + local cur_line = vim.api.nvim_win_get_cursor(0)[1] + local bufnr = vim.api.nvim_get_current_buf() + local total_lines = vim.api.nvim_buf_line_count(bufnr) + + -- Helper: does this line end with a pipe operator? + local ends_with_pipe = function(line) + local clean = line:gsub("%s*#.*$", ""):gsub("%s+$", "") + return clean:match("%%>%%$") + or clean:match("%%<>%%$") + or clean:match("%%T>%%$") + or clean:match("|>$") + end + + -- Count occurrences of a pattern in a string + local count_pat = function(s, pat) + local _, n = s:gsub(pat, "") + return n + end + + -- Walk up: find the first line of the chain + -- Track paren depth (reversed): `)` needs `(` above + local first = cur_line + local paren_depth = 0 + while first >= 1 do + local line = vim.api.nvim_buf_get_lines(bufnr, first - 1, first, true)[1] + local clean = line:gsub("%s*#.*$", "") + paren_depth = paren_depth + count_pat(clean, "%)") - count_pat(clean, "%(") + if first == 1 then break end + if paren_depth > 0 then + first = first - 1 + else + local prev = vim.api.nvim_buf_get_lines(bufnr, first - 2, first - 1, true)[1] + if ends_with_pipe(prev) then + first = first - 1 + else + break + end + end + end + + -- Walk down from first: find the last line of the chain + -- Track paren depth (forward): `(` opens, `)` closes + local last = first + paren_depth = 0 + while last <= total_lines do + local cur = vim.api.nvim_buf_get_lines(bufnr, last - 1, last, true)[1] + local clean = cur:gsub("%s*#.*$", "") + paren_depth = paren_depth + count_pat(clean, "%(") - count_pat(clean, "%)") + if last == total_lines then break end + if paren_depth > 0 or ends_with_pipe(cur) then + last = last + 1 + else + break + end + end + + -- Collect and clean lines (join with space — newlines break the transport layer) + local lines = vim.api.nvim_buf_get_lines(bufnr, first - 1, last, true) + local cleaned = {} + for _, l in ipairs(lines) do + local stripped = l:gsub("%s*#.*$", "") + stripped = vim.trim(stripped) + if stripped ~= "" then table.insert(cleaned, stripped) end + end + local code = table.concat(cleaned, " ") + + -- Validate: no semicolons + local check = code:gsub('".-"', "") + if check:find(";") then warn("`print(line)` works only if `line` is a single command") end - cleanl = string.gsub(lin, "%s*#.*", "") - M.insert("print(" .. cleanl .. ")", "comment") + + -- Move cursor to the last line so output is inserted below the chain + if last ~= cur_line then + vim.api.nvim_win_set_cursor(0, { last, 0 }) + end + + M.insert("print(" .. code .. ")", "comment") end ---Call R functions for the word under cursor