Using Purpose, you can try the following. Note that I don't really know R, so you need to fill in the code for creating the *R-main*
buffer.
Also, if you open more than 2 files with the same name, then Emacs will start playing with their buffer names. To fix this, use a proper regexp in bmag-R-purpose-conf
(exact regexp depends the value of uniquify-buffer-name-style
).
;; define purposes suitable for R projects
(defvar bmag-R-purpose-conf (purpose-conf
"R-project"
;; R files are considered "code" buffers
:regexp-purposes '(("\\.R$" . code))
;; the *R-main* buffer is considered a "repl"
;; buffer.
;; the project_log.org buffer is considered a
;; "log" buffer
:name-purposes '(("*R-main*" . repl)
("project_log.org" . log))))
;; mysterious incantation - generated with `purpose-save-window-layout'
(defvar bmag-R-layout
'(t
(0 0 92 36)
(nil
(0 0 92 18)
;; top-left window is dedicated to "code" buffers (R files)
(:purpose code :purpose-dedicated t :width 0.5 :height 0.5 :edges
(0.0 0.0 0.5 0.5))
;; top-right window is dedicated to "repl" buffers (*R-main*)
(:purpose repl :purpose-dedicated t :width 0.5 :height 0.5 :edges
(0.5 0.0 1.0 0.5)))
(nil
(0 18 92 36)
;; bottom-left window is not dedicated, but will initialy show a "log"
;; buffer (project_log.org)
(:purpose log :purpose-dedicated nil :width 0.5 :height 0.5 :edges
(0.0 0.5 0.5 1.0))
;; bottom-right window is not dedicated, but will initialy show a dired
;; buffer
(:purpose dired :purpose-dedicated nil :width 0.5 :height 0.5 :edges
(0.5 0.5 1.0 1.0)))))
(defun bmag-project-root ()
"Get project's root directory."
(expand-file-name (read-directory-name "Project root directory: " nil nil t)))
(defun bmag-file-in-project (root name)
(file-truename (concat root name)))
(defun bmag-open-R-project ()
(interactive)
(let ((root (bmag-project-root)))
(purpose-mode)
;; activate Purpose configuration for current project
(purpose-set-extension-configuration :project bmag-R-purpose-conf)
;; make current frame display windows as specified in `bmag-R-layout'
(purpose-set-window-layout bmag-R-layout)
;; open relevant buffers. Purpose takes care of displaying them in the correct windows
(dired root)
(find-file (bmag-file-in-project root "/project_log.org"))
(find-file (bmag-file-in-project root "/main.R"))
;; --- insert code for creating *R-main* here ---
))
You can adapt this solution to other languages. For example, Python:
(defvar bmag-python-purpose-conf
(purpose-conf "python-project"
:mode-purposes '((python-mode . code)
(inferior-python-mode . repl))
:name-purposes '(("project_log.org" . log))))
;; note: `bmag-python-layout' is identical to `bmag-R-layout'
(defvar bmag-python-layout
'(t
(0 0 92 36)
(nil
(0 0 92 18)
(:purpose code :purpose-dedicated t :width 0.5 :height 0.5 :edges
(0.0 0.0 0.5 0.5))
(:purpose repl :purpose-dedicated t :width 0.5 :height 0.5 :edges
(0.5 0.0 1.0 0.5)))
(nil
(0 18 92 36)
(:purpose log :purpose-dedicated nil :width 0.5 :height 0.5 :edges
(0.0 0.5 0.5 1.0))
(:purpose dired :purpose-dedicated nil :width 0.5 :height 0.5 :edges
(0.5 0.5 1.0 1.0)))))
(defun bmag-open-python-project ()
(interactive)
(let ((root (bmag-project-root)))
(purpose-mode)
(purpose-set-extension-configuration :project bmag-python-purpose-conf)
(purpose-set-window-layout bmag-python-layout)
(dired root)
(find-file (bmag-file-in-project root "/project_log.org"))
(find-file (bmag-file-in-project root "/main.py"))
(python-shell-switch-to-shell)))
If you use Projectile (or an equivalent package), you could use it to get the project's root directory automatically.