Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix r profile #399

Merged
merged 5 commits into from
Feb 3, 2025
Merged

Fix r profile #399

merged 5 commits into from
Feb 3, 2025

Conversation

mihem
Copy link
Contributor

@mihem mihem commented Jan 31, 2025

@b-rodrigues I found that the resulting .Rprofile has some curly braces which prevent functions to work.

{
    is_rstudio <- Sys.getenv("RSTUDIO") == "1"
...
    rm(is_rstudio, is_nix_r)
}

So I could call install.packages() and there was not stop message.
Getting rid of the curly braces was quite difficult. Tried using expression or using subsitute but that did not work. So in the end i justed used gsub to remove them. Maybe not very elegant, but at least works. I tested that in my case it raises the expected error message. Not sure we can create a unit test for that, because it's testing the resulting environment?

Additionally, vscode-R did not work properly, .vsc.attach did not work and functionalities like View did not work.
REditorSupport/vscode-R#1094

So I added the necessary source lines. I put this in an if statement only evaluating if the editor is vscode, so I think this should not mess up anything.

Looking forward to your feedback.

mihem added 2 commits January 31, 2025 21:31
remove curly braces because they prevent the code from working
add source vscode to the rix_init.R file
@b-rodrigues
Copy link
Contributor

Could you give more details? I just tried running install.packages("dplyr") inside of a Nix session, and I do get the error message. Same for update.packages().

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

