---
title: "Alignment detection"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Alignment detection}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include=FALSE}
knitr::opts_chunk$set(
  eval = FALSE,
  collapse = TRUE,
  comment = "#>"
)
styler::cache_deactivate()
```

# Overview

Sometimes, you deliberately align code to make it more readable.

```{r}
call(
  a   =       3,
  bre = 3213232
)
```

Until styler 1.1.1.9002 (with `strict = TRUE`, e.g. as in `styler::style_file(..., strict = TRUE)`), this was formatted as follows:

```{r}
call(
  a = 3,
  bre = 3213232
)
```

because no alignment detection was built in.[^1]

[^1]: With `strict = FALSE`, the spacing would have been kept, however, `strict = FALSE` has a number of other implications because it is in general less invasive. For example, it would not add braces and line breaks to "if (TRUE) return()".

styler \>= 1.1.1.9003 detects aforementioned alignment for function calls. This vignette describes how aligned code is defined in styler and gives some examples so users can format their aligned code to match the definition styler uses to ensure their code is not unintentionally reformatted.

## Examples

These typical examples match *styler*'s definition of alignment. Note the spacing around operators and commas.

```{r}
tibble::tribble(
  ~key_here,  ~right_aligned,
  "left",            "right", # comments are allowed
  "long string",      "shrt" # columns can overlap ('~' above ',')
)

tibble::tribble(
  ~key_here,     ~left_aligned,
  "left",        "right", # comments are allowed
  "long string", "shrt" # columns can overlap ('~' above ',')
)

# right-aligned after =
purrr::map(x, fun, # arguments on same line as opening brace are not considered
  arg2 =       2,
  ar   = f(k, x)
)

# left aligned after =
purrr::map(x, fun, # arguments on same line as opening brace are not considered
  arg2 = 2,
  ar   = f(k, x)
)
```

# Details

An important definition used in the remainder is the one of a **column**. All arguments of a function call that have the same position but are placed on different lines form a column. The below call shows a call with two columns and two rows. Columns separate arguments of the function call, so the separator is the comma. The first row is named because all arguments are named, the second is unnamed:

```{r}
call(
  # column 1  | column 2 |
  abkj = f(2), 7,        # | row 1
  more_ = "a", 2         # | row 2
)
```

**For alignment detection, the first column is omitted if not all arguments in that column are named**

## Function calls

Below, we try to explain in an intuitive way how your code should look like to be recognized as aligned.

Make commas match position vertically and align everything right before commas:

```{r}
# all arguments of first column named -> must right align values after `=`,
# one or more spaces around `=`, none before and at least one after the comma.
# aligned if the (imaginary) comma on the last line is in line with the commas
fell(
  x  =    1,
  y  =   23,
  zz = NULL
)

# this works also with more than one column
fell(
  x  =    1, annoying =       3,
  y  =   23, # nothing in column 2 for row 2
  zz = NULL, finally  = "stuff"
)

# or if not all arguments of the first column are named
gell(
  p = 2,   g = gg(x),  n = 3 * 3, #
  31,    fds =    -1, gz = f / 3,
)
```

... or match position of `=` vertically and align everything after this operator left

```{r}
# all arguments of first column named -> must left align values after `=`,
# at least one space before `=`, exactly one after, none before and at least one
# after the comma.
# aligned if the first values after `=` are aligned (and exactly one space after
# `=`)
fell(
  x = 1,
  y = 23,
  zz = NULL
)

# this works also with more than one column
fell(
  x  = 1,   annoying = 3,
  y  = 23, # nothing in column 2 for row 2
  zz = NULL, finally = "stuff"
)

# or if not all arguments of the first column are named
gell(
  p = 2, g = gg(x), n = 3 * 3, #
  31, fds = -1, gz = f / 3 + 1,
)
```

... or match the start of the token after `,`

```{r}
call(
  x = 2,           p = "another",
  y = "hhjkjkbew", x = 3
)

tibble::tribble(
  ~x,        ~y,
  "another", 1:3,
  "b",       1211234
)
```

## Comments

not supported yet.

## Assignment

not supported yet.
