Don't Make Me Write: Tips for Avoiding Typing in RStudio

December 18, 2023

I have a confession to make: I am lazy. Ok, maybe that's too strong. Let's go for a euphemism instead: I am efficient. I love learning handy tricks that make my life easier and make my job smoother with fewer hiccups along the way. This is one part of why, here in the Data Lab, we love automation - why waste our time on rote, repetitive, housekeeping tasks when we can get the bots to do it for us?

In this blog post, we'll highlight a few tips about how you can use RStudio to code more efficiently and write less. (Perhaps you may be interested in our thoughts on reading less too!)

Always be documenting (your functions)

Not only do we love automation (and caffeine) in the Data Lab, but we also love documentation. "Always be documenting" (our adorable take on ABD) is our unofficial motto. It's really easy for documentation to fall by the wayside — after all, it's not exactly the "fun" part of coding — so it helps to find ways to lower the barrier to writing documentation. We can't exactly automate writing documentation, but we can leverage some tricks to help us get our documentation going! 

Let's see one useful example of this: Writing documentation for custom functions. A common approach to documenting functions in R, especially (but not only!) when writing R packages, is to use Roxygen comments, which provide a defined structure for laying out a function's purpose - its arguments, what it returns, example usage, and more. Roxygen comments are very informative and communicative, but honestly their format can be a little clunky, and writing them isn't always my favorite activity.

Seemingly to save me from myself, RStudio in fact comes pre-built with a handy shortcut for getting your Roxygen documentation started - just write your function (or at least, write a function definition), pop your cursor inside the body of the function, click [.inline-snippet]Insert Roxygen Skeleton[.inline-snippet] from the [.inline-snippet]Code[.inline-snippet] menu (or, use the shortcut hit [.inline-snippet]shift+opt+cmd+R[.inline-snippet] directly), and voila! A "skeleton" for filling in your Roxygen comments will automagically appear, and you can simply fill in the template with your documentation.

Here, we show a "before/after" picture of the [.inline-snippet]cluster_sce() function from our scpcaTools R package[.inline-snippet]. Please note, only the first several lines of the function body are pictured for space. Left: The function before inserting the Roxygen Skeleton. Right: The resulting Roxygen Skeleton as it appears when inserted.

In the Data Lab, we use Roxygen comments throughout our R projects, including throughout the open-source workflow behind the Single-cell Pediatric Cancer Atlas (ScPCA) Portal. You can find some examples of places we've leveraged the [.inline-snippet]Insert Roxygen Skeleton[.inline-snippet] shortcut to write our function documentation in, for example, our scpcaTools R package  and in our Nextflow-based workflow itself.

Of course, this shortcut is just one of many that RStudio provides off the bat for quickly executing lots of useful tasks, and you can customize their specific keybindings to your heart's content.

I was really excited when I first discovered this Roxygen shortcut. What a superb way to embrace my laziness - I mean, my quest for efficiency - while still writing all my docs! I started thinking about other common coding structures I write over and over, and of course, what immediately came to mind was writing a function definition itself! Was there another shortcut I could use to trigger RStudio to write me a skeleton function in the first place?

Be the shortcut you wish the see in the world: Be a snippet

Turns out there was no shortcut, but there was something else available to me - a code snippet

Snippets allow you to quickly stamp out a structured piece of code for re-use over and over again. There are lots of good reasons to use snippets:

  • You guessed it, they increase your efficiency - Type less to type more and save some time.
  • They help you avoid typos - The correct spelling/syntax is ready to pop in with much less human error.
  • They help reduce your frustration. We all have a nemesis piece of code whose syntax we can never remember. Just turn it into a snippet, and you'll spend much less time going back and forth to the docs to remind yourself what to type.

For the rest of this blog post, we'll focus on how to use and write your own snippets in RStudio. But it’s worth noting that snippets are also supported in other text editors besides RStudio, like VS Code

In RStudio, you can find the pre-cooked snippets from [.inline-snippet]Tools[.inline-snippet] -> [.inline-snippet]Edit Snippets[.inline-snippet]. RStudio binds certain snippets to the language you're coding in. You can directly edit any of these predefined snippets and add your own snippets to the language of your choice. 

Here, I've scrolled down to the pre-defined R snippet called [.inline-snippet]fun[.inline-snippet], which automagically writes a function skeleton for you:

To use this snippet in RStudio, from an R file such as an R script or R Markdown document, simply type  [.inline-snippet]fun[.inline-snippet] and RStudio will suggest the snippet, and you can hit enter to accept it (or, skip the suggested completion list and simply type [.inline-snippet]<snippet name>+Shift+Tab[.inline-snippet]). Then, something even more magical happens — See the [.inline-snippet]${1:name}[.inline-snippet] and [.inline-snippet]${2:variables}[.inline-snippet] components of the snippet? Those are placeholders for items that you fill in yourself, pre-populated with values [.inline-snippet]name[.inline-snippet] and [.inline-snippet]variables[.inline-snippet], respectively. By hitting [.inline-snippet]tab[.inline-snippet], you can cycle through these placeholders and enter your own values as you go. The other placeholder - [.inline-snippet]${0}[.inline-snippet] - represents where your cursor will land after tabbing through all the pre-populated placeholders.

See it in action here! In this gif, I hit tab all the way through to cycle through each placeholder.

After discovering the magic of snippets, I decided to write one to tackle one of my code nemeses: saving files. Sounds crazy, no? For such a simple one-line task, do we really need a snippet?

It turns out, even for small tasks like this, sometimes we need a little help from ourselves. As part of the ScPCA pipeline, we have to manage lots of large [.inline-snippet]RDS[.inline-snippet] files holding [.inline-snippet]SingleCellExperiment[.inline-snippet] objects as they are passed through steps in the workflow, and ultimately added to the ScPCA Portal. As an effort to reduce file size along the way - both for us as we process the data and for users when they download the data - we aim to always compress our [.inline-snippet]RDS[.inline-snippet] files. This is straightforward enough to do with a third argument to the [.inline-snippet]readr::write_rds()[.inline-snippet] function, for example to add [.inline-snippet]gz[.inline-snippet] compression: [.inline-snippet]readr::write_rds(<object>, <filename>, compress = "gz")[.inline-snippet].1

The trouble, of course, is remembering to include that third argument! After forgetting this one too many times, I decided to make myself a snippet which I added to the R snippets list:

1Note that the base R equivalent of this function, [.inline-snippet]saveRDS()[.inline-snippet], automatically will apply [.inline-snippet]"gz"[.inline-snippet] compression, but we tend to prefer [.inline-snippet]tidyverse[.inline-snippet] functions for style.

I called this snippet [.inline-snippet]writec[.inline-snippet] for "write compression," a phrase I used because, well, it works for me and this is my snippet - the snippet world is your oyster. Now, all I have to do is type [.inline-snippet]writec[.inline-snippet] followed by [.inline-snippet]Shift+Tab[.inline-snippet] (or select the snippet option from the autocomplete dropdown), and a little template appears with my cursor sitting ready for me to type in the first placeholder slot. Notice too that I've included a comment in this snippet, so in this case, my snippet also writes a little bit of documentation for me. Thanks, bots!

We hope this blog post has given you some food for thought about this neat way to type less to type more! You too can conquer your code nemeses with a snippet - get the syntax right every time, and save yourself the frustration of forgetting that one argument yet again. Be sure to subscribe to our blog for future trips and tricks to accelerate your coding!

I have a confession to make: I am lazy. Ok, maybe that's too strong. Let's go for a euphemism instead: I am efficient. I love learning handy tricks that make my life easier and make my job smoother with fewer hiccups along the way. This is one part of why, here in the Data Lab, we love automation - why waste our time on rote, repetitive, housekeeping tasks when we can get the bots to do it for us?

In this blog post, we'll highlight a few tips about how you can use RStudio to code more efficiently and write less. (Perhaps you may be interested in our thoughts on reading less too!)

Always be documenting (your functions)

Not only do we love automation (and caffeine) in the Data Lab, but we also love documentation. "Always be documenting" (our adorable take on ABD) is our unofficial motto. It's really easy for documentation to fall by the wayside — after all, it's not exactly the "fun" part of coding — so it helps to find ways to lower the barrier to writing documentation. We can't exactly automate writing documentation, but we can leverage some tricks to help us get our documentation going! 

Let's see one useful example of this: Writing documentation for custom functions. A common approach to documenting functions in R, especially (but not only!) when writing R packages, is to use Roxygen comments, which provide a defined structure for laying out a function's purpose - its arguments, what it returns, example usage, and more. Roxygen comments are very informative and communicative, but honestly their format can be a little clunky, and writing them isn't always my favorite activity.

Seemingly to save me from myself, RStudio in fact comes pre-built with a handy shortcut for getting your Roxygen documentation started - just write your function (or at least, write a function definition), pop your cursor inside the body of the function, click [.inline-snippet]Insert Roxygen Skeleton[.inline-snippet] from the [.inline-snippet]Code[.inline-snippet] menu (or, use the shortcut hit [.inline-snippet]shift+opt+cmd+R[.inline-snippet] directly), and voila! A "skeleton" for filling in your Roxygen comments will automagically appear, and you can simply fill in the template with your documentation.

Here, we show a "before/after" picture of the [.inline-snippet]cluster_sce() function from our scpcaTools R package[.inline-snippet]. Please note, only the first several lines of the function body are pictured for space. Left: The function before inserting the Roxygen Skeleton. Right: The resulting Roxygen Skeleton as it appears when inserted.

In the Data Lab, we use Roxygen comments throughout our R projects, including throughout the open-source workflow behind the Single-cell Pediatric Cancer Atlas (ScPCA) Portal. You can find some examples of places we've leveraged the [.inline-snippet]Insert Roxygen Skeleton[.inline-snippet] shortcut to write our function documentation in, for example, our scpcaTools R package  and in our Nextflow-based workflow itself.