Hm, this is weird. On my machine (ubuntu noble) this did not raise the expected error. I tried making it reproducible using docker (and then encountered the issue #401 ), but the docker image then raised the expected error. So i need to investigate further why this happens with my settings in a non-docker environment.

@b-rodrigues
Copy link
Contributor

could you post the generated .Rprofile here?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

I couldn't reproduce my earlier problems; sorry, don't know what happened there. So I removed the gsub part which removed the curly braces and only kept the part for vscode-R. I also added a check for positron because this is also "vscode" but does work with vscode-R. https://positron.posit.co/extensions.html

@b-rodrigues
Copy link
Contributor

where you starting the session with --vanilla perhaps?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

No. Well, everything works fine now, so I am happy :P.
Is it possible to create unit tests to check if the .RProfile is properly setup, so raises the expected errors in the nix-environment?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

@b-rodrigues any further input you need from me for this PR and the other PRs?

@b-rodrigues
Copy link
Contributor

can you explain what the Positron check does ?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

See https://positron.posit.co/extensions.html
If it s positron, this should not get called.

@b-rodrigues
Copy link
Contributor

I still don't get it, what should not be called ?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

image

So for vscode-R this is not important, but I think if you use Positron adding
source(file.path(Sys.getenv(if (.Platform$OS.type == "windows") "USERPROFILE" else "HOME"), ".vscode-R", "init.R"))
breaks things, that's why I included the Positron check.

@b-rodrigues
Copy link
Contributor

I need to know exactly what this fixes before merging though

@b-rodrigues
Copy link
Contributor

From my reading this seems to be something rix shouldn't "fix"

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

With the current .Rprofile, vscode-R is not really usable.

E.g. View(iris) opens a new windows, which looks terrible:

image

I guess you know this from using emacs.

while after this "fix" this looks as it's supposed to be in vscode-R

image

And this is only one example, similar things are true for plotting, see attached Namespace etc.

So adding this one line is just something which vscode-R users need to do to get vscode-R working properly: https://github.com/REditorSupport/vscode-R/wiki/R-Session-watcher#advanced-usage-for-self-managed-r-sessions

This is only one additional line, Rstudio has also specific settings and only if your editor is vscode, but not Positron, and if your session is interactive, this will be used. This will then source this file:
https://github.com/REditorSupport/vscode-R/blob/master/R/session/init.R

@b-rodrigues
Copy link
Contributor

I see but isn't vs code-r not mandatory with Positron? it seems to me that if someone wants to use vscode-r with Positron then it's on them to apply the suggested fix from the documentation, no?

@b-rodrigues
Copy link
Contributor

Ultimately, this has nothing to do with Nix nor rix, or did I misunderstand something? it is possible to append the .Rprofile instead of overwriting it so these users would need to append

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

I only use vscode-R (tried Positron, but Copilot does not work, cannot use spacemacs keybindings using VSpaceCode as i am used to, devcontainer and ssh experimental)
No, from my understanding Positron is incompatible with vscode-R.
So personally right now, I am only interested in using vscode-R, which require this line. You could say I have to manually add this line for each rix project, but of course it would be convenient if works out of the box, and I don't see any disadvantage here.

I just included checking if it's Positron because otherwise also Positron would source this file, which would not work if you read the Positron docs.

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

Well, maybe it's not directly linked to nix or rix, but you also have special seetings for Rstudio or vscode (installing language server) and you create a specific R profile.
So as long as I am not in the nix-shell everaything works fine, but when I use the nix-shell vscode-R functionality does not work because of the custom .Rprofile that nix/rix uses. So I think rix should take care of getting back this functionality.

@b-rodrigues
Copy link
Contributor

OK I see I was confusing Positron and vscode

@b-rodrigues
Copy link
Contributor

I'll be testing and merging all PR this weekend hopefully

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

Thanks!
I would think that all PRs except the get closest commit should be trivial, but of course the devil is in the details, so I am happy if you test this.

@b-rodrigues
Copy link
Contributor

b-rodrigues commented Feb 1, 2025

Could you describe the issue step by step? Because I can't replicate. I have installed vscodium-fhs from nixpkgs, and trying to plot seems to work fine (same for View(mtcars)):

image

this is with an .Rprofile generated from the code in main and no {httpgd}. It's with this R extension

image

that's the one, right?

@mihem
Copy link
Contributor Author

mihem commented Feb 1, 2025

Yes this is the right extension and everything works fine, which you can see because your plot looks good but also your terminal is attached to the code (becase it says R 4.4.2). And you have an "R interactive" session, which I am not able to create using nix shell.

However, I think you don't use R in a nix-shell? Or are you opening vscode from within nix-shell?

I am using my locally installed VSCode.

So I open my locally installed VSCode and when I then open a R terminal liek this (or via VSpacecode with Spc-m-m)

image

I get an iRinteractive terminal, where everything works fine, however this is my local R and not nix.

image

If I want to use R in nix I open a shell (zsh in my case) and run "nix-shell" and then "R"

image

THen you can see the terminal is called R not R interactive. And in the bottom row R: (not attached).

If i click on this `R: (not attched), i get the following error (since the init.R of vscode-R is not sourced).

image

And View(iris opens this terrible window shown above.

@b-rodrigues
Copy link
Contributor

i open vscode from a running nix-shell, what happens if you do that ?

@b-rodrigues
Copy link
Contributor

if you don't want to start vscode from a nix shell then this extension might help https://marketplace.visualstudio.com/items?itemName=arrterian.nix-env-selector

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

I haven't thought about these options thanks. However, both options had some issues (or probably the same issue):

So using the extensions you proposed:
It's attached to the editor, which is great. However the libPaths is wrong (I think the first one shouldn't be in there at all and then why is there only one nix path in there), and I can't load my library then.

image

Using vscode from within nix-shell very much the same:

image

@b-rodrigues
Copy link
Contributor

are you inside of nested shells?

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

Out of curiosity: How do handle this, e.g. in Emacs?

And for my understanding: What is the disadvantage of changing the Rprofile? At least I don't really know how to fix this with libPaths. And using nix-shell and R from within vscode is just a self-managed R terminal described int he documentation and similar to tmux, so don't think this is such a hacky solution

image

@b-rodrigues
Copy link
Contributor

A priori no disadvantage but I want to make sure I understand what's wrong. When I start vscode from a shell everything works as expected so I need to know what's about your setup that breaks things because it could be the symptom of a more general issue.
Changing the .Rprofile could potentially break things for other setups.

Rstudio is the only editor that must be managed by Nix to work with Nix shell, but other could be locally managed.

As for me with emacs, I have emacs installed from openSuse, but use nix-direnv https://github.com/nix-community/nix-direnv

so when I start an R session in a folder with a nix-shell it gets loaded automatically

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

Hm this could easily happen because I would use nnn for directory navigation and then change to shell again.
So I now didn't use nnn to get to that directory.

Using the extension I didn't know why there should be a nested shell, I think it's not

image

Still same issue then:
image

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

And the other options:

zsh is level1 and nix-shell is then level2.

image

But then .. tada everything works.

image

@b-rodrigues
Copy link
Contributor

can you share the .Rprofile and default.nix files here ?

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

Usually I like to stay within the editor (earlier emacs,now vscode), and use extensions (projects) to navigate to my project and then open files and the R terminal from there (can use Spacemacs keybindings).
I think the option of navigating to the folder using the shell (i have to remember not to use nested shell which can easily happen with my file manager nnn), running nix-shell and opening code from there is okay, maybe a little less preferable from my view.

I would still prefer adding this PR to make it work with self-managed R terminals for vscode users (I can't see why this would break things for others because it will only apply if you use vscode), and we could change it if this does actually break the setup for other users .

@b-rodrigues
Copy link
Contributor

And if you don't have a system wide library of packages, this works as well ?

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

thanks for sharing your workflow (althouth I am not fully understanding nix-direnv).

And to sum up:
You are right, vscode works fine when started locally. However vscodeR needs this init.R script if it's not started within nix-shell.

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

Ah, now I think I am finally understand the problem you have with the approach.
You mean if you install everything using nix and don't have system libraries at all. I don't think this will apply to many R users, but sure would be nice if it would also work then.
I am not sure there is a way I can test this. Isn't this your setup? Can you test this?
I mean we could also include another statement within the if vscode statement. If the file exists then use this, otherwise skip this and maybe print a message that this has to be done manually or link to the docs (where we should better explian that the editor has to be started from within nix-shell)

@b-rodrigues
Copy link
Contributor

Can you test this?

I'd be quicker for you to rename the R library in your home/ so it doesn't get loaded than for me to setup vscode and extensions and whatnot 😉

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

Ah sorry, I though you mean having everything installed in /nix.
So i renamed R and everything works fine.
If i rename .vscode-R then i get an error message of course

Error in file(filename, "r", encoding = encoding) : 
  cannot open the connection
In addition: Warning message:
In file(filename, "r", encoding = encoding) :
  cannot open file '/home/mischko/.vscode-R/init.R': No such file or directory

And as before when the code of this PR wasn't included I cannot attach the R terminal

> .vsc.attach()
Error in .vsc.attach() : could not find function ".vsc.attach"

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

So I added a check if the file exists (so this would be apply if someone uses VSCode interactively (not Positron), but does not have vscode-R installed (which is unlikely because you cannot do much without an R extension), but still. I hope this is what you meant?

@b-rodrigues
Copy link
Contributor

I'll be doing some final testing and then this should be good to merge.

It also made me think that the vignette titled "interactive use" needs to be updated and describe all of this as well.

@b-rodrigues
Copy link
Contributor

So I installed vs code from the opensuse package manager and opened a project with a default.nix and got this message

image

I already had these two extensions (perhaps from previous testing?)

image

Starting the command palette and selecting "Nix-Env: select environment" and then restarting vs code works. Then, using View(mtcars) opens the data in that awful window as you described.

I then tried with the code in your branch, but got following warning message:

Warning messages:
1: In rm(is_rstudio, is_nix_r, is_code, is_positron) :
  object 'is_rstudio' not found
2: In rm(is_rstudio, is_nix_r, is_code, is_positron) :
  object 'is_nix_r' not found
3: In rm(is_rstudio, is_nix_r, is_code, is_positron) :
  object 'is_code' not found
4: In rm(is_rstudio, is_nix_r, is_code, is_positron) :
  object 'is_positron' not found

and the .Rprofile is just NULL. Can you replicate? Try in a completely empty directory. Here is the call to rix() I used:

library(rix)

rix(
  date = "2025-01-27",
  r_pkgs = c("httpgd", "dplyr", "ggplot2"),
  ide = "code",
  project_path = ".",
  overwrite = TRUE,
  print = TRUE
)

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

@b-rodrigues sorry, my bad. It worked before. But with the last commit, I put the last two parentheses at the wrong place and didn't test anymore.

I tested it now and it worked for me. Here is the resulting .Rprofile

### File generated by `rix::rix_init()` ###
# 1. Currently, system RStudio does not inherit environmental variables
#   defined in `$HOME/.zshrc`, `$HOME/.bashrc` and alike. This is workaround to
#   make the path of the nix store and hence basic nix commands available
#   in an RStudio session
# 2. For nix-R session, remove `R_LIBS_USER`, system's R user library.`.
#   This guarantees no user libraries from the system are loaded and only
#   R packages in the Nix store are used. This makes Nix-R behave in pure manner
#   at run-time.
{
    is_rstudio <- Sys.getenv("RSTUDIO") == "1"
    is_nix_r <- nzchar(Sys.getenv("NIX_STORE"))
    is_code <- Sys.getenv("TERM_PROGRAM") == "vscode"
    is_positron <- Sys.getenv("POSITRON") == "1"
    if (isFALSE(is_nix_r) && isTRUE(is_rstudio)) {
        cat("{rix} detected RStudio R session")
        old_path <- Sys.getenv("PATH")
        nix_path <- "/nix/var/nix/profiles/default/bin"
        has_nix_path <- any(grepl(nix_path, old_path))
        if (isFALSE(has_nix_path)) {
            Sys.setenv(PATH = paste(old_path, nix_path, sep = ":"))
        }
        rm(old_path, nix_path)
    }
    if (isTRUE(is_nix_r)) {
        install.packages <- function(...) {
            stop("You are currently in an R session running from Nix.\n", "Don't install packages using install.packages(),\nadd them to ", "the default.nix file instead.")
        }
        update.packages <- function(...) {
            stop("You are currently in an R session running from Nix.\n", "Don't update packages using update.packages(),\n", "generate a new default.nix with a more recent version of R. ", "If you need bleeding edge packages, read the", "'Understanding the rPackages set release cycle and using ", "bleeding edge packages' vignette.")
        }
        remove.packages <- function(...) {
            stop("You are currently in an R session running from Nix.\n", "Don't remove packages using `remove.packages()``,\ndelete them ", "from the default.nix file instead.")
        }
        current_paths <- .libPaths()
        userlib_paths <- Sys.getenv("R_LIBS_USER")
        user_dir <- grep(paste(userlib_paths, collapse = "|"), current_paths, fixed = TRUE)
        new_paths <- current_paths[-user_dir]
        .libPaths(new_paths)
        rm(current_paths, userlib_paths, user_dir, new_paths)
    }
    if (isTRUE(is_code) && interactive() && isFALSE(is_rstudio) && isFALSE(is_positron)) {
        vscode_r_init <- file.path(Sys.getenv(if (.Platform$OS.type == "windows") 
            "USERPROFILE"
        else "HOME"), ".vscode-R", "init.R")
        if (file.exists(vscode_r_init)) {
            source(vscode_r_init)
        }
        else {
            message("No .vscode-R/init.R file found. If you want to use VSCode-R, you need to source it in your .Rprofile or start vscode from within nix-shell")
        }
    }
    rm(is_rstudio, is_nix_r, is_code, is_positron)
}

@b-rodrigues
Copy link
Contributor

nice, I'll do some more testing and will likely merge tomorrow

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

I also made a short screenrecording to show how I would use it

rix_rprofile_vscode.mp4

I renamed ~/.vscode-R (so testing what would happen if you don't have vscode-R extension installed) and then it shows the message and it's not attached

image

@b-rodrigues
Copy link
Contributor

b-rodrigues commented Feb 2, 2025

what does this mean ? not attached ?

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

In contrast, I played around with starting code from nix-shell and somestimes encountered difficulties. So if i already had an instance of vscode running, then the new vscode, which was started from within nix-shell, showed again this one nix location only and one of my system library.

image

So I am more happy with the solution starting vscode without nix-shell.

@mihem
Copy link
Contributor Author

mihem commented Feb 2, 2025

@b-rodrigues not attached just means that the R-terminal is not attached to the file. That's because vscode-R is not working properly, so you cannot use all the goodies and have this awful View etc.

if (file.exists(vscode_r_init)) {
source(vscode_r_init)
} else {
message("No .vscode-R/init.R file found. If you want to use VSCode-R, you need to source it in your .Rprofile or start vscode from within nix-shell")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the extension called VSCode-R? Is it this one? https://open-vsx.org/extension/REditorSupport/r

Shouldn't it be REditorSupport?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well it's often called vscode-R and it's stored in the location .vscode-R.
Here the github repo also says vscode-R https://github.com/REditorSupport/vscode-R.
As far as I know it's the only (or at least only official) R extension in vscode

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough

@b-rodrigues
Copy link
Contributor

b-rodrigues commented Feb 3, 2025

So this seems to be working fine, but I think that the best workflow likely is:

  • install direnv
  • create an .envrc file in the root folder of your project (next to the default.nix file) and add following line: use nix
  • Install the vcode direnv extension: https://marketplace.visualstudio.com/items?itemName=mkhl.direnv
  • Restart vscode. You'll have to allow direnv (you'll get a notification). You might also need to restart the R shell.
  • Now VSCode automatically loads the shell

This is actually exactly how I do it with Emacs. Just put .envrc file in all your projects and allow them (only need to do this once) and VSCode will seamlessly switch envs.

This is ready to merge, there's just one comment left for you to address.

Many thanks for this contribution!

@b-rodrigues b-rodrigues merged commit 0ed4a71 into ropensci:main Feb 3, 2025
13 of 14 checks passed
@mihem
Copy link
Contributor Author

mihem commented Feb 3, 2025

Thank you.

I will definitely try this out. And VSCode will then also activate the nix-environment? That would save two steps (but requires an extra package, and extensions and creating a file).

@b-rodrigues
Copy link
Contributor

I will definitely try this out. And VSCode will then also activate the nix-environment?

Yep, once you install direnv, create an .envrc file and allow direnv in that directory, vs code will switch automatically and transparently.

@mihem
Copy link
Contributor Author

mihem commented Feb 4, 2025

I've tried this and it worked great.
I agree that this is also a great option, maybe even slightly better than the one I've used until now because you don't have to manually activate the shell and start R each time. And installing took <5min and was very painless.

@b-rodrigues
Copy link
Contributor

b-rodrigues commented Feb 4, 2025

I’ll be documenting this: #404

@mihem
Copy link
Contributor Author

mihem commented Feb 4, 2025

Good idea!
And sorry, they tell you to hook this into your shell, this is not necessary because the extension takes care of this?
Is there any other stuff I can do when I hook this into my shell? https://direnv.net/docs/hook.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants