Weird formatting of structure objects in RStudio editor

rstudio

#1

I have the following tibble in my global environment:

> print(test, n=100)
# A tibble: 21 x 7
   month               alpha alpha_mod  beta beta_mod gam_ma gam_ma_mod
   <dttm>              <int>     <int> <int>    <int>  <int>      <int>
 1 2016-10-31 00:00:00   283       133   260      102    208         64
 2 2016-11-30 00:00:00   298       139   278      119    190         67
 3 2016-12-31 00:00:00   277       106   249       92    176         62
 4 2017-01-31 00:00:00   231        85   242      107    208         86
 5 2017-02-28 00:00:00   276       132   301      119    221         78
 6 2017-03-31 00:00:00   323       141   349      126    265         76
 7 2017-04-30 00:00:00   242        89   249      108    204         67
 8 2017-05-31 00:00:00   255       110   309      132    215         67
 9 2017-06-30 00:00:00   208        80   256       89    251         90
10 2017-07-31 00:00:00   289       142   280      141    283        128
11 2017-08-31 00:00:00   284       174   326      199    314        155
12 2017-09-30 00:00:00   263       159   276      148    257        106
13 2017-10-31 00:00:00   280       146   299      161    250        125
14 2017-11-30 00:00:00   278       162   322      160    290        132
15 2017-12-31 00:00:00   269       153   235      125    240        125
16 2018-01-31 00:00:00   288       161   281      159    290        143
17 2018-02-28 00:00:00   255       142   256      137    275        132
18 2018-03-31 00:00:00   324       174   293      139    295        159
19 2018-04-30 00:00:00   339       211   356      208    292        159
20 2018-05-31 00:00:00   355       208   307      177    316        158
21 2018-06-30 00:00:00   300       194   279      162    324        191

I use dput to create a structure, because I want to include it in a reproducible example:

