Indentation of Nested ifelse() by ESS

TL;DR:

  • Set ess-align-nested-calls to nil so that ESS would indent the nested ifelse() calls as usual.
  • The code snippet that works for me is as follows:
(add-hook 'ess-mode-hook
           (lambda ()
            (ess-set-style 'RRR)
            (setq ess-align-nested-calls nil)))

I use Emacs and the ESS package (Emacs Speaks Statistics) to edit R scripts, which has been working well out-of-the-box most of the time (thanks to the hard work by the package developers).

One minor “issue” that bothered me from time to time was, however, the indentation of nested ifelse() calls. For example, the default RRR style provided by ESS indents the following code (by M-x indent-region or C-M-\) as follows:

x <- ifelse(x == "foo", "bar",
     ifelse(x == "bar", "foo", "not-foo-or-bar"))
y <- alpha(x == "foo", "bar",
           ifelse(x == "bar", "foo", "not-foo-or-bar"))
z <- ifelse(x == "foo", "bar",
            alpha(x, "is not bar"))

Let’s ignore the dummy code that I made up and focus on the indentation style. We can find that the indentation style looks inconsistent. Why does ESS align the nested ifelse() call (at line 2) to its parent function call? It seems that this indentation inconsistency occurs only for nested ifelse() calls. Can it be a weird bug in ESS? The answer is no.

After looking into the ESS manual and all the available style configurations, I found that the particular behavior was caused by the variable ess-align-nested-calls whose default value is '("ifelse"). Clear documentation is available through c-h v ess-align-nested-calls. Therefore, I set ess-align-nested-calls to nil and resolved this “issue”. The previous code chunk now looks consistent and great to my eyes.

x <- ifelse(x == "foo", "bar",
            ifelse(x == "bar", "foo", "not-foo-or-bar"))
y <- alpha(x == "foo", "bar",
           ifelse(x == "bar", "foo", "not-foo-or-bar"))
z <- ifelse(x == "foo", "bar",
            alpha(x, "is not bar"))

I felt glad that I was able to figure this feature out on my own without bothering the ESS team. But why should the nested ifelse() be indented differently by default (except for the RStudio* style)? Hmm, I have no clue.

comments powered by Disqus