Setting up R with Visual Studio Code quickly and easily with the languageserversetup package

Introduction

Over the past years, R has been gaining popularity, bringing to life new tools to with ith it. Thanks to the amazing work by contributors implementing the Language Server Protocol for R and writing Visual Studio Code Extensions for R, the most popular development environment amongst developers across the world now has very strong support for R as well.

In this post, we will look at the languageserversetup package that aims to make the setup of the R Language Server robust and easy to use by installing it into a separate, independent library and adjusting R startup in a way that initializes the language server when relevant.

Visual Studio Code and R

According to the 2019 StackOverflow developer survey, Visual Studio Code is the most popular development environment across the board, with amazing support for many languages and extensions ranging from improved code editing to advanced version control support and Docker integration.

Until recently the support for R in Visual Studio Code was in my view not comprehensive enough to justify switching from other tools such as RStudio (Server) to using VS Code exclusively. This has changed with the work done by the team implementing the following 3 tools:

The features now include all that we need to work efficiently, including auto-complete, definition provider, code formatting, code linting, information on functions on hover, color provider, code sections and more.

If you are interested in more steps around the setup and the overview of features I recommend the Writing R in VSCode: A Fresh Start blogpost by Kun Ren. I also recommend that you follow Kun on Twitter if you are interested in the latest developments.

Setup considerations, issues, and tweaks: creating the languageserversetup package

With my current team, we have almost fully embraced Visual Studio Code as an IDE for our work in R, which is especially great as the work is multi-language and multi-environment in nature and we can do our development in Scala, R and more, including implementing and testing Jenkins pipelines and designing Docker images without leaving VS Code.

Setting up for the team on multiple systems and platforms we have found the following interesting points which were my motivation to write a small R package, languageserversetup, that should make the installation and setup of the R language server as easy and painless as possible.

Managing package libraries

One of the specifics of R is that all extensions (packages) are installed into package libraries, be it the packages we develop and use for our applications or the tools we use mostly as means to make our development life easier. We can therefore often end in a situation where we need to use different versions of R packages for different purposes. For example, the languageserver package currently needs R6 (>= 2.4.1), stringr (>= 1.4.0) and more, in total it recursively requires 75 other R packages to be installed. When installing and running the package we can run into conflicting versions of what our current applications need versus what the languageserver package requires to function properly.

Managing library paths

The second consideration, related to the first one is that if we simply install the language server into the default library with for instance install.packages it will change the library to a state that is possibly not desired. We can also run into unexpected crashes, where the languageserver will function properly for a time until one of the non-triggered dependencies with a hidden conflict gets triggered.

A solution - Complete library separation and smart initialization

One possible solution to the above issues is to:

  1. Keep the package libraries of the languageserver and the other libraries that the user uses (perhaps apart from the main system library containing the base and recommended packages that come with the R installation itself) completely separated, including all non-base dependencies

  2. Initialize that library only when the R process in question is triggered by the language server, otherwise, keep the process untouched and use the user libraries as usual

Solving it with 2 R commands - the languageserversetup package

To make the above solution easily accessible, I have created a small R package called languageserversetup that will do all the work for you. It can be installed from CRAN and it has no dependencies on other R packages:

install.packages("languageserversetup")

Now the entire setup has only 2 steps:

  1. Install the languageserver package and all of its dependencies into a separate independent library (Will ask for confirmation before taking action) using:
languageserversetup::languageserver_install()
  1. Add code to .Rprofile to automatically align the library paths for the language server functionality if the process is an instance of the languageserver, otherwise, the R session will run as usual with library paths unaffected. This is achieved by running (will also ask for confirmation):
languageserversetup::languageserver_add_to_rprofile()

That’s it. Now you can enjoy the functionality without caring about the setup of libraries or any package version conflicts. Thanks to the full separation of libraries, the removal is as trivial as deleting the library directory.

In action with VS Code

Installing languageserversetup and using languageserver_install()

Installing the language server

Installing the language server

Initializing the functionality with languageserver_add_to_rprofile()

Adding the language server to startup

Adding the language server to startup

All done, now enjoy the awesomeness!

Technical details

If you are interested in more technical details,

  • please visit the package’s openly accessible GitHub repository.
  • the README.md has information on options configuration, installation, uninstallation, platforms and more
  • the help files for the functions can be accessed from R with ?languageserver_install, ?languageserver_startup, ?languageserver_add_to_rprofile and ?languageserver_remove_from_rprofile for more details on their arguments and customization
  • for testing, GitHub actions are set up for multiple platforms and to run all CRAN checks on the package on each commit

References