https://github.com/genovese/ess-smart-equals.git
git clone 'git://github.com/genovese/ess-smart-equals.git'
Assignment in R is syntactically complicated by three features: 1. the historical role of ‘’ (underscore) as an assignment character in the S language (SPlus may still allow this); 2. the somewhat inconvenient-to-type, if conceptually pure, ‘←’ operator as the preferred assignment operator; and 3. the ability to use either an ‘=’ or an ‘←’ for assignment.
ESS uses ‘’ as a (default) smart assignment character which expands to the ‘←’ with one invokation and gives an underscore on two. This makes it rather painful to use underscores in variable, field, and function names. Moreover, _ no longer has any association with assignment in R, so the mnemonic is strained.
It is possible to reassign the special underscore to another character, such as ‘=’, but that raises other inconviences because of the multiple roles that ‘=’ can play (assignment and default argument setting).
This package gives an alternative smart assignment for R and S code that is tied to the ‘=’ key instead of the ‘’ key. It intelligently handles the various ways that ‘=’ is used in R (and S) by examining the preceding context. It works under the assumption that ‘=’ used for default arguments to functions will not be surrounded by spaces but that binary operators involving ‘=’ should be. When this is enabled, underscore is completely divorced from assignment and thus can be used directly in names.
This package defines a global minor mode ess-smart-equals-mode
, that
when enabled for S-language modes causes the ‘=’ key to use the
preceding character to determine the intended construct (assignment,
comparison, default argument). Loosely speaking, an ‘=’ preceded by a
space is converted to an assignment, an ‘=’ preceded by a comparison
character (<>!=
) becomes a space-padded comparison operator, and
otherwise just an ‘=’ is inserted. The specific rules are as follows:
=<>!
preceed the current ‘=’, insert an ‘= ’, but
if no space preceeds the preceeding character, insert a space
so that the resulting binary operator is surrounded by spaces.With a prefix argument, ‘=’ always just inserts an ‘=’.
These insertions ensure that binary operators have a space on either end but they do not otherwise adjust spacing on either side. Note that in #4 above, the second ‘=’ key is assumed to be intended as an equality comparison because the assignment would have been produced by an ‘=’ following a space.
This package is available on MELPA, and you can install it with
M-x package-install ess-smart-equals
or through the list-packages
interface.
Alternatively, you can use Cask by putting
(depends-on "ess")
(depends-on "ess-smart-equals")
in the Cask file in your init directory and run
cask install
to update your dependencies.
Finally, you can put ess-smart-equals.el
anywhere on
your load-path
.
The package defines a minor mode ess-smart-equals-mode
that operates in all S-language-mode buffers (e.g., R-mode,
inferior-ess-mode, S-mode). The minor mode makes it
easy to enable and disable the smart equals functionality.
In any ess-mode buffer, toggle the mode with
M-x ess-smart-equals-mode
You will likely want the mode enabled automatically in the appropriate buffers, so put
(add-hook 'ess-mode-hook 'ess-smart-equals-mode)
(add-hook 'inferior-ess-mode-hook 'ess-smart-equals-mode)
in your .emacs
file. Of course, you will need to install
ess
first.
Here is an example .emacs
initialization that uses
the package use-package
to :
(use-package ess
:defer t
:pre-load (setq ess-R-smart-operators t) ; enables smart commas too
:init (autoload 'R-mode "ess-site"
"Major mode for editing R source. See `ess-mode' for more help."
t)
:config (progn
(eval-after-load 'ess-smart-equals
'(progn
(add-hook 'ess-mode-hook 'ess-smart-equals-mode)
(add-hook 'inferior-ess-mode-hook 'ess-smart-equals-mode)))
(use-package ess-smart-equals :ensure t)))
In the left column below, ^ marks the location at which an ‘=’ key is pressed, and in the right column it marks the resulting position of point.
Before '=' After '='
---------- ---------
foo ^ foo <- ^
foo ^ foo <- ^
foo(a^ foo(a=^
foo=^ foo == ^
foo<^ foo <= ^
"foo ^ "foo =^
#...foo ^ #...foo =^
foo <- ^ foo == ^