emacs-ess / ESS

Emacs Speaks Statistics: ESS
https://ess.r-project.org/
GNU General Public License v3.0
613 stars 160 forks source link

Unable to view R dired environment for package development #1279

Open mtvincen opened 4 months ago

mtvincen commented 4 months ago

When using ESS to test package development the variables are written to a specific namespace for that package. I have been attempting to view the namespace that is created for the development package through the M-x ess-rdired while in the buffer that is creating the variables in the package namespace. However, I am only ever able to get the global environment. Is there a way to change the environment that R dired is displayed? Any help and increased documentation about this would be greatly appreciated!

maxecharel commented 4 months ago

Hi @mtvincen

Docstring of ess-rdired-mode tells us that ‘ess-rdired’ shows the list of current objects in the current environment.

Visiting the source of ess-rdired-mode:

  (add-hook 'tabulated-list-revert-hook #'ess-rdired-refresh nil t)

Looking at the source code of ess-rdired-refresh, we find that it first extracts the name of the inferior process contained in ess-local-process-name (it sets it to a local named proc) then use it as an argument when calling a variant of ess-command:

  (ess--foreground-command ess-rdired-objects out-buff nil nil nil proc)

We can see that this function sends the command ess-rdired-objects to the inferior process proc. It then collects the results and displays them in a dedicated buffer.

The value of ess-rdired-objects is ".ess.rdired()", which is defined as

function () 
{
    cat("\n")
    objs <- ls(envir = .GlobalEnv) ## !!! here it is
## TRUNCATED

Therefore, ESS R Dired list objects in the global environment, a feature that is hardcoded in the R function called by R Dired to get the list of objects. Changing this would require to modify the R function .ess.rdired() so that it accepts as an argument the name/identifier of the environment to map, then to create an 'interface' that allows the user to easily specify the environment scanned by ess-rdired-refresh and by extension ess-rdired-mode.

I hope this answers your question, at least partially. Implementing such a feature is certainly feasible, now the question is to know whether it is desirable given the intended purpose of R Dired.

mtvincen commented 4 months ago

@maxecharel thanks for the follow up. Would you be able to go through the ESS code and determine in which environment the variables from an R script in package mode are being stored? I've attempted to track this down but have been unsuccessful. I believe they are being archived in some way where they don't show up in the global environment, but not exactly sure how to get access to that information. Even if you don't eventually add it to the ess-rdired functionality it would allow me to run or create my own function to print out the information that I am looking for. Thanks

maxecharel commented 4 months ago

Hi, just to be sure that there is no misunderstanding: I am not an ESS maintainer, so basically the maximum I could do with my limited abilities would be to try to reshape the source of R Dired and submit a PR. Maybe at some point I will try to have a look at it, but cannot promise anything ;)

I think that your question is now more a R question than an ESS one. To the best of my knowledge, ESS does not force any package environment. Such environment is 'spontaneously' created by the inferior process when 'loading' the package. When you're working on your package (let's call it mypkg, and let's say it has been attached to the search path), you can list the objects in its environment with:

ls(envir = as.environment("package:mypkg")

I hope it answers your question.

mtvincen commented 4 months ago

I completely understand you're a volunteer with some knowledge of lisp and the package. I don't necessarily expect anything to change any time soon, as it's probably not a priority issue for most people.

I've tried the R function option that you have listed. However, this only seems to list out the functions that are exported by the package. It doesn't include any of the variables that are created when you run individual lines from within a script.

Looking at the ESS documentation (page 48: 10.3 Namedspace Environment) I found the following:

When developing packages, ESS sends code to the corresponding package namespace and (for visible objects) into package environment (visible on search path). All objects that are assigned are displayed in the minibuffer along side the environment in which they are assigned.

So it appears that the variables are sent to the namespace:mypkg but these are not viewable through the ls command because they are not searchable through the package:mypkg environment (i.e., not visible objects). I'm not entirely sure what minibuffer the package documentation is referring to though, so there might be some way to see this information that I'm not familiar with. I was thinking it might have something to do with an Rdired buffer, hence the original question.

maxecharel commented 4 months ago

Thanks for the info :) What about

ls(name = getNamespace("mypkg"))

? Possibly with the argument all.names=TRUE, if you have names starting with . I may dig into this issue more thoroughly end of this week. This will be the opportunity to enhance my knowledge: the internals of namespaces and environments are not trivial, so adjusting R Dired for what you want is clearly not an easy task (at least from my perspective). If you find a solution, keep me posted!