> dput(test)
structure(list(month = structure(c(1477872000, 1480464000, 1483142400, 
1485820800, 1488240000, 1490918400, 1493510400, 1496188800, 1498780800, 
1501459200, 1504137600, 1506729600, 1509408000, 1.512e+09, 1514678400, 
1517356800, 1519776000, 1522454400, 1525046400, 1527724800, 1530316800
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), alpha = c(283L, 
298L, 277L, 231L, 276L, 323L, 242L, 255L, 208L, 289L, 284L, 263L, 
280L, 278L, 269L, 288L, 255L, 324L, 339L, 355L, 300L), alpha_mod = c(133L, 
139L, 106L, 85L, 132L, 141L, 89L, 110L, 80L, 142L, 174L, 159L, 
146L, 162L, 153L, 161L, 142L, 174L, 211L, 208L, 194L), beta = c(260L, 
278L, 249L, 242L, 301L, 349L, 249L, 309L, 256L, 280L, 326L, 276L, 
299L, 322L, 235L, 281L, 256L, 293L, 356L, 307L, 279L), beta_mod = c(102L, 
119L, 92L, 107L, 119L, 126L, 108L, 132L, 89L, 141L, 199L, 148L, 
161L, 160L, 125L, 159L, 137L, 139L, 208L, 177L, 162L), gam_ma = c(208L, 
190L, 176L, 208L, 221L, 265L, 204L, 215L, 251L, 283L, 314L, 257L, 
250L, 290L, 240L, 290L, 275L, 295L, 292L, 316L, 324L), gam_ma_mod = c(64L, 
67L, 62L, 86L, 78L, 76L, 67L, 67L, 90L, 128L, 155L, 106L, 125L, 
132L, 125L, 143L, 132L, 159L, 159L, 158L, 191L)), row.names = c(NA, 
-21L), class = c("tbl_df", "tbl", "data.frame"))

However, when I copy the structure in RStudio source editor, the formatting is completely messed up:

structure(list(month = structure(c(1477872000, 1480464000, 1483142400, 
                                   1485820800, 1488240000, 1490918400, 1493510400, 1496188800, 1498780800, 
                                   1501459200, 1504137600, 1506729600, 1509408000, 1.512e+09, 1514678400, 
                                   1517356800, 1519776000, 1522454400, 1525046400, 1527724800, 1530316800
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), alpha = c(283L, 
                                                             298L, 277L, 231L, 276L, 323L, 242L, 255L, 208L, 289L, 284L, 263L, 
                                                             280L, 278L, 269L, 288L, 255L, 324L, 339L, 355L, 300L), alpha_mod = c(133L, 
                                                                                                                                  139L, 106L, 85L, 132L, 141L, 89L, 110L, 80L, 142L, 174L, 159L, 
                                                                                                                                  146L, 162L, 153L, 161L, 142L, 174L, 211L, 208L, 194L), beta = c(260L, 
                                                                                                                                                                                                  278L, 249L, 242L, 301L, 349L, 249L, 309L, 256L, 280L, 326L, 276L, 
                                                                                                                                                                                                  299L, 322L, 235L, 281L, 256L, 293L, 356L, 307L, 279L), beta_mod = c(102L, 
                                                                                                                                                                                                                                                                      119L, 92L, 107L, 119L, 126L, 108L, 132L, 89L, 141L, 199L, 148L, 
                                                                                                                                                                                                                                                                      161L, 160L, 125L, 159L, 137L, 139L, 208L, 177L, 162L), gam_ma = c(208L, 
                                                                                                                                                                                                                                                                                                                                        190L, 176L, 208L, 221L, 265L, 204L, 215L, 251L, 283L, 314L, 257L, 
                                                                                                                                                                                                                                                                                                                                        250L, 290L, 240L, 290L, 275L, 295L, 292L, 316L, 324L), gam_ma_mod = c(64L, 
                                                                                                                                                                                                                                                                                                                                                                                                              67L, 62L, 86L, 78L, 76L, 67L, 67L, 90L, 128L, 155L, 106L, 125L, 
                                                                                                                                                                                                                                                                                                                                                                                                              132L, 125L, 143L, 132L, 159L, 159L, 158L, 191L)), row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              -21L), class = c("tbl_df", "tbl", "data.frame"))
#>         month alpha alpha_mod beta beta_mod gam_ma gam_ma_mod
#> 1  2016-10-31   283       133  260      102    208         64
#> 2  2016-11-30   298       139  278      119    190         67
#> 3  2016-12-31   277       106  249       92    176         62
#> 4  2017-01-31   231        85  242      107    208         86
#> 5  2017-02-28   276       132  301      119    221         78
#> 6  2017-03-31   323       141  349      126    265         76
#> 7  2017-04-30   242        89  249      108    204         67
#> 8  2017-05-31   255       110  309      132    215         67
#> 9  2017-06-30   208        80  256       89    251         90
#> 10 2017-07-31   289       142  280      141    283        128
#> 11 2017-08-31   284       174  326      199    314        155
#> 12 2017-09-30   263       159  276      148    257        106
#> 13 2017-10-31   280       146  299      161    250        125
#> 14 2017-11-30   278       162  322      160    290        132
#> 15 2017-12-31   269       153  235      125    240        125
#> 16 2018-01-31   288       161  281      159    290        143
#> 17 2018-02-28   255       142  256      137    275        132
#> 18 2018-03-31   324       174  293      139    295        159
#> 19 2018-04-30   339       211  356      208    292        159
#> 20 2018-05-31   355       208  307      177    316        158
#> 21 2018-06-30   300       194  279      162    324        191

Created on 2018-07-12 by the reprex package (v0.2.0).

Why does it happen?


#2

I wish I knew the answer, because this irritates me every time and I wind up fiddling around reformatting it all into something more reasonable and compact. It's odd because when I paste the dput() output into the Source pane, I briefly see a flash of the console version before it suddenly rearranges itself with all those nested indents and line breaks.

Running Reformat Code doesn't help, because that just puts each element of every vector on its own line so the whole thing is needlessly long. E.g., dput(cars) > copy from console to Source > Select All > Reformat Code gives you:

structure(
  list(
    speed = c(
      4,
      4,
      7,
      7,
      8,
      9,
      10,
      10,
      10,
      11,
      11,
      12,
      12,
      12,
      12,
      13,
      13,
      13,
      13,
      14,
      14,
      14,
      14,
      15,
      15,
      15,
      16,
      16,
      17,
      17,
      17,
      18,
      18,
      18,
      18,
      19,
      19,
      19,
      20,
      20,
      20,
      20,
      20,
      22,
      23,
      24,
      24,
      24,
      24,
      25
    ),
    dist = c(
      2,
      10,
      4,
      22,
      16,
      10,
      18,
      26,
      34,
      17,
      28,
      14,
      20,
      24,
      28,
      26,
      34,
      34,
      46,
      26,
      36,
      60,
      80,
      20,
      26,
      54,
      32,
      40,
      32,
      40,
      50,
      42,
      56,
      76,
      84,
      36,
      46,
      68,
      32,
      48,
      52,
      56,
      64,
      66,
      54,
      70,
      92,
      93,
      120,
      85
    )
  ),
  .Names = c("speed",
             "dist"),
  row.names = c(NA, -50L),
  class = "data.frame"
)

instead of:

structure(list(speed = c(4, 4, 7, 7, 8, 9, 10, 10, 10, 11, 11, 
12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 16, 
16, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 20, 20, 20, 20, 20, 
22, 23, 24, 24, 24, 24, 25), dist = c(2, 10, 4, 22, 16, 10, 18, 
26, 34, 17, 28, 14, 20, 24, 28, 26, 34, 34, 46, 26, 36, 60, 80, 
20, 26, 54, 32, 40, 32, 40, 50, 42, 56, 76, 84, 36, 46, 68, 32, 
48, 52, 56, 64, 66, 54, 70, 92, 93, 120, 85)), .Names = c("speed", 
"dist"), row.names = c(NA, -50L), class = "data.frame")

ETA: If I create a new "Text File" in the Source pane and paste in the console output before saving the text file for the first time, no weird indentation and line breaks are introduced. The whitespace is identical to the console. I can then save the file and name it with a .R extension and it picks up the proper syntax highlighting while keeping the console-style whitespace. So I guess that's a workaround, but rather an awkward one?


#3

datapasta::tribble_paste allows you to preserve the dataframe with better formatting for a reprex, but converts the dates into strings:

library(datapasta)
df1 <- structure(list(month = structure(c(1477872000, 1480464000, 1483142400, 
                                   1485820800, 1488240000, 1490918400, 1493510400, 1496188800, 1498780800, 
                                   1501459200, 1504137600, 1506729600, 1509408000, 1.512e+09, 1514678400, 
                                   1517356800, 1519776000, 1522454400, 1525046400, 1527724800, 1530316800
), class = c("POSIXct", "POSIXt"), tzone = "UTC"), alpha = c(283L, 
                                                             298L, 277L, 231L, 276L, 323L, 242L, 255L, 208L, 289L, 284L, 263L, 
                                                             280L, 278L, 269L, 288L, 255L, 324L, 339L, 355L, 300L), alpha_mod = c(133L, 
                                                                                                                                  139L, 106L, 85L, 132L, 141L, 89L, 110L, 80L, 142L, 174L, 159L, 
                                                                                                                                  146L, 162L, 153L, 161L, 142L, 174L, 211L, 208L, 194L), beta = c(260L, 
                                                                                                                                                                                                  278L, 249L, 242L, 301L, 349L, 249L, 309L, 256L, 280L, 326L, 276L, 
                                                                                                                                                                                                  299L, 322L, 235L, 281L, 256L, 293L, 356L, 307L, 279L), beta_mod = c(102L, 
                                                                                                                                                                                                                                                                      119L, 92L, 107L, 119L, 126L, 108L, 132L, 89L, 141L, 199L, 148L, 
                                                                                                                                                                                                                                                                      161L, 160L, 125L, 159L, 137L, 139L, 208L, 177L, 162L), gam_ma = c(208L, 
                                                                                                                                                                                                                                                                                                                                        190L, 176L, 208L, 221L, 265L, 204L, 215L, 251L, 283L, 314L, 257L, 
                                                                                                                                                                                                                                                                                                                                        250L, 290L, 240L, 290L, 275L, 295L, 292L, 316L, 324L), gam_ma_mod = c(64L, 
                                                                                                                                                                                                                                                                                                                                                                                                              67L, 62L, 86L, 78L, 76L, 67L, 67L, 90L, 128L, 155L, 106L, 125L, 
                                                                                                                                                                                                                                                                                                                                                                                                              132L, 125L, 143L, 132L, 159L, 159L, 158L, 191L)), row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              -21L), class = c("tbl_df", "tbl", "data.frame"))




