[ESS] Windows suggestion: ask registry for location of Rterm.exe

Paul Johnson pauljohn32 at gmail.com
Fri Jun 15 18:43:11 CEST 2012


I have a new idea on the "Rterm not found" problem that we see in
Windows sometimes. Ask the registry!

I wish I could do all this and show you the answer, but can't yet.
Before I forget what I've learned, I want to tell you, on the off
chance that this is an easy-ish problem for one of you.

The "Rterm not found" problem with Emacs-ESS is fairly frequent for
us.  Working with a class of 50 people, I suppose that 10-20 will have
trouble with Emacs-ESS because their R is not installed in the usual
place.  Emacs-ESS looks some places, but doesn't always find it. It
doesn't find Rterm.exe if we install R in C:\Program Files\R, for
example (no R version subdirectory).

I noticed that Rstudio and Notepad++(with NPPtoR) have no trouble
finding Rterm, no matter where it is installed.  So I started checking
into how those other editors do it, and the answer seems to be they
ask the registry for the newest R installation, unless user specifies
otherwise. It appears to me the registry access code in the batchfiles
project may be the most immediately relevant.


1. batchfiles

I learned of an R for Windows project called "batchfiles" which has
various idioms to find R by asking the registry.

https://code.google.com/p/batchfiles

I think it should be on the front of "runemacs" or such. It would run
every time Emacs-ESS starts, it would respect R_HOME in the user's
init.el file, but check registry optionally..

The batchfiles are written in the Windows Command language (which I
knew in 1994 or so:)). Here's what they do to find the R HOME. This
idiom is used in several of their script files:

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: use environment variable R_HOME if defined
:: else current folder if bin\rcmd.exe exists
:: else most current R as determined by registry entry
:: else error
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

if not defined R_HOME if exist bin\r.exe set R_HOME=%CD%
if not defined R_HOME for /f "tokens=2*" %%a in (
 'reg query hklm\software\R-core\R /v InstallPath 2^>NUL ^| findstr InstallPath'
  ) do set R_HOME=%%~b
if not defined R_HOME for /f "tokens=2*" %%a in (
 'reg query hklm\software\wow6432Node\r-core\r /v InstallPath 2^>NUL
^| findstr InstallPath'
  ) do set R_HOME=%%~b
if not defined R_HOME echo "Error: R not found" & goto:eof

In rterm.bat, you see they have a routine to guess the arch subfolder
and then it pieces together a command.

Can we launch Command scripts from inside LISP?

2. NPPtoR

In NPPtoR, http://sourceforge.net/projects/npptor/files/npptor%20source%20code/

The code is written in a language unfamilar to me (suffix ahk) but the
idea is clear enough.  Here's a subroutine "findRHome"

findRHome:
{
; 1. check command line
; 2. check RHOME variable
; 3. check path
; 4. check registry
; 5. check assumed locations
  if Rhome =
  {
    EnvGet , Rhome, RHOME
  }
  if Rhome =
  {
    Rscriptexe = findInPath("Rcript.exe")
    if Rscriptexe <>
      Rhome = cmdCapture(Rscriptexe . " --vanilla -e `"cat(R.home())`"")
  }
  if Rhome =
  {
    RegRead, Rdir, HKEY_LOCAL_MACHINE, SOFTWARE\R-core\R, InstallPath
    Rhome= %Rdir%
    if Rdir=
      Rdir := RegRead64("HKEY_LOCAL_MACHINE", "SOFTWARE\R-core\R",
"InstallPath")
    Rhome= %Rdir%
  }
  if Rhome =
 {
    curfiletime = 0
    ifExist C:\Program Files (x86)\R
      Loop , C:\Program Files (x86)\R\* , 2, 0
      {
        FileGetTime , filetime, %A_LoopFileFullPath%, C
        if(filetime>curtime)
        {
          curtime := filetime
          Rhome= %A_LoopFileFullPath%
        }
      }
    ifExist C:\Program Files\R
      Loop , C:\Program Files\R\* , 2, 0
      {
        FileGetTime , filetime, %A_LoopFileFullPath%, C
        if(filetime>curtime)
        {
          curtime := filetime
          Rhome= %A_LoopFileFullPath%
        }
      }
  }
  return

3. RStudio

The Rstudio code is available here: http://rstudio.org/download/desktop

Rstudio is written in C++,. which is a bit more familiar to me, but
its routines to find R are harder to isolate. I was encouraged when I
found this stanza:

From: src/cpp/desktop/DesktopRVersion.cpp
/*
Looks for a valid R directory in the following places:
- Value of %R_HOME%
- Value of HKEY_LOCAL_MACHINE\Software\R-core\R at InstallPath
    (both 32-bit and 64-bit keys)
- Values under HKEY_LOCAL_MACHINE\Software\R-core\R\*@InstallPath
    (both 32-bit and 64-bit keys)
- Enumerate %ProgramFiles% directory (both 32-bit and 64-bit dirs)

If forceUi is true, we always show the picker dialog.
Otherwise, we try to do our best to match the user's specified wishes,
and if we can't succeed then we show the picker dialog.
*/
RVersion detectRVersion(bool forceUi, QWidget* parent)
{
   Options& options = desktop::options();

   RVersion rVersion(options.rBinDir());

   if (!forceUi)
   {
      if (!rVersion.isEmpty())
      {
         // User manually chose an R version. Use it if it's valid.
         if (rVersion.isValid())
            return rVersion;
      }
      else
      {
         // User wants us to autodetect (or didn't specify--autodetect
         // is the default).
         RVersion autoDetected = autoDetect();
         if (autoDetected.isValid())
            return autoDetected;
      }
   }

   // Either forceUi was true, xor the manually specified R version is
   // no longer valid, xor we tried to autodetect and failed.
   // Now we show the dialog and make the user choose.

   ChooseRHome dialog(allRVersions(QList<RVersion>() << rVersion), parent);
   dialog.setValue(rVersion, options.preferR64());
   if (dialog.exec() == QDialog::Accepted)
   {
      // Keep in mind this value might be "", if the user indicated
      // they want to use the system default. The dialog won't let
      // itself be accepted unless a valid installation is detected.
      rVersion = dialog.value();
      options.setRBinDir(rVersion.binDir());
      if (rVersion.isEmpty())
         options.setPreferR64(dialog.preferR64());

      // Recurse. The ChooseRHome dialog should've validated that
      // the values are acceptable, so this recursion will never
      // go more than one level deep (i.e. this call should never
      // result in the dialog being shown again).
      return detectRVersion(false, parent);
   }

   // We couldn't autodetect a string and the user bailed on the
   // dialog. No R_HOME is available.
   return QString();
}

Even though this seems promising, it refers the work of finding R in
the registry to other functions, and I'm not able to put my finger on
a single one to imitate.  If you look at this file,

src/cpp/desktop/DesktopWin32DetectRHome.cpp



-- 
Paul E. Johnson
Professor, Political Science    Assoc. Director
1541 Lilac Lane, Room 504     Center for Research Methods
University of Kansas               University of Kansas
http://pj.freefaculty.org            http://quant.ku.edu



More information about the ESS-help mailing list