2

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.

TimTeaFan
  • 17,549
  • 4
  • 18
  • 39

2 Answers2

3

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.

Waldi
  • 39,242
  • 6
  • 30
  • 78
1

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]])
+ }
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
manro
  • 3,529
  • 2
  • 9
  • 22
  • Thanks for this idea! It's working. I upvoted, but ideally I'd prefer an approach only using the `rstudioapi`. The fact, that we can extract the indentation suggests that it is somehow possible to also use this information when pasting text. – TimTeaFan Jan 04 '22 at 00:44
  • @TimTeaFan Look to an addition ;) – manro Jan 04 '22 at 16:40
  • Thank your very much for your effort! Although adding `\t` would work in theory, I'm in a package and deal with user inputs, so guessing how many tabs are needed in which line is probably pretty difficult, I'd say. I added some more context to my question above. – TimTeaFan Jan 04 '22 at 23:13
  • @TimTeaFan In the Europe is late already, I'll try to think tomorrow ;) – manro Jan 04 '22 at 23:26
  • @TimTeaFan I haven't any ideas, how to force ```inserttext``` works rightly :( Maybe you should ask at github? https://rstudio.github.io/rstudioapi/ – manro Jan 05 '22 at 10:07