I am trying to disable the underscore thing in ESS where it gets converted to a <- . If I add

(add-hook 'ess-mode-hook
   (lambda ()
      (ess-toggle-underscore nil)))

To my init file, it works for the first R file I open, but as soon as I open a second R file, the behavior is back there. Is there anyway to completely disable this?

2 Answers 2


I have this in my config file:

;; smart assign
(setq ess-smart-S-assign-key ";")  ;if ";" needed, press ";" key twice
(ess-toggle-S-assign nil)
(ess-toggle-underscore nil) ;leave underscore key alone!

With the later versions of ESS the following is sufficient:

;; Must be specified before loading ESS.
(setq ess-smart-S-assign-key ";")  ;if ";" needed, press ";" key twice

;; Just a package manager, this can be ignored.
(use-package ess
  :ensure t)

(require 'ess-site)
(require 'ess-rutils)

With ESS version 18.10.3 (maybe even a slightly earlier versions), you can just do this:

(require 'ess-site)
(require 'ess-rutils)

(dolist (map (list ess-mode-map inferior-ess-mode-map))
  (define-key map (kbd ";") 'ess-insert-assign))
  • I guess that sort of works, but why would they force that sort of behavior? Commented May 29, 2018 at 11:53
  • Do you mean using the underscore for <-? It's just easier to type I guess, I prefer using ";" -- one key press only.
    – Arktik
    Commented May 29, 2018 at 11:59
  • S-Plus allowed "_" as a synonym for "<-" (variables were named like var.name; var_name would not have worked). It was not a good feature.
    – James King
    Commented Jun 13, 2020 at 3:13

Edited on July 11, 2018 after I realized that my function was not working with the latest ESS version anymore.

To change this behaviour, you can use the customize-variable function for ess-smart-S-assign and change the "Ess Smart S Assign Key" value to "Nothing",

or you can write in your init file:

(setq ess-insert-assign nil)

ess-insert-assign replaces the now obsolete ess-smart-S-assign function, though this latter is maintained as an alias for backward compatibility. So, this works as well:

(setq ess-smart-S-assign nil)

I did not like the default behaviour either, but I use yasnippet to autocomplete the assignment sign, which is rather uneasy to type.

To try to answer your question:

why would they force that sort of behavior?

It might be that the reason ess-mode-hook doesn't work has to do with the way keyboard remapping works, rather than a stubborn behaviour.

ess-mode-hook does work for other things, but this keyboard remapping seems to follow some particular rules:

In the customization option page for this variable, there is this information: "You may change this to nil at any time. However, if you change it to another string, it must be set before ESS is loaded." So it seems that this has to be changed before loading ESS. Since you were trying to change the default value to "nil", it is unclear to me why this was not working after loading ESS though. I used to be able to disable it with:

(eval-after-load 'ess-site
'(ess-toggle-underscore nil))

but this recently stopped working.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.