datapasta::tribble_paste(df1)
new_df <- tibble::tribble(
                                ~month, ~alpha, ~alpha_mod, ~beta, ~beta_mod, ~gam_ma, ~gam_ma_mod,
                          "2016-10-31",   283L,       133L,  260L,      102L,    208L,         64L,
                          "2016-11-30",   298L,       139L,  278L,      119L,    190L,         67L,
                          "2016-12-31",   277L,       106L,  249L,       92L,    176L,         62L,
                          "2017-01-31",   231L,        85L,  242L,      107L,    208L,         86L,
                          "2017-02-28",   276L,       132L,  301L,      119L,    221L,         78L,
                          "2017-03-31",   323L,       141L,  349L,      126L,    265L,         76L,
                          "2017-04-30",   242L,        89L,  249L,      108L,    204L,         67L,
                          "2017-05-31",   255L,       110L,  309L,      132L,    215L,         67L,
                          "2017-06-30",   208L,        80L,  256L,       89L,    251L,         90L,
                          "2017-07-31",   289L,       142L,  280L,      141L,    283L,        128L,
                          "2017-08-31",   284L,       174L,  326L,      199L,    314L,        155L,
                          "2017-09-30",   263L,       159L,  276L,      148L,    257L,        106L,
                          "2017-10-31",   280L,       146L,  299L,      161L,    250L,        125L,
                          "2017-11-30",   278L,       162L,  322L,      160L,    290L,        132L,
                          "2017-12-31",   269L,       153L,  235L,      125L,    240L,        125L,
                          "2018-01-31",   288L,       161L,  281L,      159L,    290L,        143L,
                          "2018-02-28",   255L,       142L,  256L,      137L,    275L,        132L,
                          "2018-03-31",   324L,       174L,  293L,      139L,    295L,        159L,
                          "2018-04-30",   339L,       211L,  356L,      208L,    292L,        159L,
                          "2018-05-31",   355L,       208L,  307L,      177L,    316L,        158L,
                          "2018-06-30",   300L,       194L,  279L,      162L,    324L,        191L
                          )