Of course, this shortcut is just one of many that RStudio provides off the bat for quickly executing lots of useful tasks, and you can customize their specific keybindings to your heart's content.

I was really excited when I first discovered this Roxygen shortcut. What a superb way to embrace my laziness - I mean, my quest for efficiency - while still writing all my docs! I started thinking about other common coding structures I write over and over, and of course, what immediately came to mind was writing a function definition itself! Was there another shortcut I could use to trigger RStudio to write me a skeleton function in the first place?

Be the shortcut you wish the see in the world: Be a snippet

Turns out there was no shortcut, but there was something else available to me - a code snippet

Snippets allow you to quickly stamp out a structured piece of code for re-use over and over again. There are lots of good reasons to use snippets:

  • You guessed it, they increase your efficiency - Type less to type more and save some time.
  • They help you avoid typos - The correct spelling/syntax is ready to pop in with much less human error.
  • They help reduce your frustration. We all have a nemesis piece of code whose syntax we can never remember. Just turn it into a snippet, and you'll spend much less time going back and forth to the docs to remind yourself what to type.

For the rest of this blog post, we'll focus on how to use and write your own snippets in RStudio. But it’s worth noting that snippets are also supported in other text editors besides RStudio, like VS Code

In RStudio, you can find the pre-cooked snippets from [.inline-snippet]Tools[.inline-snippet] -> [.inline-snippet]Edit Snippets[.inline-snippet]. RStudio binds certain snippets to the language you're coding in. You can directly edit any of these predefined snippets and add your own snippets to the language of your choice. 

Here, I've scrolled down to the pre-defined R snippet called [.inline-snippet]fun[.inline-snippet], which automagically writes a function skeleton for you:

To use this snippet in RStudio, from an R file such as an R script or R Markdown document, simply type  [.inline-snippet]fun[.inline-snippet] and RStudio will suggest the snippet, and you can hit enter to accept it (or, skip the suggested completion list and simply type [.inline-snippet]<snippet name>+Shift+Tab[.inline-snippet]). Then, something even more magical happens — See the [.inline-snippet]${1:name}[.inline-snippet] and [.inline-snippet]${2:variables}[.inline-snippet] components of the snippet? Those are placeholders for items that you fill in yourself, pre-populated with values [.inline-snippet]name[.inline-snippet] and [.inline-snippet]variables[.inline-snippet], respectively. By hitting [.inline-snippet]tab[.inline-snippet], you can cycle through these placeholders and enter your own values as you go. The other placeholder - [.inline-snippet]${0}[.inline-snippet] - represents where your cursor will land after tabbing through all the pre-populated placeholders.

See it in action here! In this gif, I hit tab all the way through to cycle through each placeholder.

After discovering the magic of snippets, I decided to write one to tackle one of my code nemeses: saving files. Sounds crazy, no? For such a simple one-line task, do we really need a snippet?

It turns out, even for small tasks like this, sometimes we need a little help from ourselves. As part of the ScPCA pipeline, we have to manage lots of large [.inline-snippet]RDS[.inline-snippet] files holding [.inline-snippet]SingleCellExperiment[.inline-snippet] objects as they are passed through steps in the workflow, and ultimately added to the ScPCA Portal. As an effort to reduce file size along the way - both for us as we process the data and for users when they download the data - we aim to always compress our [.inline-snippet]RDS[.inline-snippet] files. This is straightforward enough to do with a third argument to the [.inline-snippet]readr::write_rds()[.inline-snippet] function, for example to add [.inline-snippet]gz[.inline-snippet] compression: [.inline-snippet]readr::write_rds(<object>, <filename>, compress = "gz")[.inline-snippet].1

The trouble, of course, is remembering to include that third argument! After forgetting this one too many times, I decided to make myself a snippet which I added to the R snippets list:

1Note that the base R equivalent of this function, [.inline-snippet]saveRDS()[.inline-snippet], automatically will apply [.inline-snippet]"gz"[.inline-snippet] compression, but we tend to prefer [.inline-snippet]tidyverse[.inline-snippet] functions for style.

I called this snippet [.inline-snippet]writec[.inline-snippet] for "write compression," a phrase I used because, well, it works for me and this is my snippet - the snippet world is your oyster. Now, all I have to do is type [.inline-snippet]writec[.inline-snippet] followed by [.inline-snippet]Shift+Tab[.inline-snippet] (or select the snippet option from the autocomplete dropdown), and a little template appears with my cursor sitting ready for me to type in the first placeholder slot. Notice too that I've included a comment in this snippet, so in this case, my snippet also writes a little bit of documentation for me. Thanks, bots!

We hope this blog post has given you some food for thought about this neat way to type less to type more! You too can conquer your code nemeses with a snippet - get the syntax right every time, and save yourself the frustration of forgetting that one argument yet again. Be sure to subscribe to our blog for future trips and tricks to accelerate your coding!

Back To Blog