Remote pair programming in R using Visual Studio Code and Live Share
- The Problem
- State of the Code Editors
- Installation
- Configuration
- Writing an R Package Using VS Code
- Live Share Tutorial
- Final Thoughts
The problem
Way back in the Before Time, my older brother and I worked together on an R package called {wizehiver}. To collaborate, we used many tools. We had an email thread (of over 35 emails!) that eventually became two email threads. We tried GitHub Issues, but we were in such close communication that the back-and-forth on issues was ineffectual. We also tried pair programming but since we lived in separate cities, we did it while one of us would share our screen on Skype. We wished there was a better, more hands-on, and immediate way to collaborate in a source code editor in real-time, similar to how seamless it is to work on Google Docs.
State of the code editors
The RStudio IDE is in our opinion the best IDE for R out there; however, live collaboration using RStudio’s Project Sharing feature is limited to those with a paid RStudio Server Pro license as of this writing. There are many source code editors out there, and notably Atom and Visual Studio (VS) Code both provide extensions for free, collaborative real-time editing.
We have been following, with increasing interest, the growing community of developers who have been focused on tools for R in VS Code. There are now several R packages, VS Code extensions, and a command-line R console available, as well as several tutorials dedicated to R in VS Code. Here we set out to see if VS Code could fill the particular gap we identified in our previous work together — the need for seamless remote pair programming. A few of our use cases are:
We wanted to collaborate on this blog post in a shared
.Rmd
file which we could edit and knit as we wrote. Ultimately we wrote most of this post on Google Docs before transferring it to a versioned.Rmd
on GitHub for finishing touches.We wanted to start collaborating on an open-source R package {mutagen} which will (someday) provide useful extensions to {dplyr}’s
mutate()
:
So far, we only have a hex sticker — #hexdrivendevelopment in action!
but… I… already… know… how… the… hexsticker… should… look…
— Thomas Lin Pedersen (@thomasp85) July 26, 2018
Embarrassingly, our last commit to the package was in December 2019. While it would be convenient to blame the pandemic, it was a mix of being busy and other ‘hobby’ projects. However, having a synchronous way of collaborating—where we could see the package being built in action—would enable us to truly get the project underway. Before we begin the tutorial, first we have a public service announcement: if you would like to see Microsoft devote additional resources to support R in VS Code, please upvote R in this vscode-jupyter
issue!
Installation
We’re going to use Homebrew to facilitate installation steps on macOS. We only provide instructions for macOS here, but we do provide links for macOS users who prefer to install applications using the point-and-click method, and for Linux and Windows users to find the correct binaries. We also indicate which steps are optional.
Open Applications > Utilities > Terminal.
Install Homebrew using the terminal command below, also provided on the Homebrew landing page. Paste this code into your terminal:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- (Optional) For our favorite free and open-source terminal on macOS, install iTerm2 by pasting this into your terminal:
brew install --cask iterm2
- If you don’t have them already, you’ll need R and RStudio Desktop. We’re partial to the preview version of RStudio Desktop which has all the latest features. You can install (and update) them easily from your terminal:
brew install --cask r
brew tap homebrew/cask-versions
brew install --cask rstudio-preview
- Install
radian
, a ‘21st century R console’ and the recommended R console for VS Code.
Update 2021-02-11: Thanks to the efforts of @jdblischak
and @randy3k
in this closed issue, radian
can now be installed with conda-forge
instead of only with pip
. Most data science tutorials recommend using Python with conda
environments, so we suspect that our readers will be more familiar with using conda
than pip
, as we are. If you do choose to use pip
(or python -m pip
), beware that pip
should be used carefully inside conda
environments.
The steps below first install Miniforge, which we prefer to Miniconda since it sets conda-forge
as the default channel, then create an empty conda
environment named r-console
into which we install radian
and jedi
. jedi
is an optional package that enables Python autocompletion using the {reticulate} R package. Paste this into your terminal:
brew install miniforge
conda create --name r-console
conda activate r-console
conda install radian
conda install jedi # for {reticulate} python autocompletion
- In RStudio, install the required R packages for VS Code, namely {languageserver} from CRAN and the latest GitHub release of {vscDebugger}:
install.packages("languageserver")
::install_github("ManuelHentschel/vscDebugger", ref = remotes::github_release()) remotes
For the tutorial, make sure that you have the following R packages installed, if you don’t already:
install.packages("devtools")
install.packages("dplyr")
install.packages("purrr")
install.packages("tibble")
install.packages("usethis")
install.packages("vctrs")
- Install VS Code by pasting this into your terminal:
brew install --cask visual-studio-code
- Open VS Code and install the following extensions from the Extensions gallery (
Shift-Command-X
):
Configuration
- Make sure the
r-console
environment is still active in your terminal. If it is, your terminal prompt will look like this, or similar:
(r-console) ~ %
If not, then reactivate the r-console
environment:
conda activate r-console
- Type
which radian
in your terminal to display the path to theradian
executable. Below is what it is on our local machines. Copy the path to your clipboard.
/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian
- Determine whether
bash
orzsh
is your default shell. If you don’t know, type this into your terminal:
echo $SHELL
Older Macs may still use bash
, while newer Macs or those with older Macs who have created new user accounts since upgrading to macOS Catalina will likely run zsh
, the new default macOS shell.
- Let’s take VS Code for a spin! An useful feature to know about is that typing
code <path/file.ext>
in your terminal will open a new or existing file in VS Code at the path you specify. Many more details are available in the help pagecode -h
. Depending on whether your default shell isbash
orzsh
, typecode ~/.bashrc
orcode ~/.zshrc
in your terminal to open your shell configuration file, and paste the path you copied in step 2. above to add an alias toradian
and bind it to lowercaser
:
alias r="/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian"
You can paste the alias anywhere in the file, but it is probably best to paste it at the very bottom, and avoid inserting it in any preexisting code blocks (e.g., conda initialize
blocks) which may be overwritten. Save your configuration file and restart your terminal for the settings to take effect. Now all you need to open radian
is to type r
in any terminal (Terminal, iTerm2, RStudio, or VS Code)! Useful radian
commands to know are:
q() # to exit R, same as with vanilla R and RStudio
; # to enter shell mode, exit by pressing backspace on an empty line
~ # to enter {reticulate} python mode, exit by pressing backspace on an empty line
- To configure your
.Rprofile
, typecode ~/.Rprofile
in your terminal, or if you are already set up with {usethis} in RStudio, run the R commandusethis::edit_r_profile()
. At a minimum, you will want to enable {rstudioapi} emulation in VS Code:
options(vsc.rstudioapi = TRUE)
- To configure
radian
, typecode ~/.radian_profile
in your terminal which will open up a new blank editor and create a new file named.radian_profile
in the home directory. This is our.radian_profile
:
options(
radian.insert_new_line = FALSE,
radian.escape_key_map = list(
list(key = "-", value = " <- "),
list(key = "m", value = " %>% ")
) )
Save ~/.radian_profile
and restart your terminal for the settings to take effect.
- Now we’ll configure VS Code settings. Open VS Code, and navigate to
settings.json
by using the Command Palette (Shift-Command-P
) and navigating toPreferences: Open Settings (JSON)
. This is oursettings.json
:
{
// Liveshare: Prompt when receiving focus requests
"liveshare.focusBehavior": "prompt",
// R: Treat`names.like.this` as one word for selection
"[r]": {
"editor.wordSeparators": "`~!@#%$^&*()-=+[{]}\\|;:'\",<>/?"
},
// R: Use active terminal for all commands
"r.alwaysUseActiveTerminal": true,
// R: Use bracketed paste mode when sending code to console (radian)
"r.bracketedPaste": true,
// R: R or radian path for macOS
"r.rterm.mac": "/usr/local/Caskroom/miniforge/base/envs/r-console/bin/radian",
// R: Enable R session watcher (experimental)
"r.sessionWatcher": true,
// R: Remove hidden items when clearing R workspace
"r.workspaceViewer.removeHiddenItems": true,
// Telemetry: Disable Microsoft crash reporter
"telemetry.enableCrashReporter": false,
// Telemetry: Disable Microsoft telemetry
"telemetry.enableTelemetry": false,
// Terminal: Path to integrated shell on macOS
"terminal.integrated.shell.osx": "/bin/zsh"
}
The r.rterm.mac
field above should be the path to radian
if you followed the radian
installation instructions above, otherwise it should be the path to your R
executable (if you don’t know it, type which R
in your terminal). Since we use Homebrew to install the latest zsh
using brew install zsh
, the path to our zsh
is /usr/local/bin/zsh
, but we have put /bin/zsh
above since that is the default zsh
location for most macOS users. You should run which r
and which zsh
to confirm your local settings are correct.
- Below are some useful keyboard shortcuts for
keybindings.json
, found by using the Command Palette (Shift-Command-P
) in VS Code and navigating toPreferences: Open Keyboard Shortcuts (JSON)
. This is ourkeybindings.json
:
[
{
"description": "View: Show R Workspace",
"key": "alt+r",
"command": "workbench.view.extension.workspaceViewer"
},
{
"description": "R: Create R Terminal",
"key": "alt+`",
"command": "r.createRTerm"
},
{
"description": "R: Insert Assignment Operator",
"key": "alt+-",
"command": "type",
"when": "editorLangId == r || editorLangId == rmd && editorTextFocus",
"args": { "text": " <- " }
},
{
"description": "R: Insert Pipe Operator",
"key": "shift+cmd+m",
"command": "type",
"when": "editorLangId == r || editorLangId == rmd && editorTextFocus",
"args": { "text": " %>% " }
},
{
"description": "R: Insert Assignment Pipe Operator",
"key": "shift+cmd+,",
"command": "type",
"when": "editorLangId == r || editorLangId == rmd && editorTextFocus",
"args": { "text": " %<>% " }
},
{
"description": "R: Insert Tee Pipe Operator",
"key": "shift+cmd+.",
"command": "type",
"when": "editorLangId == r || editorLangId == rmd && editorTextFocus",
"args": { "text": " %T>% " }
},
{
"description": "R: Test Package",
"key": "shift+cmd+8",
"command": "r.test"
},
{
"description": "R: Document",
"key": "shift+cmd+9",
"command": "r.document"
},
{
"description": "R: Load All",
"key": "shift+cmd+0",
"command": "r.loadAll",
}
]
Writing an R Package using VS Code
In this section we’re going to set up a toy R package in VS Code, and in the next section we will enable Live Share.
Open VS Code and use the Command Palette (
Shift-Command-P
) to navigate toR: Create R Terminal
, or use the suggested keyboard shortcut above (Option-`
). Note that if you have an editor open and the focus is on the editor, for the shortcut to work you may first need to useControl-`
forView: Toggle Integrated Terminal
followed byOption-`
forR: Create R Terminal
. If our configuration above worked for you, these commands should open a terminal instance with theradian
console, and the title of the terminal should be1: R Interactive
(or2: R Interactive
if it’s the second active terminal).In the VS Code R console, create a {mutagen} package folder on your Desktop, declare dependencies, and start an R script for a new function
cast_integers()
:
library(usethis)
create_package("~/Desktop/mutagen")
<- c("dplyr", "purrr", "tibble", "vctrs")
deps ::walk(deps, use_package)
purrruse_r("cast_integers")
In VS Code, open the {mutagen} folder using File > Open… (
Command-O
) and selecting themutagen
folder in the Desktop. This will open a new VS Code instance and the title bar will readWelcome — mutagen
. The R extension icon will be visible on the sidebar since VS Code will detect the.R
file in the folder.Use the Explorer icon in the sidebar (
Shift-Command-E
) and open thecast_integers.R
file. Paste the following code into the editor and save the file:
#' Safely cast numeric columns to integers
#'
#' `cast_integers()` casts all eligible numeric columns in a data frame to integers, without data loss, using `vctrs::vec_cast()` for coercion.
#' @param .data A data frame
#' @return A tibble. If the input data frame has rownames, these will be preserved in a new rowname column.
#' @examples (mtcars_integerized <- cast_integers(mtcars))
#' @export
<- function(.data) {
cast_integers stopifnot(is.data.frame(.data))
<- tibble::rownames_to_column(.data)
.data <- tibble::as_tibble(.data)
.data <- purrr::map_lgl(
int_index
.data,~ !inherits(try(vctrs::vec_cast(.x, to = integer()), silent = TRUE), "try-error")
)<- dplyr::mutate(
.data
.data,::across(
dplyr.cols = any_of(names(which(int_index))),
.fns = ~ vctrs::vec_cast(.x, to = integer())
)
)return(.data)
}
- Now create a new R console in VS Code using either the keyboard shortcuts (
Control-`
to toggle the terminal andOption-`
to create an R console) or by opening the Command Palette (Shift-Command-P
) and navigating toR: Create R Terminal
. Focus your view on the R extension by clicking R the sidebar (Option-R
), and now test out the package. Below are a series of R console commands to familiarize you with the package development workflow in VS Code. We will load the package, document it, and create a new object in the R workspace that uses the new function we just loaded onto the package environment. To get familiar with the VS Code user interface, we will also print the object in the console, view it with the data viewer, and check out the help file for our new function.
library(dplyr)
::load_all() # or Shift-Command-0 using keyboard shortcuts above
devtools::document() # or Shift-Command-9 using keyboard shortcuts above
devtools<- mtcars %>% cast_integers()
mtcars_integerized
mtcars_integerizedView(mtcars_integerized)
?cast_integers
Final thoughts
We’re excited for the future of R programming in VS Code. Live Share is an outstanding innovation for collaborative real-time editing, and is only one of the many amazing features in VS Code. Here we have only scratched the surface of use cases for Live Share. Microsoft keeps a running list of many other Live Share use cases.
We are also huge fans of RStudio and the RStudio IDE. On our wish list for RStudio is that a live collaboration feature be supported in future versions of RStudio Desktop (not only the Pro version) and RStudio Cloud. Having many excellent options is a good thing! In the meantime, it is clear that VS Code is maturing into a capable IDE for R. Live Share is an attractive and free feature that enables real-time collaboration for the masses and that we hope others will enjoy as much as we have.
Liked this post? I’d love for you to retweet!
🎉📢🎉 Collaborating in #rstats? Git got you down? Want to code with others remotely, in real-time, and for free (à la Google Docs)? Check out how to set up and use @code (#vscode) and #vsliveshare for remote #pairprogramming 🤝 in R! 🤯. Tutorial here: https://t.co/Qbrw71V77Z pic.twitter.com/3sy9hAJea7
— Isabella Velásquez (@ivelasq3) February 4, 2021