How to use indentation with `rstudioapi::insertText`

268 views Asked by At

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.

2

There are 2 answers

0
Waldi On BEST ANSWER

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.

5
manro On

I didn't hear about an indentation feature in rstudioapi library.

But I know, that the styler has this possibility.

Maybe, it will be also helpful for you.

An example:

library(styler)

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

style_text(test_str, indent_by = 3)

An output:

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

Let's add this into insertText

> rstudioapi::insertText(style_text(test_str, indent_by = 3))
named list()
> for (i in seq_along(x)) {
+    out[[i]] <- sum(x[[i]])
+ }

It works?


An addition

Maybe this?

Add \t to our string.

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

Because you want to see two spaces, let's do this:

> insertText(gsub('\\t','  ', test_str))
named list()
> for (i in seq_along(x)) {
+   out[[i]] <- sum(x[[i]])
+ }