9

Recently, R witnessed the smart introduction of the piping operator %>% or then operator in code which I use quite frequently nowadays. I wonder if this has already been implemented in the newest version of ESS. If not, it shouldn't be a problem to come up with elisp code to write a function for it. I need to implement this so that it will print that operator %>% and then jumps to a new indented line.

MWE

library(ggplot2)
library(dplyr)    
diamonds %>%
      filter(cut=="Ideal") %>%
      ggplot(aes(price)) +
      geom_histogram() +
      facet_wrap (~ color)

My elisp trial - in .init.el or .emacs file:

(defun then_R_operator ()
  "%>% operator or 'then' pipe operator"
  (interactive)
  (insert " %>%") ; note the space before the first %
  (reindent-then-newline-and-indent))
(global-set-key (kbd "C-%") 'then_R_operator)  

It works, but I want to check if there is something wrong with it or are there any suggestions to improve it (being a newbie in elisp). How to restrict this only to ESS mode?

Note
I realized that font-locking of %>% can be done by enabling ess-fl-keyword:operatorsfrom the ESS menu.

Drew
  • 75,699
  • 9
  • 109
  • 225
doctorate
  • 1,789
  • 16
  • 39
  • I'd take care for the space character with `(just-one-space 1)` before the pipe. You want use the `ess-mode-map` (and propably the `inferior-ess-mode-map`) to set the key with `(define-key ess-mode-map (kbd "C-%") 'then_R_operator)`. – mutbuerger Feb 07 '15 at 14:24
  • thanks! what is the difference between the two: `inferior...` and `ess-mode...`? – doctorate Feb 07 '15 at 14:52
  • `ess-mode` activates itself when editing, e.g., `.R` files.`inferior-ess-mode` activates when running an interactive `R` process inside Emacs (i.e. through the `R` command or with `C-c C-z` which calls `ess-switch-to-inferior-or-script-buffer`). – undostres Feb 07 '15 at 17:50
  • @undostres thanks. do u mean if I want to define a key for this operator in the `inferior...` this will let me use it in the interactive R console, which is inside Emacs? if yes then I think it would be better to define keys for both `ess-mode` and `inferior`, right? – doctorate Feb 07 '15 at 18:01
  • @doctorate Yes. – undostres Feb 07 '15 at 20:52

2 Answers2

13

thanks to mutbuerger for the helpful comments. Currently, I use this for this operator to work with ESS only.

(defun then_R_operator ()
  "R - %>% operator or 'then' pipe operator"
  (interactive)
  (just-one-space 1)
  (insert "%>%")
  (reindent-then-newline-and-indent))
(define-key ess-mode-map (kbd "C-%") 'then_R_operator)
(define-key inferior-ess-mode-map (kbd "C-%") 'then_R_operator)
doctorate
  • 1,789
  • 16
  • 39
1

You can define a key binding for %>% with use-package:

(use-package ess
  :bind (:map ess-r-mode-map
         ("C-c >" . " %>% ")
         :map inferior-ess-r-mode-map
         ("C-c >" . " %>% ")))
aparkerlue
  • 317
  • 2
  • 8
  • You don't need `use-package` to do this. You can set the key with `define-key`, `global-set-key`, `local-set-key`, or however you like. Example: `(local-set-key (kbd "C-c >") " %>% ")`. – Dan Jun 03 '21 at 16:23