R-nvim / R.nvim

Neovim plugin to edit R files
GNU General Public License v3.0
128 stars 15 forks source link

Open R console in a new tmux pane #152

Open MiboraMinima opened 1 week ago

MiboraMinima commented 1 week ago

I am trying to configure the plugin to launch R in a new tmux pane within the same terminal. I've attempted the following configuration:

external_term = "tmux split-window 'R'"

This config successfully opens a new tmux pane when I start R.nvim and I can write R code in it. However, I am unable to send code from Neovim to the new pane. Additionally, the plugin doesn't function correctly, displaying the message "R is not ready yet" in Neovim when I attempt to run any command linked to R.nvim.

When I start R in the new pane, I see the following output:

ARGUMENT 'new-session' __ignored__

ARGUMENT 'Rnvim-551' __ignored__

ARGUMENT 'RNVIM_TMPDIR=/dev/shm/R.nvim-user' __ignored__

ARGUMENT 'RNVIM_COMPLDIR=/home/user/.cache/R.nvim' __ignored__

ARGUMENT 'RNVIM_ID=2930209553' __ignored__

ARGUMENT 'RNVIM_SECRET=2372621146' __ignored__

ARGUMENT 'RNVIM_PORT=10101' __ignored__

ARGUMENT 'R_DEFAULT_PACKAGES=datasets,utils,grDevices,graphics,stats,methods,nvimcom' __ignored__

ARGUMENT 'R' __ignored__

When I set config_tmux = true, the pane opens and closes immediately. If I set config_tmux = false, the pane stays open but nothing works as expected. The same messages are displayed in both cases.

Additional Information:

Is it possible to open an R console in a new tmux pane, as the plugin seems to have been designed to open it in a new terminal ?

PMassicotte commented 1 week ago

have you simply tried:

external_term = "tmux split-window -vf ",
jalvesaq commented 1 week ago

Great, @PMassicotte! I didn't know that it was so simple!

statquant commented 1 week ago

This is great thanks for this !

MiboraMinima commented 1 week ago

It works perfectly ! Thank you !

PMassicotte commented 1 week ago

Maybe add this info in the help?

jalvesaq commented 1 week ago

Yes, it's a good idea to add it. Something like:

diff --git a/doc/R.nvim.txt b/doc/R.nvim.txt
index 04316cd..b402bd0 100644
--- a/doc/R.nvim.txt
+++ b/doc/R.nvim.txt
@@ -128,7 +128,8 @@ Suggestions for Unix (Linux, OS X, etc.):

    Tmux >= 3.0:  http://tmux.sourceforge.net
                  Tmux is required only if you want to run R in an external
-                 terminal emulator (see |external_term|).
+        terminal emulator or in a Tmux split panel
+        (see |external_term|).

    colorout:     https://github.com/jalvesaq/colorout/releases
                  Colorizes the R output in terminal emulators.
@@ -889,6 +890,11 @@ complete command to run the terminal. Examples:
 Please, look at the manual of your terminal emulator to know how to call it.
 The last argument must be the one which precedes the command to be executed.

+Although the option is intended to allow running R in an external terminal
+emulator, it can also be used to run R in a Tmux split panel. Example:
+>lua
+   external_term = "tmux split-window -vf "
+<
 The terminal error messages, if any, are shown as warning messages, unless you
 put in your config:
 >lua
PMassicotte commented 1 week ago

Excellent!

johngodlee commented 1 week ago

I receive an error when trying to run this with a minimal config taken from the R.nvim README.md. I'm running macOS Sonoma 14.5.

The error:

Vim:E482: Can't open file /var/folders/z6/k42yf16d3kj553t0r92j6vyr0000gn/T/nvim.johngodlee/oJeYzK/0/openR for writing: no such file or directory
stack traceback:
^I[C]: in function 'writefile'
^I...ee/.local/share/nvim/lazy/R.nvim/lua/r/external_term.lua:165: in function 'start_extern_term'
^I...s/johngodlee/.local/share/nvim/lazy/R.nvim/lua/r/run.lua:160: in function <...s/johngodlee/.local/share/nvim/lazy/R.nvim/lua/r/run.lua:16>

The config:

init.lua:

require("config.lazy")

lua/config/lazy.lua:

-- lazy.nvim boilerplate
local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
        vim.fn.system({
                "git",
                "clone",
                "--filter=blob:none",
                "https://github.com/folke/lazy.nvim.git",
                "--branch=stable", -- latest stable release
                lazypath,
        })
end
vim.opt.rtp:prepend(lazypath)

-- load lazy
require("lazy").setup("plugins")

lua/plugins/r.lua:

The config is the same as in the R.nvim README.md, save for these additional lines:

    config = function()
            local opts = {
                    external_term = "tmux split-window -vf "
            }

Full config:

