19

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?

aL3xa
  • 35,415
  • 18
  • 79
  • 112

5 Answers5

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.

Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • 6
    +1 I'm lost in the same desert as Hadley, but I'll give you +1 for linking to XKCD. – Andrie Sep 21 '11 at 15:55
  • 2
    ==:-) 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! ;-) – Dirk Eddelbuettel Sep 21 '11 at 15:56
  • 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. =) – aL3xa Sep 21 '11 at 15:56
  • 3
    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. – Dirk Eddelbuettel Sep 21 '11 at 15:58
  • 2
    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. – Dirk Eddelbuettel Sep 21 '11 at 16:00
  • My brain isn't big enough to hold all those keyboard shortcuts. – Andrie Sep 21 '11 at 16:01
  • 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. – Dirk Eddelbuettel Sep 21 '11 at 16:01
  • 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. =/ – aL3xa Sep 21 '11 at 16:03
  • 2
    @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!!! =) – aL3xa Sep 21 '11 at 16:04
  • 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. – Dirk Eddelbuettel Sep 21 '11 at 16:05
  • OK, @DirkEddelbuettel, but, don't you sometimes want those pretty spaces around operators, spaces after commas... I mean, c'mon... =) – aL3xa Sep 21 '11 at 16:17
  • 1
    Yes, I much prefer "if (foo) {" to "if(foo){" but I guess I must still be doing that by hand... – Dirk Eddelbuettel Sep 21 '11 at 16:20
  • But why?!? O_o Save your keystrokes, joint arthritis is lurking around the corner! =) – aL3xa Sep 21 '11 at 16:56
  • @Dirk: just for you, I need to photoshop it so the vim guy is hitting him with an underscore. ;-) – Joshua Ulrich Sep 22 '11 at 15:45
  • Same with the timeless one involving the horse... of which this is reminding me a tad now ;-) – Dirk Eddelbuettel Sep 22 '11 at 15:55
  • @DirkEddelbuettel Here's a new one for you. http://images2.wikia.nocookie.net/__cb20080202231409/uncyclopedia/images/1/11/Beating-a-dead-horse.gif – Shane Sep 25 '11 at 16:19
  • Wow that guy is on a mission. I like his classic outfit though. – Dirk Eddelbuettel Sep 25 '11 at 16:26
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.

Lionel Henry
  • 6,652
  • 27
  • 33
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)
Community
  • 1
  • 1
VitoshKa
  • 8,387
  • 3
  • 35
  • 59
  • Perfect! And it also answers another rant of mine: http://stackoverflow.com/questions/7803317/emacs-mode-function-that-wraps-operators-with-spaces – aL3xa Oct 25 '11 at 18:01
  • See also [electric-operator](https://github.com/davidshepherd7/electric-operator) which is similar to smart-operator but has native support for R. – dshepherd Apr 03 '16 at 10:41
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.

Giupo
  • 413
  • 2
  • 9
  • 1
    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. – doctorate Jan 22 '16 at 09:26
  • 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]` – Giupo Mar 26 '18 at 10:09
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.

dshepherd
  • 4,989
  • 4
  • 39
  • 46