emacs-ess / ESS

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

Add support for R projects and integrate with `project.el` #1179

Closed vspinu closed 2 years ago

vspinu commented 2 years ago

We currently have project.el integration for R packages as part of ess-r-package.el and we have experimental support for starting R in project root here

Proposal:

  1. Add project.el support for arbitrary R projects (those containing .Rprofile or XYZ.Rproj)
  2. Make R (and others) start in project root by default

Once the above is done can look into session management functionality as provided by sesman (#914, #1172 cc @tpeacock19).

@lionel- proposed (2.) years ago and if I recall correctly we even tried it once, but there were a few edge cases. I think the edge cases are really edge and the benefits outweigh the drawbacks.

A quick local hack which works for me



;;;*;;; Project detection

(defvar-local ess-r-project--info-cache nil
  "Current package info cache.
See `ess-r-project-info' for its structure.")

(defun ess-r-project (&optional dir)
  "Return the current project as an Emacs project instance.
R project is a directory containing either .Rprofile or XYZ.Rproj
file. Return a list of the form (:name \"XYZ\" :root
\"/path/to/project\"). If DIR is provided, the project is
searched from that directory instead of `default-directory'."
  (let ((info (ess-r-project-info dir)))
    (when (car info)
      (cons 'ess-r-project (plist-get info :root)))))

(cl-defmethod project-roots ((project (head ess-r-project)))
  "Return the project root for ESS R projects."
  (list (cdr project)))

(cl-defmethod project-root ((project (head ess-r-project)))
  "Return the project root for ESS R projects."
  (cdr project))

(defun ess-r-project-info (&optional dir)
  "Get the description of the R project in directory DIR.
Return an plist with the keys :name and :root. When not in a
project return '(nil). This value is cached buffer-locally for
efficiency reasons."
  (if (and (null dir)
           (car ess-r-project--info-cache))
      ess-r-project--info-cache
    (let ((dir (locate-dominating-file (or dir
                                           (buffer-file-name)
                                           default-directory)
                                       ".Rprofile")))
      (when dir
        (let ((dir (directory-file-name dir)))
          (setq ess-r-project--info-cache
                (list :name (file-name-nondirectory dir) :root dir)))))))