#check for equality:

> df1 == new_df
      month alpha alpha_mod beta beta_mod gam_ma gam_ma_mod
 [1,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [2,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [3,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [4,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [5,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [6,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [7,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [8,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
 [9,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[10,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[11,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[12,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[13,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[14,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[15,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[16,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[17,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[18,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[19,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[20,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE
[21,] FALSE  TRUE      TRUE TRUE     TRUE   TRUE       TRUE

#5

Nice, but hacky! I'd rather have RStudio source editor to do a proper job of formatting code...not sure if I should open a issue.


#6

That's a pity, it was quite close to what I needed.


#7

Agreed! This seems like an edge case situation, where auto-formatting that works well under other circumstances runs amok for dput() output being used in a reprex. And the requirements of this situation are unusual β€” unlike with other code, we don’t really care to read the dput output, just to have it included in as unobtrusive a manner as possible. That said, the current auto-formatting is terrible for reading, too.

I have no idea if the IDE team would view this as a bug or not. One way to find out, of course, is to file the issue realizing it may get closed. Or you could file better handling of pasted dput() output as a feature request!


#8

Have you tried turning off auto-indent after pasting? Uncheck this box:

image


#9

It works! Thanks @jonathan, from now on I can deselect the option before pasting a structure object and reselect it immediately after. It's simpler than the other solutions proposed. Thanks again!


#10

Personally, I'd still like to see the auto-indenter handle this sort of thing better, because the way it indents these structure objects doesn't make much sense to me. Is this too small of a detail for a feature request? I realize that your average person probably doesn't paste dput() output quite as often as I do :grin:

In the meantime, I found an even quicker workaround than fiddling with the options:

  1. Paste dput() output and select
  2. Comment with (Ctrl or ⌘)+Shift +C)
  3. Reflow comment with (Ctrl or ⌘)+Shift +/
  4. Uncomment with (Ctrl or ⌘)+Shift +C)

(default keyboard shortcuts, adjust as necessary if you customized these)


#11

For what it's worth, the indentation here is 'correct', but the real issue here is that RStudio doesn't provide a mechanism for pasting output while also preserving the source formatting (ie; not reformatting on paste).

Many other editors / IDEs allow for separate 'Paste' and 'Paste and Indent' actions; I think RStudio should provide a similar set of commands for pasting with / without reindenting the pasted contents.


#12

That would be a great feature, indeed!