rrstudiorstudioapi

How to use indentation with `rstudioapi::insertText`


I have a string that I want to paste with indentation into RStudio using the {rstudioapi}. Here is a simple test string:

test_str <- "for (i in seq_along(x)) {\nout[[i]] <- sum(x[[i]])\n}"
cat(test_str)

#> for (i in seq_along(x)) {
#> out[[i]] <- sum(x[[i]])
#> }

When copying the console output and pasting it manually into an R script in RStudio the output has the correct indentation of one tab equalling two spaces (my default setting):

# this is my desired output (directly in a script, not the console):
for (i in seq_along(x)) {
  out[[i]] <- sum(x[[i]])
}

When using rstudioapi::insertText the string is inserted in the script without indentation:

rstudioapi::insertText(test_str)

for (i in seq_along(x)) {
out[[i]] <- sum(x[[i]]) # one tab (equalling two spaces) is missing
}

How can I add indentation when using rstudioapi::insertText or any other function from the {rstudioapi} package?

Reading the documentation I found how to read the system preference for indentation:

rstudioapi::readRStudioPreference("num_spaces_for_tab")
#> 2

However, I can't figure out how to make insertText use this information.

More context:
I'm looking for a way to add indentation programmatically to string outputs. That means, I don't want to add manually \t to lines which should have indentation. I'm in a package and have to deal with user input, which makes it probably pretty tough to calculate the correct amount of indentation which is needed. In the example above line 1 and 3 would need no indentation, while line 2 would need one tab or two spaces.

Ideally, I'd like to use no other package than the {rstudioapi} or base R. Looking at the documentation insertText also has a location argument which works with positions or ranges in scripts. I'm not sure whether this can be somehow used to include indentation.

I'm also looking at the {datapasta} package which also uses the {rstudioapi} and here the "num_spaces_for_tab"option is used in the output_context (in the script called oc$nspc), but I'm not sure how to apply it to my problem.


Solution

  • You could use rstudioapi::executeCommand to launch reindent or reformatCode commands:

    If you run following commands together in editor (for example with ctrl+A Ctrl+Enter):

    test_str <- "for (i in seq_along(x)) {\nout[[i]] <- sum(x[[i]])\n}"
    rstudioapi::insertText(test_str)
    
    # Should be adapted to the range you want to reformat (here : all lines)
    ranges <- rstudioapi::document_range(c(1, 0), c(Inf, Inf))
    rstudioapi::setSelectionRanges(ranges)
    rstudioapi::executeCommand('reformatCode')
    
    

    You get:

    for (i in seq_along(x)) {
      out[[i]] <- sum(x[[i]])
    }
    

    List of available command IDs is available here.