---
title: "An introduction to styler"
author: "Lorenz Walthert"
date: "`r Sys.Date()`"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{An introduction to styler}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

This vignette introduces the basic functionality of styler and showcases
how styler applies a few rules of the 
[tidyverse style guide](http://style.tidyverse.org/index.html) to example code.
Note that you can create your own style guide and customize styler even further, 
as described in the vignette "Customizing styler".

```{r, echo = FALSE}
knitr::opts_chunk$set(echo = TRUE, comment = "")
knitr::knit_engines$set(list(
  styler = function(options) {
    options$comment <- ""
    knitr::engine_output(
      options,
      
      c("# Before", options$code),
      c("# After", styler::style_text(options$code))
    )
  }
))

```

It's possible to use different levels of 'invasiveness', as described in the 
help file for the only style guide implemented so far, which is the 
[tidyverse style guide](http://style.tidyverse.org/index.html). The style guide 
in use is passed to the styling function (i.e `style_text()` and friends) via 
the `style` argument, which defaults to `tidyverse_style`. In addition to this 
argument, there are further customization options. For example, we can limit 
ourselves to styling just spacing information by indicating this with the 
`scope` argument:

```{r}
library("styler")
library("magrittr")
style_text("a=3; 2", scope = "spaces")
```

Or, on the other extreme of the scale, styling spaces, indention, line breaks 
and tokens (which is the default):

```{r}
style_text("a=3; 2", scope = "tokens")
```


`scope` always includes less-invasive styling than the option chosen, 
e.g. `spaces = "line_breaks"` includes styling spaces and indention in addition 
to line breaks.


We can also choose to style line breaks but not tokens:
```{r}
style_text("if(x) {66 } else {a=3}", scope = "line_breaks")
```

Note that `scope = "spaces"` does not touch indention
```{r}
code <- c(
    "a <- function() { ", 
    "                a=3", 
    "}"
)

style_text(code, scope = "spaces")
```

But `scope = "indention"` - as the name says - does.
```{r}
style_text(code, scope = "indention")
```


Another option that is helpful to determine the level of 'invasiveness' is
`strict`. If set to `TRUE`, spaces and line breaks before or after tokens are
set to either zero or one. However, in some situations this might be undesirable,
as the following example shows:

```{r}
style_text(
  "data_frame(
     small  = 2 ,
     medium = 4,#comment without space
     large  = 6
   )", strict = FALSE
)
```

We prefer to keep the equal sign after "small", "medium" and large aligned,
so we set `strict = FALSE` to set spacing to *at least* one around `=`.

Also, spaces before comments are preserved with that option.

```{r}
style_text(
  "a <-   'one'   #just one
   abc <- 'three' # three", 
  strict = FALSE
)
```


Though simple, hopefully the above examples convey some of the flexibility of 
the configuration options available in `styler`. Let us for now focus on a 
configuration with `strict = TRUE` and `scope = "tokens"` and illustrate a few 
more examples of code before and after styling.

`styler` can identify and handle unary operators and other math tokens:

```{styler}
1++1-1-1/2
```

This is tidyverse style. However, styler offers very granular control for 
math token spacing. Assuming you like spacing around `+` and `-`, but not 
around `/` and `*` and `^`, do the following:
```{r}
style_text(
  "1++1/2*2^2", 
  math_token_spacing = specify_math_token_spacing(zero = c("'/'", "'*'", "'^'"))
)
```

It can also format complicated expressions that involve line breaking and 
indention based on both brace expressions and operators:

```{styler}
if (x >3) {stop("this is an error")} else {
c(there_are_fairly_long,
1 / 33 * 
2 * long_long_variable_names)%>% k(

) }
```

Lines are broken after `(` if a function call spans multiple lines:

```{styler}
do_a_long_and_complicated_fun_cal("which", has, way, to, 
                              "and longer then lorem ipsum in its full length"
                              )
```

`styler` replaces `=` with `<-` for assignment:
```{styler}
one = "one string"
```

It converts single quotes within strings if necessary:
```{styler}
one <- 'one string'
two <- "one string in a 'string'"
```

And adds braces to function calls in pipes:

```{styler}
a %>%
  b %>%
  c
```

Function declarations are indented if multi-line:

```{styler}
my_fun <- function(x, 
y, 
z) {
  just(z)
}
```

`styler` can also deal with tidyeval syntax:

```{styler}
mtcars %>%
  group_by( !!my_vars )
```

If you, say, don't want comments starting with `###` to be indented, you can 
formulate an unindention rule:
```{r}
style_text(
  c(
    "a <- function() {",
    "### not to be indented",
    "# indent normally",
    "33",
    "}"
  ),
  reindention = specify_reindention(regex_pattern = "###", indention = 0)
  
)
```

