Author: Lorenz Walthert
Date: 2018-06-25

# An introduction to styler

#### Lorenz Walthert

#### 2018-06-25

This vignette introduces the basic functionality of styler and showcases how styler applies a few rules of the tidyverse style guide to example code. Note that you can create your own style guide and customize styler even further, as described in the vignette “Customizing styler”.

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. 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:

    library("styler")
    library("magrittr")
    style_text("a=3; 2", scope = "spaces")

    a = 3; 2

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

    style_text("a=3; 2", scope = "tokens")

    a <- 3
    2

`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:

    style_text("if(x) {66 } else {a=3}", scope = "line_breaks")

    if (x) {
      66
    } else {
      a = 3
    }

Note that `scope = "spaces"` does not touch indention

    code <- c(
        "a <- function() { ",
        "                a=3",
        "}"
    )

    style_text(code, scope = "spaces")

    a <- function() {
                    a = 3
    }

But `scope = "indention"` - as the name says - does.

    style_text(code, scope = "indention")

    a <- function() {
      a = 3
    }

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:

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

    data_frame(
      small  = 2,
      medium = 4, # comment without space
      large  = 6
    )

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.

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

    a <-   "one"   # just one
    abc <- "three" # three

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:

    # Before
    1++1-1-1/2

    # After
    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:

    style_text(
      "1++1/2*2^2",
      math_token_spacing = specify_math_token_spacing(zero = c("'/'", "'*'", "'^'"))
    )

    1 + +1/2*2^2

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

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

    ) }

    # After
    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:

    # Before
    do_a_long_and_complicated_fun_cal("which", has, way, to,
                                  "and longer then lorem ipsum in its full length"
                                  )

    # After
    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:

    # Before
    one = "one string"

    # After
    one <- "one string"

It converts single quotes within strings if necessary:

    # Before
    one <- 'one string'
    two <- "one string in a 'string'"

    # After
    one <- "one string"
    two <- "one string in a 'string'"

And adds braces to function calls in pipes:

    # Before
    a %>%
      b %>%
      c

    # After
    a %>%
      b() %>%
      c()

Function declarations are indented if multi-line:

    # Before
    my_fun <- function(x,
    y,
    z) {
      just(z)
    }

    # After
    my_fun <- function(x,
                       y,
                       z) {
      just(z)
    }

`styler` can also deal with tidyeval syntax:

    # Before
    mtcars %>%
      group_by( !!my_vars )

    # After
    mtcars %>%
      group_by(!!my_vars)

If you, say, don’t want comments starting with `###` to be indented, you can formulate an unindention rule:

    style_text(
      c(
        "a <- function() {",
        "### not to be indented",
        "# indent normally",
        "33",
        "}"
      ),
      reindention = specify_reindention(regex_pattern = "###", indention = 0)

    )

    a <- function() {
    ### not to be indented
      # indent normally
      33
    }