return {
  {
    "R-nvim/R.nvim",
    config = function()
            local opts = {
                    external_term = "tmux split-window -vf "
            }
            require("r").setup(opts)
    end,
    lazy = false
  },
  {
    "nvim-treesitter/nvim-treesitter",
    run = ":TSUpdate",
    config = function ()
      require("nvim-treesitter.configs").setup({
        ensure_installed = { "markdown", "markdown_inline", "r", "rnoweb" },
      })
    end
  },
  "R-nvim/cmp-r",
  {
    "hrsh7th/nvim-cmp",
    config = function()
      require("cmp").setup({ sources = {{ name = "cmp_r" }}})
      require("cmp_r").setup({ })
    end,
  },
}
jalvesaq commented 1 week ago

The problem is that macOS doesn't open whatever terminal emulator users choose and our solution is to open a shell script. This causes the default terminal emulator to be opened by macOS. So, we have to create an exception if the "terminal" is tmux.

Line 157 of lua/r/external_term.lua is:

    if config.is_darwin then

I don't have a macOS to try any changes, but, perhaps, it would work if line 157 were:

    if config.is_darwin and not term_cmd:find("^tmux ") then
jalvesaq commented 1 week ago

Or:

    if config.is_darwin and term_name ~= "tmux " then
johngodlee commented 1 week ago

Hi @jalvesaq thanks for the prompt reply. I tried both your suggestions, but neither worked.

The first suggestion complains that term_cmd is not set:

...ee/.local/share/nvim/lazy/R.nvim/lua/r/external_term.lua:157: attempt to index upvalue 'term_cmd' (a nil value)

The second fails with the same message as when no changes are applied.

Thanks for the headstart though, I will continue to think about how this can be fixed.

jalvesaq commented 1 week ago

Maybe it will be fixed if we change the position of line 20. Instead of:

    if config.is_darwin then return end

    if type(config.external_term) == "string" then
        -- User defined terminal
        term_name = string.gsub(tostring(config.external_term), " .*", "")
        if string.find(tostring(config.external_term), " ") then
            -- Complete command defined by the user
            term_cmd = config.external_term
            return
        end
    end

It would be:

    if type(config.external_term) == "string" then
        -- User defined terminal
        term_name = string.gsub(tostring(config.external_term), " .*", "")
        if string.find(tostring(config.external_term), " ") then
            -- Complete command defined by the user
            term_cmd = config.external_term
            return
        end
    end

    if config.is_darwin then return end
johngodlee commented 1 week ago

When I combine the suggested move of L20 with this change to L157:

    if config.is_darwin and not term_cmd:find("^tmux ") then

everything works as expected! Thank you so much for your help.

Will it be possible to add these changes to the next release, or is there still a lot of testing to make sure these changes don't break other stuff?

jalvesaq commented 1 week ago

I can do the changes on the main branch. But, instead of not term_cmd:find("^tmux "), it's simpler to test term_name ~= "tmux" (there was a trailing space in my comment above).

PMassicotte commented 1 week ago

Maybe it will be fixed if we change the position of line 20. Instead of:

    if config.is_darwin then return end

    if type(config.external_term) == "string" then
        -- User defined terminal
        term_name = string.gsub(tostring(config.external_term), " .*", "")
        if string.find(tostring(config.external_term), " ") then
            -- Complete command defined by the user
            term_cmd = config.external_term
            return
        end
    end

It would be:

    if type(config.external_term) == "string" then
        -- User defined terminal
        term_name = string.gsub(tostring(config.external_term), " .*", "")
        if string.find(tostring(config.external_term), " ") then
            -- Complete command defined by the user
            term_cmd = config.external_term
            return
        end
    end

    if config.is_darwin then return end

Good catch!

jalvesaq commented 1 week ago

I pushed the changes to the main branch and it should work on macOS now... Thanks for reporting the issue and for the feedback!

mpadge commented 20 hours ago

Quick question here as a related sub-issue for @jalvesaq and/or @PMassicotte: The new tmux pane for me now only scrolls back to top of visible buffer but not further, using tmux scroll Ctrl-[ + Ctrl-B. This occurs regardless of whether I use my custom tmux.conf or not (via config_tmux). My config is here. Any help would be appreciated! And thanks for all of your awesome work!

PMassicotte commented 15 hours ago

What is your history-limit?

Maybe you can increase it with something like:

echo "set -g history-limit 5000" >> ~/.tmux.conf

I am a kitty user now, so might not be the right way :)

mpadge commented 14 hours ago

Thanks @PMassicotte, but it's not that. I use huge history limits, and it's very clearly related to screen buffer not history itself. This is in alacritty, not kitty. Any other ideas?

jalvesaq commented 14 hours ago

Tmux is running inside Tmux, so you have to press <C-A> twice and then [ to enter the copy mode in the nested Tmux.

jalvesaq commented 14 hours ago

Since running R in a Tmux split pane is a recurrent demand, I'll try to make it work better.

jalvesaq commented 13 hours ago

On the branch https://github.com/R-nvim/R.nvim/tree/tmux_split, R.nvim directly splits Tmux window instead of running a nested Tmux instance.