From 0662b8a8f3a15760cafaf7c603f6c8d06844aee9 Mon Sep 17 00:00:00 2001 From: "Guilherme D. Garcia" Date: Sun, 8 Feb 2026 19:41:30 -0500 Subject: [PATCH 1/4] feat: make insert_commented pipe-chain aware When the cursor is inside a multi-line pipe chain (|>, %>%, %<>%, %T>%, or + for ggplot), \ro now collects the full chain instead of just the current line. The output is inserted as a comment below the last line of the chain. Single-line behavior is unchanged. --- lua/r/run.lua | 59 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/lua/r/run.lua b/lua/r/run.lua index 03cd3580..e1e00b87 100644 --- a/lua/r/run.lua +++ b/lua/r/run.lua @@ -433,13 +433,62 @@ 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("|>$") + or clean:match("%+$") + end + + -- Walk up: find the first line of the chain + local first = cur_line + while first > 1 do + 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 + + -- Walk down: find the last line of the chain + local last = cur_line + while last < total_lines do + local cur = vim.api.nvim_buf_get_lines(bufnr, last - 1, last, true)[1] + if ends_with_pipe(cur) then + last = last + 1 + else + break + end + end + + -- Collect and clean lines + local lines = vim.api.nvim_buf_get_lines(bufnr, first - 1, last, true) + local cleaned = {} + for _, l in ipairs(lines) do + table.insert(cleaned, (l:gsub("%s*#.*$", ""))) + end + local code = table.concat(cleaned, "\n") + + -- 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 From 0da372db4526550704f1c9c7d1bae0693810464d Mon Sep 17 00:00:00 2001 From: "Guilherme D. Garcia" Date: Sun, 8 Feb 2026 19:50:59 -0500 Subject: [PATCH 2/4] fix: join pipe chain lines with space instead of newline --- lua/r/run.lua | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lua/r/run.lua b/lua/r/run.lua index e1e00b87..ceca28e3 100644 --- a/lua/r/run.lua +++ b/lua/r/run.lua @@ -469,13 +469,15 @@ M.insert_commented = function() end end - -- Collect and clean lines + -- 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 - table.insert(cleaned, (l:gsub("%s*#.*$", ""))) + local stripped = l:gsub("%s*#.*$", "") + stripped = vim.trim(stripped) + if stripped ~= "" then table.insert(cleaned, stripped) end end - local code = table.concat(cleaned, "\n") + local code = table.concat(cleaned, " ") -- Validate: no semicolons local check = code:gsub('".-"', "") From f9c713be2b021431e8f3ec63a42b709bf7a85d58 Mon Sep 17 00:00:00 2001 From: "Guilherme D. Garcia" Date: Sun, 8 Feb 2026 20:07:13 -0500 Subject: [PATCH 3/4] fix: add paren tracking and remove ggplot + from pipe detection - Walk-down now tracks parenthesis depth so multi-line function args (e.g., mutate(\n...\n)) are included in the chain - Walk-up tracks reverse paren depth so cursor on `)` lines finds the matching `(` above - Remove `+` from pipe operators (printing ggplot objects as comments is not useful) --- lua/r/run.lua | 40 +++++++++++++++++++++++++++++++--------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/lua/r/run.lua b/lua/r/run.lua index ceca28e3..21350193 100644 --- a/lua/r/run.lua +++ b/lua/r/run.lua @@ -444,25 +444,47 @@ M.insert_commented = function() or clean:match("%%<>%%$") or clean:match("%%T>%%$") or clean:match("|>$") - 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 - while first > 1 do - local prev = vim.api.nvim_buf_get_lines(bufnr, first - 2, first - 1, true)[1] - if ends_with_pipe(prev) then + 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 - break + 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: find the last line of the chain - local last = cur_line - while last < total_lines do + -- 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] - if ends_with_pipe(cur) then + 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 then + last = last + 1 + elseif ends_with_pipe(cur) then last = last + 1 else break From dfb21c3d07de44b876b39e7b4ba7cc8b29a4b060 Mon Sep 17 00:00:00 2001 From: "Guilherme D. Garcia" Date: Sun, 8 Feb 2026 20:22:23 -0500 Subject: [PATCH 4/4] fix: combine identical if branches to satisfy selene linter --- lua/r/run.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lua/r/run.lua b/lua/r/run.lua index 21350193..0a81355e 100644 --- a/lua/r/run.lua +++ b/lua/r/run.lua @@ -482,9 +482,7 @@ M.insert_commented = function() 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 then - last = last + 1 - elseif ends_with_pipe(cur) then + if paren_depth > 0 or ends_with_pipe(cur) then last = last + 1 else break