Make Emacs ESS follow R style guide
Asked Answered
T

5

20

I've been using Emacs/ESS for quite a while, and I'm familiar with Hadley's R style recommendations. I'd like to follow these conventions in ESS, like those nice spaces around operators, space after comma and after if statement, before curly braces, etc.

Did anyone even bothered to follow this style guide at all? IMHO, official style recommendations are quite modest, and they say nothing about the style whatsoever. Google R style guide are too similar with the ones I use when I code in JavaScript, so it's a no-no.

Long story short: is there anyone with (e)LISP skills willing to implement (Hadley's) style guide for ESS?

Totality answered 21/9, 2011 at 15:35 Comment(0)
A
6

The good point of Hadley's guide is spaceing around operators (except maybe around /)

There is a smart-operator package which implements it for almost every operator.

This is my setup (uncoment operators which you want to use):

(setq smart-operator-mode-map
  (let ((keymap (make-sparse-keymap)))
    (define-key keymap "=" 'smart-operator-self-insert-command)
    ;; (define-key keymap "<" 'smart-operator-<)
    ;; (define-key keymap ">" 'smart-operator->)
    ;; (define-key keymap "%" 'smart-operator-%)
    (define-key keymap "+" 'smart-operator-+)
    ;; (define-key keymap "-" 'smart-operator--)
    ;; (define-key keymap "*" 'smart-operator-*)
    ;; (define-key keymap "/" 'smart-operator-self-insert-command)
    (define-key keymap "&" 'smart-operator-&)
    (define-key keymap "|" 'smart-operator-self-insert-command)
    ;; (define-key keymap "!" 'smart-operator-self-insert-command)
    ;; (define-key keymap ":" 'smart-operator-:)
    ;; (define-key keymap "?" 'smart-operator-?)
    (define-key keymap "," 'smart-operator-,)
    ;; (define-key keymap "." 'smart-operator-.)
    keymap)
  "Keymap used my `smart-operator-mode'.")

See also a nice discussion on R styles here.

[edit] I am also using the defacto camelCase style of R code for globals. The underscore-separated names for local variables - it's easy to differentiate.

There is a special subword mode in emacs which redefines all editing and navigation commands to be used on capitalized sub-words

(global-subword-mode)
Ageless answered 25/10, 2011 at 14:30 Comment(2)
Perfect! And it also answers another rant of mine: #7803817Totality
See also electric-operator which is similar to smart-operator but has native support for R.Carine
S
29

I don't write Elisp, and I disagree with Hadley about the stylistic merits of underscores. Moreover, Hadley is still lost in the desert of not using the OneTrueEditor so we can expect no help from him on this on this issue.

But if you are open to follow R Core rather than Hadley, below is what the R Internals manual, section 8. "R Coding Standards" recommends. To me, it is R Core who defines R style first and foremost. Google's and Hadley's styles are nice secondary recommendations.

Anyway, back to Elisp. The following has served we well for many years, and I do like the fact that the basic R behaviour is similar to the Emacs C++ style as I happen to look at code in both modes a lot.

[...]

It is also important that code is written in a way that allows others to understand it. This is particularly helpful for fixing problems, and includes using self-descriptive variable names, commenting the code, and also formatting it properly. The R Core Team recommends to use a basic indentation of 4 for R and C (and most likely also Perl) code, and 2 for documentation in Rd format. Emacs (21 or later) users can implement this indentation style by putting the following in one of their startup files, and using customization to set the c-default-style' to"bsd"' and c-basic-offset' to4'.)

 ;;; ESS
 (add-hook 'ess-mode-hook
           (lambda ()
             (ess-set-style 'C++ 'quiet)
             ;; Because
             ;;                                 DEF GNU BSD K&R  C++
             ;; ess-indent-level                  2   2   8   5  4
             ;; ess-continued-statement-offset    2   2   8   5  4
             ;; ess-brace-offset                  0   0  -8  -5 -4
             ;; ess-arg-function-offset           2   4   0   0  0
             ;; ess-expression-offset             4   2   8   5  4
             ;; ess-else-offset                   0   0   0   0  0
             ;; ess-close-brace-offset            0   0   0   0  0
             (add-hook 'local-write-file-hooks
                       (lambda ()
                         (ess-nuke-trailing-whitespace)))))
 (setq ess-nuke-trailing-whitespace-p 'ask)
 ;; or even
 ;; (setq ess-nuke-trailing-whitespace-p t)
 ;;; Perl
 (add-hook 'perl-mode-hook
           (lambda () (setq perl-indent-level 4)))

(The `GNU' styles for Emacs' C and R modes use a basic indentation of 2, which has been determined not to display the structure clearly enough when using narrow fonts.)

I think the only additions I regularly make are to follow the last commented-out snippet:

;; or even
(setq ess-nuke-trailing-whitespace-p t)

You can of course turn off the underscore toggle if you really need to code with underscores.

Stockpile answered 21/9, 2011 at 15:44 Comment(17)
+1 I'm lost in the same desert as Hadley, but I'll give you +1 for linking to XKCD.Commentary
==:-) I knew someone would get a kick out of it. Editor wars and style issues are way to personal anyway to be taken all that seriously. That said, time you switch to Emacs, son! ;-)Stockpile
I sense some bad interpersonal vibes 'round here... =( I won't discuss that one, though... I still admire both Hadley's and your work (I don't speak C/C++, so no Rcpp for me, but I tend to use littler more than Rscript). After all, I started using Emacs/ESS on your recommendation. I honestly believe that it's possible to get a useful mash-up of code from various sources. And I'd really want to see your .emacs tweaks related to R. =)Totality
Ahh, it's all just friendly jestering. I love Hadley almost as much as the next guy, but the underscores still keep me awake at night. Not to mention the pastel colours in ggplot. Ouch.Stockpile
That said, I'd be all for someone writing an ESS setup for his style, and/or for Google's. The more the merrier. Until then, I am rather content with what R Core has provided.Stockpile
My brain isn't big enough to hold all those keyboard shortcuts.Commentary
You really only need a dozen or os, and if you select the commands by mouse, Emacs reminds you of the keyboard shortcuts. It is pretty easy to glide into this.Stockpile
FWIW, I'm an anti-fan of pastel colours in ggplot2. But girls seem to love them, and since there's a plenty of estrogen swarming around in department of psychology, I have no worries when choosing the colour theme - the default one works just fine. Though the underscore solution is a bit uptight in ESS. But, to hell with it... it's a convention, you don't ask question, you just obey them. =/Totality
@Andrie, it may seem overwhelming at first, but you'll get used to this after a while... Dammit, you'll even start adding your own!!! =)Totality
There is a toggle too. AFAICT it really is an old shortcut from when folks used to press a single _ to get ESS to insert <- for them.Stockpile
OK, @DirkEddelbuettel, but, don't you sometimes want those pretty spaces around operators, spaces after commas... I mean, c'mon... =)Totality
Yes, I much prefer "if (foo) {" to "if(foo){" but I guess I must still be doing that by hand...Stockpile
But why?!? O_o Save your keystrokes, joint arthritis is lurking around the corner! =)Totality
@Dirk: just for you, I need to photoshop it so the vim guy is hitting him with an underscore. ;-)Glandular
Same with the timeless one involving the horse... of which this is reminding me a tad now ;-)Stockpile
@DirkEddelbuettel Here's a new one for you. images2.wikia.nocookie.net/__cb20080202231409/uncyclopedia/…Gardy
Wow that guy is on a mission. I like his classic outfit though.Stockpile
S
23

With the development version of ESS (to be released in September 2015), just add to your ess-mode-hook:

(ess-set-style 'RStudio)

RStudio also has a 'Vertically align arguments' checkbox that is set by default. If you want to reproduce the behaviour when this setting is unchecked (as in Hadley's code), you'll need to change ess-offset-arguments to prev-line:

(setq ess-offset-arguments 'prev-line)

Please file an issue on https://github.com/emacs-ess/ESS if you find an important discrepancy between ESS and RStudio indentation.

Sombrero answered 9/8, 2014 at 13:26 Comment(0)
A
6

The good point of Hadley's guide is spaceing around operators (except maybe around /)

There is a smart-operator package which implements it for almost every operator.

This is my setup (uncoment operators which you want to use):

(setq smart-operator-mode-map
  (let ((keymap (make-sparse-keymap)))
    (define-key keymap "=" 'smart-operator-self-insert-command)
    ;; (define-key keymap "<" 'smart-operator-<)
    ;; (define-key keymap ">" 'smart-operator->)
    ;; (define-key keymap "%" 'smart-operator-%)
    (define-key keymap "+" 'smart-operator-+)
    ;; (define-key keymap "-" 'smart-operator--)
    ;; (define-key keymap "*" 'smart-operator-*)
    ;; (define-key keymap "/" 'smart-operator-self-insert-command)
    (define-key keymap "&" 'smart-operator-&)
    (define-key keymap "|" 'smart-operator-self-insert-command)
    ;; (define-key keymap "!" 'smart-operator-self-insert-command)
    ;; (define-key keymap ":" 'smart-operator-:)
    ;; (define-key keymap "?" 'smart-operator-?)
    (define-key keymap "," 'smart-operator-,)
    ;; (define-key keymap "." 'smart-operator-.)
    keymap)
  "Keymap used my `smart-operator-mode'.")

See also a nice discussion on R styles here.

[edit] I am also using the defacto camelCase style of R code for globals. The underscore-separated names for local variables - it's easy to differentiate.

There is a special subword mode in emacs which redefines all editing and navigation commands to be used on capitalized sub-words

(global-subword-mode)
Ageless answered 25/10, 2011 at 14:30 Comment(2)
Perfect! And it also answers another rant of mine: #7803817Totality
See also electric-operator which is similar to smart-operator but has native support for R.Carine
C
4

Having the same style preference of the OP, I jumped here and I thank @lionel for your valid suggestions, but I had an issue coming from setting RStudio style in ~/emacs.d/init.el with:

(ess-set-style 'RStudio)

Emacs/ESS refused to apply the style (4-space indent instead of the 2-space, not discussing style here :) ).

My advice for the novice, using the following hook in your ~/emacs.d/init.el:

(add-hook 'find-file-hook 'my-r-style-hook)
(defun my-r-style-hook ()
  (when (string-match (file-name-extension buffer-file-name) "[r|R]$")
    (ess-set-style 'RStudio)))

will do the trick.

Cindacindee answered 19/1, 2016 at 9:29 Comment(2)
back to lionel's answer, it worked well with me. Did you check the ess-style variable? just type M-: ess-style and you should get the Rstudio style.Srinagar
Disregard my answer! I was not setting the ess-mode-hook correctly. My solution just adds a hook for opening all the files ending with [r|R]Cindacindee
C
1

One more component of the style guide which hasn't been covered here so far is indentation when a function runs over multiple lines. The style guide says to use indentation like

long_function_name <- function(a = "a long argument", 
                               b = "another argument",   # X
                               c = "another long argument") {
  # As usual code is indented by two spaces.
}

but using any of the default styles seems to indent line X by some fixed number of spaces rather than up to the (. The solution is to set ess-arg-function-offset to some non-number, e.g.

(set 'ess-arg-function-offset t)

This should be placed in a mode hook similar to @Dirk Eddelbuettel's answer. Also it must go after any calls to ess-set-style or it will be overridden.

Carine answered 10/3, 2015 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.