---
title: "RStudio Addins"
date-meta: 2022-12-12
---

RStudio addins provide a mechanism for executing R functions interactively from within RStudio; either through keyboard shortcuts, through the **Command Palette** or through the **Addins** menu.

An addin can be as simple as a function that inserts a commonly used snippet of text, and as complex as a Shiny application that accepts input from the user, and later mutates a document open in RStudio.

## Using addins

The following documentation covers:  

- Basics of installing addins  
- Binding keyboard shortcuts to them  
- Developing new addins  

## Installation

RStudio addins are distributed as [R packages](https://r-pkgs.org/). Once you've installed an R package that contains addins, they'll be immediately become available within RStudio.

Let's start by playing around with a couple of the example addins provided by the [addinexamples](https://github.com/rstudio/addinexamples) package. Within RStudio, install this package (plus its requisite dependencies) with:

``` r
# if necessary: install.packages("devtools")
devtools::install_github("rstudio/addinexamples", type = "source")
```

## Running addins

After installing this package, you should see the *Addins* toolbar menu populated with the addins exported by this package:

![](images/addin-examples.png){alt="Addins Menu" fig-alt="A screenshot of the addinexamples dropdown - displaying the insert, find and replace, reformat R code, and Subset a data frame add-ins." width="400"}

Try pressing the **Insert %in%** addin -- the text `%in%` will be inserted at the cursor position.

The **Addins** menu displays all available addins, along with a search bar for searching by package name or by addin name:

![](images/addin-search.png){width="450"}

### Keyboard shortcuts

Addins can be assigned a keyboard shortcut through the **Tools** \> **Modify Keyboard Shortcuts** menu.

![](images/addin-shortcut.png){fig-alt="A screenshot of the Customize Keyboard shortcuts menu"}

## Developing addins

### Addin basics

The **Insert %in%** addin is implemented entirely with R code. In fact, the R function that made this happen is located [here](https://github.com/rstudio/addinexamples/blob/master/R/insertInAddin.R), and its definition is show below:

``` r
insertInAddin <- function() {
  rstudioapi::insertText(" %in% ")
}
```

Executing `addinexamples::insertInAddin()` directly at the console will insert `%in%`. RStudio is executing that R script behind the scenes, the addin is providing a user interface element and potentially a shortcut rather than manually writing and executing the function each time.

There are two major types of addins:

1.  Text macros, which insert text into the console or source pane and in some cases transform text within the source pane. The `insertInAddin` addin defined above is an example of a text macro.

2.  Shiny Gadgets, which are fully interactive Shiny applications. Gadgets may also perform text transformations but they are capable of much more.

More details on Shiny Gadgets are provided below, but first we'll take a look at using the [rstudioapi](https://rstudio.github.io/rstudioapi/) package (which allows us to interact with RStudio from R code) and then what it takes to install and register an addin.

### RStudio API

The [rstudioapi](https://rstudio.github.io/rstudioapi/) package allows interacting with RStudio directly with R code.

``` r
install.packages("rstudioapi")
```

For addins in particular, a number of methods were added that allow R code to introspect and mutate the contents of a document open in RStudio. These methods are outlined below briefly, but see documentation within the [rstudioapi](https://rstudio.github.io/rstudioapi/) package for more details.

|                                         |                                                                                              |
|----------------------|--------------------------------------------------|
| `getActiveDocumentContext()`            | Returns information about the currently active RStudio document. See below for more details. |
| `insertText(location, text, id = NULL)` | Insert text at a specific location within a document.                                        |
| `setDocumentContext(text, id = NULL)`   | Set the contents of a document open in RStudio.                                              |

The list returned from `getActiveDocumentContext()` provides the following information about the active RStudio document:

-   *id* --- The unique document id.

-   *path* --- The path to the document on disk.

-   *contents* --- The contents of the document.

-   *selection* --- A list of selections.

The `id` can be passed to other functions within the API to address a specific document instance rather than the currently active document. Even though it's optional, it's highly recommended that you use the `id` parameter to ensure that you modify the document that was active when your addin was invoked.

The `location` argument to several of the API functions specifies a position or range to operate on. See the [rstudioapi manual](https://rstudio.github.io/rstudioapi/) for more details on specifying locations.

### Registering addins

Addins are just R functions, distributed via R packages. The registration file located at [inst/rstudio/addins.dcf](https://github.com/rstudio/addinexamples/blob/master/inst/rstudio/addins.dcf) lets RStudio know which addins are available. Each addin should have the following four fields:

-   **Name**: The name of the addin.

-   **Description**: A description of the addin.

-   **Binding**: The R function this addin is associated with.

-   **Interactive**: Whether this addin is interactive (e.g. runs a Shiny application).

For example:

``` markdown
Name: Insert %in%
Description: Inserts `%in%` at the cursor position.
Binding: insertInAddin
Interactive: false
```

To create your own RStudio addins:

1.  Create an R package

2.  Create some R functions

3.  Create a file at `inst/rstudio/addins.dcf`

RStudio will automatically discover and register these addins when your package is installed. Any number of addins can be added with a single `addins.dcf` file, but a blank line must be between each addin that is registered.

### Execution Modes

The `Interactive` field within the addin registration describes whether the addin is interactive or non-interactive. It's important to understand when an addin should be declared as interactive versus non-interactive, as this affects how RStudio will attempt to execute the addin:

-   Interactive addins are invoked by emitting a call to their function directly into the R console. For addins that display user-interface (e.g. using a Shiny application) this enables users to stop/interrupt them.

-   Non-interactive addins are run in the background and **can not be interrupted**, so it's imperative that these addins complete execution quickly. Otherwise, it's possible that the addin could freeze the user's R session.

The use case for non-interactive addins is typically simple text insertion or transformation, in which case users would be annoyed if each invocation resulted in code being inserted into the console.

## Shiny Gadgets

Shiny gadgets are Shiny applications which can be registered and run as addins. Typically, a Shiny Gadget provides a mechanism for interactively generating code, or modifying a document, but within this realm the possibilities are endless. This article demonstrates how you might create a simple Shiny Gadget, for more complete documentation see the following articles on the Shiny Developer Center:

-   [Shiny Gadgets](https://shiny.posit.co/r/articles/build/gadgets/)

-   [Designing Gadget UI](https://shiny.posit.co/r/articles/build/gadget-ui/)

Shiny Gadgets are similar to regular Shiny applications. You will need to develop a `ui` and a `server` for your gadget, and then use the `runGadget()` function to launch your gadget.

Shiny Gadgets require the **shiny** and **miniUI** packages:

``` r
install.packages(c("shiny", "miniUI"))
```

### Gadget UI

The UI for a Shiny Gadget can be generated using functions from the miniUI package. Typically, the UI definition of a Shiny Gadget will have the following form:

``` r
ui <- miniPage(
  gadgetTitleBar("My Gadget"),
  miniContentPanel(
    ## Your UI items go here.
  )
)
```

If you're unfamiliar with how the UI for a Shiny application can be generated, please read the [Shiny UI Lesson](https://shiny.posit.co/r/getstarted/shiny-basics/lesson2/) to get further acquainted with how the UI for a Shiny application might be developed.

### Gadget Server

The server function used for a Shiny Gadget is similar to one as provided for a regular Shiny application, except with the requirement that your application must respond to the `done` event. For example,

``` r
server <- function(input, output, session) {
  
  ## Your reactive logic goes here.
  
  # Listen for the 'done' event. This event will be fired when a user
  # is finished interacting with your application, and clicks the 'done'
  # button.
  observeEvent(input$done, {
    
    # Here is where your Shiny application might now go and affect the
    # contents of a document open in RStudio, using the `rstudioapi` package.
    #
    # At the end, your application should call 'stopApp()' here, to ensure that
    # the gadget is closed after 'done' is clicked.
    stopApp()
  })
}
```

### Gadget Viewer

After defining the ui and server for your Shiny gadget, choose what kind of viewer the application should run in. Currently, there are three options available:

-   **paneViewer()**: Launch the Shiny Gadget within the RStudio **Viewer** pane. This is useful for gadgets that want to run without obscuring other windows in the RStudio, but such applications should require only a minimal amount of space (as the viewer may be small on the user's computer).

-   **dialogViewer()**: Launch the Shiny Gadget as a modal dialog within the RStudio. Use this when your gadget requires a large amount of screen real estate, but is not heavy-weight enough to require a separate window.

-   **browserViewer()**: Launch the Shiny gadget in a separate window. Use this for large Shiny gadgets that require a large amount of real estate, and perhaps are more complex than applications that could fit comfortably within an RStudio modal dialog.

### Putting It Together

Let's combine the above components into a simple 'Hello Shiny' gadget. We'll create a clock that updates its display every second. Try running the following code in RStudio -- you should see a clock displayed in the viewer pane. When you click `Done`, the current time will be inserted at the cursor position.

``` r
library(shiny)
library(miniUI)

# We'll wrap our Shiny Gadget in an addin.
# Let's call it 'clockAddin()'.
clockAddin <- function() {
  
  # Our ui will be a simple gadget page, which
  # simply displays the time in a 'UI' output.
  ui <- miniPage(
    gadgetTitleBar("Clock"),
    miniContentPanel(
      uiOutput("time")
    )
  )
  
  server <- function(input, output, session) {
    
    # Set some CSS styles for our clock.
    clockStyles <- paste(
      "border: 1px solid #DADADA",
      "background-color: #EFEFEF",
      "border-radius: 5px",
      "font-size: 6em",
      "margin-top: 60px",
      "text-align: center",
      sep = "; "
    )
    
    # We'll use a 'reactiveTimer()' to force Shiny
    # to update and show the clock every second.
    invalidatePeriodically <- reactiveTimer(intervalMs = 1000)
    observe({
      
      # Call our reactive timer in an 'observe' function
      # to ensure it's repeatedly fired.
      invalidatePeriodically()
      
      # Get the time, and render it as a large paragraph element.
      time <- Sys.time()
      output$time <- renderUI({
        p(style = clockStyles, time)
      })
    })
    
    # Listen for 'done' events. When we're finished, we'll
    # insert the current time, and then stop the gadget.
    observeEvent(input$done, {
      timeText <- paste0("\"", as.character(Sys.time()), "\"")
      rstudioapi::insertText(timeText)
      stopApp()
    })
    
  }
  
  # We'll use a pane viwer, and set the minimum height at
  # 300px to ensure we get enough screen space to display the clock.
  viewer <- paneViewer(300)
  runGadget(ui, server, viewer = viewer)
  
}

# Try running the clock!
clockAddin()

# Now all that's left is sharing this addin -- put this function
# in an R package, provide the registration metadata at
# 'inst/rstudio/addins.dcf', and you're ready to go!
```

That example provides a fully functional Shiny gadgets. Additional documentation on creating Gadgets is available at the Shiny Developer Center:

-   [Shiny Gadgets](https://shiny.posit.co/r/articles/build/gadgets/)

-   [Designing Gadget UI](https://shiny.posit.co/r/articles/build/gadget-ui/)

### Installation

Creating addins with Shiny Gadgets requires **shiny**, **miniUI**, and **rstudioapi** packages from CRAN. To create an addin package, add these packages to the package DESCRIPTION file as follows:

``` yaml
Imports:
  shiny,
  miniUI,
  rstudioapi
```

### More Examples

The **addinexamples** package contains several additional examples of Shiny Gadget based addins:

-   [Find and Replace](https://github.com/rstudio/addinexamples/blob/master/R/findAndReplaceAddin.R) --- Find and replace words in a document.

-   [Reformat R Code](https://github.com/rstudio/addinexamples/blob/master/R/reformatAddin.R) --- Reformat R code using `formatR::tidy_source()`.

-   [Subset a Data Frame](https://github.com/rstudio/addinexamples/blob/master/R/subsetAddin.R) --- Interactively subset a data frame.

\
