Type: | Package |
Title: | Non-Invasive Pretty Printing of R Code |
Version: | 1.10.3 |
Description: | Pretty-prints R code without changing the user's formatting intent. |
License: | MIT + file LICENSE |
URL: | https://github.com/r-lib/styler, https://styler.r-lib.org |
BugReports: | https://github.com/r-lib/styler/issues |
Depends: | R (≥ 3.6.0) |
Imports: | cli (≥ 3.1.1), magrittr (≥ 2.0.0), purrr (≥ 0.2.3), R.cache (≥ 0.15.0), rlang (≥ 1.0.0), rprojroot (≥ 1.1), tools, vctrs (≥ 0.4.1), withr (≥ 2.3.0), |
Suggests: | data.tree (≥ 0.1.6), digest, here, knitr, prettycode, rmarkdown, roxygen2, rstudioapi (≥ 0.7), tibble (≥ 1.4.2), testthat (≥ 3.0.0) |
VignetteBuilder: | knitr |
Encoding: | UTF-8 |
RoxygenNote: | 7.3.1 |
Config/testthat/edition: | 3 |
Config/testthat/parallel: | true |
Collate: | 'addins.R' 'communicate.R' 'compat-dplyr.R' 'compat-tidyr.R' 'detect-alignment-utils.R' 'detect-alignment.R' 'environments.R' 'expr-is.R' 'indent.R' 'initialize.R' 'io.R' 'nest.R' 'nested-to-tree.R' 'parse.R' 'reindent.R' 'token-define.R' 'relevel.R' 'roxygen-examples-add-remove.R' 'roxygen-examples-find.R' 'roxygen-examples-parse.R' 'roxygen-examples.R' 'rules-indention.R' 'rules-line-breaks.R' 'rules-spaces.R' 'rules-tokens.R' 'serialize.R' 'set-assert-args.R' 'style-guides.R' 'styler-package.R' 'stylerignore.R' 'testing-mocks.R' 'testing-public-api.R' 'ui-caching.R' 'testing.R' 'token-create.R' 'transform-block.R' 'transform-code.R' 'transform-files.R' 'ui-styling.R' 'unindent.R' 'utils-cache.R' 'utils-files.R' 'utils-navigate-nest.R' 'utils-strings.R' 'utils.R' 'vertical.R' 'visit.R' 'zzz.R' |
NeedsCompilation: | no |
Packaged: | 2024-04-07 19:04:20 UTC; lorenz |
Author: | Kirill Müller |
Maintainer: | Lorenz Walthert <lorenz.walthert@icloud.com> |
Repository: | CRAN |
Date/Publication: | 2024-04-07 23:00:02 UTC |
styler: Non-Invasive Pretty Printing of R Code
Description
styler allows you to format .qmd
, .R
, .Rmd
, .Rmarkdown
,
.Rnw
, and/or .Rprofile
files, R packages, or entire R source trees
according to a style guide.
The following functions can be used for styling:
-
style_text()
to style a character vector. -
style_file()
to style a single file. -
style_dir()
to style all files in a directory. -
style_pkg()
to style the source files of an R package. -
RStudio Addins to style either selected code or the active file.
Author(s)
Maintainer: Lorenz Walthert lorenz.walthert@icloud.com
Authors:
Kirill Müller kirill@cynkra.com (ORCID)
Other contributors:
Indrajeet Patil patilindrajeet.science@gmail.com (ORCID) (@patilindrajeets) [contributor]
See Also
Useful links:
Report bugs at https://github.com/r-lib/styler/issues
Examples
style_text("call( 1)")
style_text("1 + 1", strict = FALSE)
style_text("a%>%b", scope = "spaces")
style_text("a%>%b; a", scope = "line_breaks")
style_text("a%>%b; a", scope = "tokens")
Add the block id to a parse table
Description
Must be after nest_parse_data()
because requires a nested parse table as
input.
Usage
add_cache_block(pd_nested)
Arguments
pd_nested |
A top-level nest. |
Add column pos_id
and short
Description
Adds column pos_id
and short
to a flat parse table.
Usage
add_id_and_short(pd)
Arguments
pd |
A flat parse table |
Add the roxygen mask to code
Description
This function compares text
with initial_text
to make sure a mask is only
added to roxygen comments, not ordinary comments
Usage
add_roxygen_mask(text, initial_text, example_type)
Arguments
text |
Character vector with code. |
initial_text |
The roxygen code example to style with mask and potentially ordinary comments. |
example_type |
Either 'examples' or 'examplesIf'. |
Concentrate newlines or spaces in a string
Description
Concentrate newlines or spaces in a string
Usage
add_newlines(n)
add_spaces(n)
Arguments
n |
Scalar indicating how many characters should be concentrated |
Value
A string.
Adds the stylerignore column
Description
If a token should be ignored, the column is set to TRUE
,
otherwise to FALSE
.
Usage
add_stylerignore(pd_flat)
Arguments
pd_flat |
A parse table. |
Details
A token is ignored iff one of the two conditions hold:
it falls between a start and a stop marker whereas the markers are on their own line. Which tokens are recognized as markers is controlled with the R options
styler.ignore_start
andstyler.ignore_stop
.it is not a comment, but the last token on the line is a marker.
See examples in stylerignore. Note that you should reuse the stylerignore
column to compute switch points or similar and not a plain
pd$text %in% option_read("styler.ignore_start")
because that will fail to
give correct switch points in the case stylerignore sequences are invalid.
Add information about previous / next token to each terminal
Description
Note that this does function must be called in compute_parse_data_nested()
and we cannot wait to initialize this attribute until apply_transformers()
,
where all other attributes are initialized with
default_style_guide_attributes()
(when using tidyverse_style()
) because
for cached code, we don't build up the nested structure and leave it shallow
(to speed up things), see also shallowify()
.
Usage
add_terminal_token_after(pd_flat)
add_terminal_token_before(pd_flat)
add_attributes_caching(pd_flat, transformers, more_specs)
Arguments
pd_flat |
A flat parse table. |
transformers |
Passed to |
more_specs |
Passed to |
Functions
-
add_attributes_caching()
: Initializesnewlines
andlag_newlines
.
Checks if all arguments of column 1 are named
Description
Checks if all arguments of column 1 are named
Usage
alignment_col1_all_named(relevant_pd_by_line)
Arguments
relevant_pd_by_line |
A list with parse tables of a multi-line call, excluding first and last column. |
Remove all comment tokens
Description
Must be after split by line because it invalidates (lag)newlines, which are used for splitting by line.
Usage
alignment_drop_comments(pd_by_line)
Arguments
pd_by_line |
A list, each element corresponding to a potentially incomplete parse table that represents all token from one line. |
Remove last expression
Description
In a nest, if the last token is an expr
, the nest represents either
an if, while or for statement or a function call. We don't call about that
part, in fact it's important to remove it for alignment. See 'Examples'.
Usage
alignment_drop_last_expr(pds_by_line)
Examples
call(
x = 12,
y = 3,
)
function(a = 33,
qq = 4) {
# we don't care about this part for alignment detection
}
Ensure the closing brace of the call is removed
Description
Must be after dropping comments because the closing brace is only guaranteed to be the last token in that case.
Usage
alignment_ensure_no_closing_brace(pd_by_line, last_line_droped_early)
Arguments
pd_by_line |
A list, each element corresponding to a potentially incomplete parse table that represents all token from one line. |
Ensure last pd has a trailing comma
Description
Must be after alignment_ensure_no_closing_brace()
because if it comes after
alignment_ensure_trailing_comma()
, the last expression would not be a
brace, which would make removal complicated.
Usage
alignment_ensure_trailing_comma(pd_by_line)
Arguments
pd_by_line |
A list, each element corresponding to a potentially incomplete parse table that represents all token from one line. |
Check if spacing around comma is correct
Description
At least one space after comma, none before, for all but the last comma on the line
Usage
alignment_has_correct_spacing_around_comma(pd_sub)
Arguments
pd_sub |
The subset of a parse table corresponding to one line. |
Check if spacing around =
is correct
Description
At least one space around EQ_SUB
Usage
alignment_has_correct_spacing_around_eq_sub(pd_sub)
Arguments
pd_sub |
The subset of a parse table corresponding to one line. |
Serialize text from a parse table
Description
Line breaks are ignored as they are expected to be checked in
token_is_on_aligned_line()
.
Usage
alignment_serialize(pd_sub)
Serialize all lines for a given column
Description
Serialize all lines for a given column
Usage
alignment_serialize_column(relevant_pd_by_line, column)
Arguments
relevant_pd_by_line |
A list with parse tables of a multi-line call, excluding first and last column. |
column |
The index of the column to serialize. |
Serialize one line for a column
Description
Serialize one line for a column
Usage
alignment_serialize_line(relevant_pd_by_line, column)
Arguments
relevant_pd_by_line |
A list with parse tables of a multi-line call, excluding first and last column. |
column |
The index of the column to serialize. |
Apply reference indention to tokens
Description
Applies the reference indention created with functions
update_indention_ref()
to the flattened parse table. The indention
is applied to all token that inherit from a reference token sequentially,
i.e. by looping over the target tokens.
Usage
apply_ref_indention(flattened_pd)
Arguments
flattened_pd |
A flattened parse table |
Applying reference indention of a target token
Description
Applies the indention level of target_token
to all tokens that have
target_token
as a reference. This includes adding spaces to the first
tokens on a line and updating the column col1
and col2
for all tokens
on that line so they are kept updated.
Usage
apply_ref_indention_one(flattened_pd, target_token)
Arguments
flattened_pd |
A flattened parse table |
target_token |
The index of the token from which the indention level should be applied to other tokens. |
Ensure correct positional information for stylerignore expressions
Description
Ensure correct positional information for stylerignore expressions
Usage
apply_stylerignore(flattened_pd)
Arguments
flattened_pd |
A flattened parse table. |
Details
Get the positional information for tokens with a stylerignore tag from
env_current
, which recorded that information from the input text.Replace the computed lag_newlines and lag_spaces information in the parse table with this information.
Because we may remove or add tokens when applying the transformers, it is not save to merge via the pos_id of each token in a stylerignore sequence. We assume that the start and stop markers are the same after styling, so we join all tokens that were initially in a stylerignore sequence via the first pos_id in that stylerignore sequence.
Apply transformers to a parse table
Description
The column multi_line
is updated (after the line break information is
modified) and the rest of the transformers are applied afterwards,
The former requires two pre visits and one post visit.
Usage
apply_transformers(pd_nested, transformers)
Arguments
pd_nested |
A nested parse table. |
transformers |
A list of named transformer functions |
Details
The order of the transformations is:
Initialization (must be first).
Line breaks (must be before spacing due to indention).
Update of newline and multi-line attributes (must not change afterwards, hence line breaks must be modified first).
spacing rules (must be after line-breaks and updating newlines and multi-line).
indention.
token manipulation / replacement (is last since adding and removing tokens will invalidate columns token_after and token_before).
Update indention reference (must be after line breaks).
Make sure all supplied file types are allowed
Description
Make sure all supplied file types are allowed
Usage
assert_filetype(lowercase_filetype)
Arguments
lowercase_filetype |
A vector with file types to check, all lower case. |
Assert text to be of positive length and replace it with the empty string otherwise.
Description
Assert text to be of positive length and replace it with the empty string otherwise.
Usage
assert_text(text)
Arguments
text |
The input to style. |
Check token validity
Description
Check whether one or more tokens exist and have a unique token-text mapping
Usage
assert_tokens(tokens)
Arguments
tokens |
Tokens to check. |
Assert the transformers
Description
Actually only assert name and version of style guide in order to make sure caching works correctly.
Usage
assert_transformers(transformers)
Arguments
transformers |
A list of transformer functions that operate on flat parse tables. |
Bind a parse table with one of its children
Description
Bind a parse table with one of its children and return parse table, ordered according to the appearance of the tokens.
Usage
bind_with_child(pd_nested, pos)
Arguments
pd_nested |
A nested parse table. |
pos |
The position of the child to bind. |
Activate or deactivate the styler cache
Description
Helper functions to control the behavior of caching. Simple wrappers around
base::options()
.
Usage
cache_activate(cache_name = NULL, verbose = !getOption("styler.quiet", FALSE))
cache_deactivate(verbose = !getOption("styler.quiet", FALSE))
Arguments
cache_name |
The name of the styler cache to use. If
|
verbose |
Whether or not to print an informative message about what the function is doing. |
See Also
Other cache managers:
cache_clear()
,
cache_info()
,
caching
Cache text
Description
Splits text
into expressions and adds these to the cache. Note that
top-level comments are not cached because caching and in particular
checking if they are cached is too expensive. Comments may be cached as part
of the whole text (as opposed to on an expression by expression basis) using
cache_write()
directly. Also, we must not cache stylerignore sequence,
because we might see the same expression that does not comply with the style
guide outside a stylerignore sequence and wrongly think we should leave it as
is.
Usage
cache_by_expression(text, transformers, more_specs)
Arguments
text |
A character vector with one or more expressions. |
transformers |
A list of transformer functions, because we can only know if text is already correct if we know which transformer function it should be styled with. |
more_specs |
A named vector coercible to character that determines the
styling but are style guide independent, such as |
Clear the cache
Description
Clears the cache that stores which files are already styled. You won't be
able to undo this. Note that the file corresponding to the cache (a folder
on your file system) won't be deleted, but it will be empty after calling
cache_clear
.
Usage
cache_clear(cache_name = NULL, ask = TRUE)
Arguments
cache_name |
The name of the styler cache to use. If
|
ask |
Whether or not to interactively ask the user again. |
Details
Each version of styler has its own cache by default, because styling is potentially different with different versions of styler.
See Also
Other cache managers:
cache_activate()
,
cache_info()
,
caching
Find the groups of expressions that should be processed together
Description
Find the groups of expressions that should be processed together
Usage
cache_find_block(pd)
Arguments
pd |
A top-level nest. |
Details
We want blocks to be formed according to these rules:
Blocks should contain either cached or uncached expressions only. If a block contains cached expressions only, it does not have to be processed and can be returned immediately. If a block contains uncached expressions, it makes sense to put as many uncached expression in it, since processing one bigger block has less overhead than processing many smaller blocks.
Multiple expressions can sit on one row, e.g. in-line comment and commands separated with ";". This creates a problem when processing each expression separately because when putting them together, we need complicated handling of line breaks between them, as it is not a priori clear that there is a line break separating them. To avoid this, we put top-level expressions that sit on the same line into one block, so the assumption that there is a line break between each block of expressions holds.
All expressions in a stylerignore sequence must be in the same block. If that's not the case, the first expression in a block might not be a top-level terminal, but another top-level expression.
apply_stylerignore()
joinsenv_current$stylerignore
, which contains only terminals, with the first expression in a stylerignore sequence, based on the firstpos_id
in that stylerignore sequence (first_pos_id_in_segment
).
Where is the cache?
Description
Finds the path to the cache and creates it if it does not exist.
Usage
cache_find_path(cache_name = NULL)
Arguments
cache_name |
The name of the styler cache to use. If
|
Show information about the styler cache
Description
Gives information about the cache. Note that the size consumed by the cache will always be displayed as zero because all the cache does is creating an empty file of size 0 bytes for every cached expression. The inode is excluded from this displayed size but negligible.
Usage
cache_info(cache_name = NULL, format = "both")
Arguments
cache_name |
The name of the cache for which to show details. If
|
format |
Either "lucid" for a summary emitted with |
See Also
Other cache managers:
cache_activate()
,
cache_clear()
,
caching
Check if a cache is activated
Description
Check if a cache is activated
Usage
cache_is_activated(cache_name = NULL)
Arguments
cache_name |
The name of the cache to check. If |
Make a key for R.cache
Description
This is used to determine if caching already corresponds to a style guide.
Usage
cache_make_key(text, transformers, more_specs)
Arguments
text |
Code to create a cache for. This should be styled text, as the approach used by styler does not cache input, but styled code. |
transformers |
A list of transformer functions, because we can only know if text is already correct if we know which transformer function it should be styled with. |
more_specs |
A named vector coercible to character that determines the
styling but are style guide independent, such as |
Details
We need to compare:
text to style. Will be passed to hash function as is.
styler version. Not an issue because for every version of styler, we build a new cache.
transformers. Cannot easily hash them because two environments won't be identical even if they contain the same objects (see 'Experiments'). Simple
as.character(transformers)
will not consider infinitively recursive code dependencies. To fix this, transformers must have names and version number as described increate_style_guide()
. Now, the only way to fool the cache invalidation is to replace a transformer with the same function body (but changing the function definition of the functions called in that body) interactively without changing version number of name at the same time. Remaining problem:purrr::partial()
calls will render generic code, e.g. seeas.character(list(purrr::partial(sum, x = 4)))
. For that reason, all arguments passed to apurrr::partial()
call must be put in the style guide undermore_specs_style_guide
.
Experiments
There is unexplainable behavior in conjunction with hashing and environments:
Functions created with
purrr::partial()
are not identical when compared withidentical()
(StackOverflow)except when they have the exact same parent environment, which must be an object created and then passed to
purrr::partial(.env = ...)
, not created in-place.-
purrr::partial()
seems to ignore.env
after version 0.2.5, so until this is fixed, we'd have to work with version 0.2.5. Our caching backend package,
R.cache
, usesR.cache:::getChecksum.default
(which usesdigest::digest()
) to hash the input. The latter does not seem to care if the environments are exactly equal (see 'Examples').However, under some circumstances, it does: Commit 9c94c022 (if not overwritten / rebased by now) contains a reprex. Otherwise, search for 43219ixmypi in commit messages and restore this commit to reproduce the behavior.
Examples
add <- function(x, y) {
x + y
}
add1 <- purrr::partial(add, x = 1)
add2 <- purrr::partial(add, x = 1)
identical(add1, add2)
identical(digest::digest(add1), digest::digest(add2))
identical(digest::digest(styler::tidyverse_style()), digest::digest(styler::tidyverse_style()))
Create more specs
Description
Syntactic sugar for creating more specs. This is useful when we want to add more arguments (because we can search for this function in the source code).
Usage
cache_more_specs(include_roxygen_examples, base_indention)
Write to the cache
Description
Write to the cache
Usage
cache_write(text, transformers, more_specs)
Arguments
text |
Code to create a cache for. This should be styled text, as the approach used by styler does not cache input, but styled code. |
transformers |
A list of transformer functions, because we can only know if text is already correct if we know which transformer function it should be styled with. |
more_specs |
A named vector coercible to character that determines the
styling but are style guide independent, such as |
Remember the past to be quicker in the future
Description
Caching makes styler faster on repeated styling and is shared across all APIs
(e.g. style_text()
and Addin). That means if you style code that already
complies to a style guide and you have previously styled that code, it will
be quicker.
Configuring the cache
To comply with the CRAN policy, {styler} will by default clean up cache files that are older than 6 days. This implies that you loose the benefit of the cache for the files not styled in the last 6 days.
If you want to avoid this, i.e., if you want the cache to last longer, you can use the
R option styler.cache_root
to opt for an indefinitely long-lived cache by setting it to
options(styler.cache_root = "styler-perm")
.
If you are happy with the cache being cleared after 6 days, you can confirm the default and
silence this message by setting it instead to options(styler.cache_root = "styler")
.
You can make this change in your .Rprofile
using usethis::edit_r_profile()
.
Manage the cache
See cache_info()
,cache_activate()
or cache_clear()
for utilities to
manage the cache. You can deactivate it altogether with cache_deactivate()
.
Since we leverage {R.cache}
to manage the cache, you can also use any
{R.cache}
functionality to manipulate it.
In some cases, you want to use a non-standard cache location. In
that situation, you can set the path to the cache with the R option
R.cache.rootPath
or the environment variable R_CACHE_ROOTPATH
to an
existent path before you call the styler API.
Invalidation
The cache is specific to a version of styler by default, because different versions potentially format code differently. This means after upgrading styler or a style guide you use, the cache will be re-built.
Mechanism and size
The cache works by storing hashed output code as a whole and by expression, which is why it takes zero space on disk (the cache is a directory with empty files which have the hash of output code as name).
The cache literally takes zero space on your disk, only the inode, and you
can always manually clean up with cache_clear()
or just go to the
directory where the cache lives (find it with cache_info()
) and manually
delete files.
Using a cache for styler in CI/CD
If you want to set up caching in a CI/CD pipeline, we suggest to set the
{R.cache}
root path to a directory for which you have the cache enabled.
This can often be set in config files of CI/CD tools, e.g. see the
Travis documentation on caching.
See Also
Other cache managers:
cache_activate()
,
cache_clear()
,
cache_info()
Invoke a system command
Description
Wraps a system command into shell()
or system()
, depending on the
operating system.
Usage
calls_sys(sys_call, ...)
Arguments
sys_call |
The call to be executed. |
... |
Capture and post-process the output of style_file
without causing side
effects
Description
Capture and post-process the output of style_file
without causing side
effects
Usage
catch_style_file_output(file_in)
Arguments
file_in |
A vector with paths relative to |
Value
A list. Each element is a character vector with the captured output of
style_file()
called on
file_in
ran in a temp dir to avoid side effects on the input file (because
the next time the test would ran, the file would not need styling). The
styling is carried out with a temporary working directory change to keep
filenames relative and avoid portability issues in the exact output
comparison which is needed when the system that runs the unit testing (CI)
is a different system than the one that created the reference value.
This also implies that the ruler width, which depend on the path
length, will again have the same width on all systems and is independent of
how many characters the path of the temporary directory has.
Choose the indention method for the tokens
Description
Either use the raw indention, which is just the spaces computed between
the first token on a new line and the token before it, or use the indention
computed according to the transformer used, which is stored in the column
indention
.
All indention information will be combined with the space information for
the first token on a new line.
If use_raw_indention
is set, information in the column indention
will
be discarded anyways. If it is not set, the first token on a new line will
"inherit" the indention of the whole line.
The column indention
will be removed since all information necessary is
contained in the spacing information of the first token on a new line and
the position of the tokens will not be changed anymore at this stage.
Usage
choose_indention(flattened_pd, use_raw_indention)
Arguments
flattened_pd |
A nested parse table that was turned into a flat parse
table using |
use_raw_indention |
Boolean indicating whether or not the raw indention should be used. |
Combine child and internal child
Description
Binds two parse tables together and arranges them so that the tokens are in the correct order.
Usage
combine_children(child, internal_child)
Arguments
child |
A parse table or |
internal_child |
A parse table or |
Details
Essentially, this is a wrapper around vctrs::vec_rbind()], but
returns NULL
if the result of vctrs::vec_rbind()] is a data frame with
zero rows.
Communicate the summary of styling
Description
Communicate the summary of styling
Usage
communicate_summary(changed, ruler_width)
Arguments
changed |
Boolean with indicating for each file whether or not it has been changed. |
ruler_width |
Integer used to determine the width of the ruler. |
Communicate a warning if necessary
Description
If round trip verification was not possible, issue a warning to review the changes carefully.
Usage
communicate_warning(changed, transformers)
Arguments
changed |
Boolean with indicating for each file whether or not it has been changed. |
transformers |
The list of transformer functions used for styling. Needed for reverse engineering the scope. |
Compute the indices that need indention
Description
Based on token
, find the rows in pd
that need to be indented.
Usage
compute_indent_indices(pd, token_opening, token_closing = NULL)
Arguments
pd |
A parse table. |
token_opening |
A character vector with tokens that could induce indention for subsequent tokens. |
token_closing |
A character vector with tokens that could terminate
indention for previous tokens. If |
Details
Two cases are fundamentally different:
Indention based on operators (e.g '+'), where all subsequent tokens should be indented.
Indention based on braces (e.g. '('), where just the tokens between the opening and the closing brace have to be indented.
To cover the second case, we need token_closing
because it cannot be taken
for granted that token_closing
is always the last token in pd
. For
example in if-else expressions, this is not the case and indenting
everything between '(' and the penultimate token would result in the wrong
formatting.
Handing of [[
Since text [[
has token "LBB"
and text ]]
is parsed as two independent
]
(see 'Examples'), indention has to stop at the first ]
.
Examples
styler:::parse_text("a[1]")
styler:::parse_text("a[[1\n]]")
Obtain a nested parse table from a character vector
Description
Parses text
to a flat parse table and subsequently changes its
representation into a nested parse table with nest_parse_data()
.
Usage
compute_parse_data_nested(
text,
transformers = tidyverse_style(),
more_specs = NULL
)
Arguments
text |
The text to parse. |
transformers |
Passed to |
more_specs |
Passed to |
Value
A nested parse table. See tokenize()
for details on the columns
of the parse table.
Examples
code <- "
ab <- 1L # some comment
abcdef <- 2L
"
writeLines(code)
compute_parse_data_nested(code)
Construct *-out.R from a *-in.R
Description
Multiple *-in.R files can have the same *-out.R file since to create the *-out.R file, everything after the first dash is replaced by *-out.R.
Usage
construct_out(in_paths)
Arguments
in_paths |
A character vector that denotes paths to *-in.R files. |
Examples
styler:::construct_out(c(
"path/to/file/first-in.R",
"path/to/file/first-extended-in.R"
))
Construct paths of a tree object given the paths of *-in.R files
Description
Construct paths of a tree object given the paths of *-in.R files
Usage
construct_tree(in_paths, suffix = "_tree")
Arguments
in_paths |
Character vector of *-in.R files. |
suffix |
Suffix for the tree object. |
Construct an object of class vertical
Description
Sole purpose of the class vertical is to have a print method that aligns the output vertically.
Usage
construct_vertical(x)
Arguments
x |
A character vector or an object of class "vertical". |
Check whether an else expression needs braces
Description
Checks whether an else expression in a nest needs braces. Note that for if-else-if expressions, there is no need to add braces since the if in else-if will be visited separately with the visitor. This applies to all conditional statements with more than one alternative.
Usage
contains_else_expr_that_needs_braces(pd)
Arguments
pd |
A parse table |
Propagate context to terminals
Description
Implements a very specific pre-visiting scheme, namely to propagate
indention, spaces and lag_newlines to inner token to terminals. This means
that information regarding indention, line breaks and spaces (which is
relative in pd_nested
) will be converted into absolute.
Usage
context_to_terminals(
pd_nested,
outer_lag_newlines,
outer_indent,
outer_spaces,
outer_indention_refs
)
Arguments
pd_nested |
A nested parse table. |
outer_lag_newlines |
The lag_newlines to be propagated inwards. |
outer_indent |
The indention depth to be propagated inwards. |
outer_spaces |
The number of spaces to be propagated inwards. |
outer_indention_refs |
The reference pos id that should be propagated inwards. |
Value
An updated parse table.
See Also
context_towards_terminals visitors
Update the a parse table given outer context
Description
outer_lag_newlines
are added to the first token in pd
,
outer_indent
is added to all tokens in pd
, outer_spaces
is added to the
last token in pd
. context_to_terminals()
calls this function repeatedly,
which means the propagation of the parse information to the terminal tokens.
Usage
context_towards_terminals(
pd_nested,
outer_lag_newlines,
outer_indent,
outer_spaces,
outer_indention_refs
)
Arguments
pd_nested |
A nested parse table. |
outer_lag_newlines |
The lag_newlines to be propagated inwards. |
outer_indent |
The indention depth to be propagated inwards. |
outer_spaces |
The number of spaces to be propagated inwards. |
outer_indention_refs |
The reference pos id that should be propagated inwards. |
Value
An updated parse table.
See Also
context_to_terminals
Replace the newline character with a line break
Description
Replace the newline character with a line break
Usage
convert_newlines_to_linebreaks(text)
Arguments
text |
A character vector |
Examples
styler:::convert_newlines_to_linebreaks("x\n2")
# a simple strsplit approach does not cover both cases
unlist(strsplit("x\n\n2", "\n", fixed = TRUE))
unlist(strsplit(c("x", "", "2"), "\n", fixed = TRUE))
styler:::convert_newlines_to_linebreaks(c("x", "2"))
Copy a file to a temporary directory
Description
Takes the path to a file as input and returns the path where the temporary file is stored. Don't forget to unlink once you are done.
Usage
copy_to_tempdir(path_perm = testthat_file())
Arguments
path_perm |
The path of the file to copy. |
Create node from nested parse data
Description
Create node from nested parse data
Usage
create_node_from_nested(pd_nested, parent, structure_only)
Arguments
pd_nested |
A nested data frame. |
parent |
The parent of the node to be created. |
structure_only |
Whether or not create a tree that represents the structure of the expression without any information on the tokens. Useful to check whether two structures are identical. |
Convert a nested data frame into a node tree
Description
This function is convenient to display all nesting levels of a nested data frame at once.
Usage
create_node_from_nested_root(pd_nested, structure_only)
Arguments
pd_nested |
A nested data frame. |
structure_only |
Whether or not create a tree that represents the structure of the expression without any information on the tokens. Useful to check whether two structures are identical. |
Value
An object of class "Node" and "R6".
Examples
if (rlang::is_installed("data.tree")) {
withr::with_options(
list(styler.cache_name = NULL), # temporarily deactivate cache
{
code <- "a <- function(x) { if(x > 1) { 1+1 } else {x} }"
nested_pd <- compute_parse_data_nested(code)
initialized <- styler:::pre_visit_one(
nested_pd, default_style_guide_attributes
)
styler:::create_node_from_nested_root(initialized,
structure_only = FALSE
)
}
)
}
Create valid pos_ids if possible
Description
Create valid pos_ids if possible
Usage
create_pos_ids(pd, pos, by = 0.1, after = FALSE, n = 1L)
Arguments
pd |
A parse table. |
pos |
The position where the new id should be inserted. |
by |
By how much the reference |
after |
Boolean indicating whether it should be inserted after or before
|
n |
Number of ids to generate. |
Value
Returns a valid sequences of pos_ids or an error if it was not possible to
create one. The validation is done with validate_new_pos_ids()
See Also
Other token creators:
create_tokens()
,
validate_new_pos_ids()
Create a style guide
Description
This is a helper function to create a style guide, which is technically
speaking a named list of groups of transformer functions where each
transformer function corresponds to one styling rule. The output of this
function can be used as an argument for style
in top-level functions
like style_text()
and friends. Note that for caching to work properly,
unquote all inputs to the transformer function if possible with rlang's !!
,
otherwise, they will be passed as references (generic variable names) instead
of literals and styler:::is_cached()
won't pick up changes. See how it's
done in tidyverse_style()
with indent_by
and other arguments.
Usage
create_style_guide(
initialize = default_style_guide_attributes,
line_break = NULL,
space = NULL,
token = NULL,
indention = NULL,
use_raw_indention = FALSE,
reindention = tidyverse_reindention(),
style_guide_name = NULL,
style_guide_version = NULL,
more_specs_style_guide = NULL,
transformers_drop = specify_transformers_drop(),
indent_character = " "
)
Arguments
initialize |
The bare name of a function that initializes various variables on each level of nesting. |
line_break |
A list of transformer functions that manipulate line_break information. |
space |
A list of transformer functions that manipulate spacing information. |
token |
A list of transformer functions that manipulate token text. |
indention |
A list of transformer functions that manipulate indention. |
use_raw_indention |
Boolean indicating whether or not the raw indention should be used. |
reindention |
A list of parameters for regex re-indention, most
conveniently constructed using |
style_guide_name |
The name of the style guide. Used as a meta attribute
inside the created style guide, for example for caching. By convention,
this is the style guide qualified by the package namespace plus the
location of the style guide, separated by |
style_guide_version |
The version of the style guide. Used as a meta attribute inside the created style guide, for example for caching. This should correspond to the version of the R package that exports the style guide. |
more_specs_style_guide |
Named vector (coercible to character)
with all arguments passed to the style guide and used for cache
invalidation. You can easily capture them in your style guide function
declaration with |
transformers_drop |
A list specifying under which conditions
transformer functions can be dropped since they have no effect on the
code to format, most easily constructed with
|
indent_character |
The character that is used for indention. We strongly advise for using spaces as indention characters. |
Examples
set_line_break_before_curly_opening <- function(pd_flat) {
op <- pd_flat$token %in% "'{'"
pd_flat$lag_newlines[op] <- 1L
pd_flat
}
set_line_break_before_curly_opening_style <- function() {
create_style_guide(
line_break = list(set_line_break_before_curly_opening),
style_guide_name = "some-style-guide",
style_guide_version = "some-version"
)
}
style_text(
"a <- function(x) { x }",
style = set_line_break_before_curly_opening_style
)
Create a terminal token
Description
Creates a terminal token represented as (a row of) a parse table.
Usage
create_tokens(
tokens,
texts,
lag_newlines = 0L,
spaces = 0L,
pos_ids,
token_before = NA,
token_after = NA,
indention_ref_pos_ids = NA,
indents,
terminal = TRUE,
child = NULL,
stylerignore,
block = NA,
is_cached = FALSE
)
Arguments
tokens |
Character vector with tokens to create. |
texts |
Character vector with texts of the token to create. |
lag_newlines |
Character vector with lag_newlines corresponding to the tokens. |
spaces |
Character vector with spaces corresponding to the tokens. |
pos_ids |
Character vector with positional id corresponding to the tokens. |
token_before |
Character vector corresponding to the columns
|
token_after |
Character vector corresponding to the columns
|
indention_ref_pos_ids |
Character vector with indention ref ids corresponding to the tokens. |
indents |
Vector with indents corresponding to the tokens. |
terminal |
Boolean vector indicating whether a token is a terminal or not. |
child |
The children of the tokens. |
stylerignore |
Boolean to indicate if the line should be ignored by styler. Must take value from token before, can't have a default. |
block |
The block (of caching) to which the token belongs. An integer. |
is_cached |
Whether the token is cached already. |
See Also
Other token creators:
create_pos_ids()
,
validate_new_pos_ids()
Create a tree from text
Description
Create a tree representation from a text.
Usage
create_tree(text, structure_only = FALSE)
Arguments
text |
A character vector. |
structure_only |
Whether or not create a tree that represents the structure of the expression without any information on the tokens. Useful to check whether two structures are identical. |
Value
A data frame.
Initialize default style guide attributes
Description
This function initializes and removes various variables from the parse table.
Usage
default_style_guide_attributes(pd_flat)
Arguments
pd_flat |
A parse table. |
Examples
withr::with_options(
list(styler.cache_name = NULL), # temporarily deactivate cache
{
string_to_format <- "call( 3)"
pd <- compute_parse_data_nested(string_to_format)
styler:::pre_visit_one(pd, default_style_guide_attributes)
}
)
Delete a cache or temp directory
Description
For safety, path
is only deleted if it is a sub-directory of a temporary
directory or user cache. Since this function relies on tools::R_user_dir()
,
it early returns FALSE
on R < 4.0.0
.
Usage
delete_if_cache_directory(path)
Arguments
path |
Absolute path to a directory to delete. |
Value
TRUE
if anything was deleted, FALSE
otherwise.
dir()
, but without dot-prefix and different defaults
Description
When using dir()
, you can set full.names = FALSE
, but then you can only
pass a character vector of length one as path
to not loose the information
about where the files are. This function solves that case. It's needed when
one wants to standardize paths to use set operations on them, i.e. when the
user supplied input does not have a dot prefix. See 'Examples'.
Usage
dir_without_.(path, recursive = TRUE, ...)
Arguments
path |
A path. |
... |
Passed to |
Details
For different defaults, see dir_without_._one
.
See Also
set_and_assert_arg_paths
Examples
setdiff("./file.R", "file.R") # you want to standardize first.
dir()
, but with full names, ignored case, and included hidden files and
recursive.
Description
dir()
, but with full names, ignored case, and included hidden files and
recursive.
Usage
dir_without_._one(path, recursive, ...)
Convert roxygen comments to Rd code
Description
We leverage roxygen2 workhorse function roxygen2::roc_proc_text()
if
our input contains character that have to be escaped. Since this is an
expensive operation, we opt out of it and perform a simple
remove_roxygen_mask()
when there are no characters to escape.
Usage
emulate_rd(roxygen)
Enhance the mapping of text to the token "SPECIAL"
Description
Map text corresponding to the token "SPECIAL" to a (more) unique token description.
Usage
enhance_mapping_special(pd)
Arguments
pd |
A parse table. |
Enrich flattened parse table
Description
Enriches a flattened parse table with terminals only. In particular, it is possible to compute the exact position a token will have (line and column) when it will be serialized.
Usage
enrich_terminals(flattened_pd, use_raw_indention = FALSE)
Arguments
flattened_pd |
A nested parse table that was turned into a flat parse
table using |
use_raw_indention |
Boolean indicating whether or not the raw indention should be used. |
Details
Since we have only terminal tokens now, the line on which a token starts we
also be the line on which it ends. We call line1
the line on which the
token starts. line1
has the same meaning as line1
that can be found in a
flat parse table (see tokenize()
), just that the line1
created by
enrich_terminals()
is the updated version of the former line1
. The same
applies for col1
and col2
. Note that this function does remove the
columns indent
and spaces.
All information of the former is stored in
lag_spaces
now. The later was removed because it is redundant after adding
the column lag_spaces
, which is more convenient to work with, in particular
when serializing the parse table.
Ensure a correct text
of all strings and numeric constants
Description
Make sure text
of the tokens STR_CONST
and NUM_CONST
is correct and
adapt if necessary. We replace offending text
in the terminal expressions
with the text of their parents if their line / col position matches and
return an error otherwise.
Usage
ensure_correct_txt(pd, text)
Arguments
pd |
A parse table. |
Ensure there is one (and only one) blank line at the end of a vector
Description
Ensure there is one (and only one) blank line at the end of a vector
Usage
ensure_last_n_empty(x, n = 1L)
Examples
styler:::ensure_last_n_empty("")
styler:::ensure_last_n_empty(letters)
styler:::ensure_last_n_empty(c(letters, "", "", ""))
Add positional information of token to next terminal
Description
This is needed because at serialization time, we also have terminals only
and positional argument of non-terminals were already propagated to terminals
with context_to_terminals()
. Because tokens can be added or removed during
styling, we must not only keep the pos_id, but rather we must remember the
pos_id of the first token in the stylerignore sequence (the marker, or the
first token on a line if the stylerignore marker is an inline marker), for
which we know it will still be there, and join these markers later with all
tokens in the stylerignore sequence (this is a one to many join, i.e. one
start marker can have many tokens).
Usage
env_add_stylerignore(pd_flat)
Arguments
pd_flat |
A parse table. |
The elements that are added to this environment are:
Description
The elements that are added to this environment are:
Usage
env_current
Format
An object of class environment
of length 0.
Details
-
parser_version
: Needed to dispatch between parser versions, seeparser_version_set()
for details. -
stylerignore
: A data frame with parse data containing tokens that fall within a stylerignore sequence. This is used after serializing the flattened parse table to apply the initial formatting to these tokens. See stylerignore for details. -
any_stylerignore
: Whether there is any stylerignore marker. The idea is to check early in the runtime if this is the case and then if so, take as many short-cuts as possible. See stylerignore for details.
Check whether two expressions are identical
Description
Check whether two expressions are identical
Usage
expressions_are_identical(old_text, new_text)
Arguments
old_text |
The initial expression in its character representation. |
new_text |
The styled expression in its character representation. |
Find the index of the last comment in the sequence of comments-only tokens
after the token that has position pos
in pd
.
Description
Find the index of the last comment in the sequence of comments-only tokens
after the token that has position pos
in pd
.
Usage
extend_if_comment(pd, pos)
Arguments
pd |
A parse table. |
pos |
The position of the token to start the search from. |
Extract terminal tokens
Description
Turns a nested parse table into a flat parse table and extracts all attributes.
Usage
extract_terminals(pd_nested)
Arguments
pd_nested |
A nested parse table. |
Drop start / stop, when formatting is turned off
Description
If tidy = FALSE
(the knitr code chunk default), code is not styled upon
knitting. If it is explicitly added to a code chunk, the code chunk is in
addition not styled with styler when formatting the document.
Usage
finalize_raw_chunks(start, end, filetype, lines)
Number of lines between cache blocks
Description
This is relevant when putting expressions together into a block and preserve blank lines between them. Note that because code does not need to start on line 1, the first element of the output is the number of lines until the first block.
Usage
find_blank_lines_to_next_block(pd)
Arguments
pd |
A top-level nest. |
Find blank lines
Description
What number of line breaks lay between the expressions?
Usage
find_blank_lines_to_next_expr(pd_nested)
Arguments
pd_nested |
A nested parse table. |
Value
The line number on which the first token occurs.
Find dontrun
and friend sequences
Description
Returns the indices of the lines that correspond to a dontrun
or
friends sequence.
Usage
find_dont_seqs(bare)
Arguments
bare |
Bare code. |
Find index of the token before which the line should be broken
Description
Given a multi-line function call parse table, this function finds the position of the first named argument and breaks returns the index of it. If there is no named argument, the line is broken right after the opening parenthesis.
Usage
find_line_break_position_in_multiline_call(pd)
Arguments
pd |
A parse table. |
Find the pos ids to keep
Description
To make a parse table shallow, we must know which ids to keep.
split(cumsum(pd_parent_first$parent == 0L))
above puts comments with
negative parents in the same block as proceeding expressions (but also with
positive).
find_pos_id_to_keep()
must hence always keep negative comments. We did not
use split(cumsum(pd_parent_first$parent < 1L))
because then every top-level
comment is an expression on its own and processing takes much longer for
typical roxygen annotated code.
Usage
find_pos_id_to_keep(pd)
Arguments
pd |
A temporary top-level nest where the first expression is always a top-level expression, potentially cached. |
Details
Note that top-level comments above code have negative parents (the negative value of the parent of the code expression that follows after, another comment might be in the way though), all comments that are not top level have positive ids. All comments for which no code follows afterwards have parent 0.
Examples
styler:::get_parse_data(c("#", "1"))
styler:::get_parse_data(c("c(#", "1)"))
styler:::get_parse_data(c("", "c(#", "1)", "#"))
Find legit starting value for a new positional id
Description
Looks at the current nest as well as into its children (if necessary) to make sure the right id is returned. Otherwise, ordering of tokens might not be preserved.
Usage
find_start_pos_id(pd, pos, by, direction, after, candidates = NULL)
Arguments
pd |
A parse table. |
pos |
The position where the new id should be inserted. |
by |
By how much the reference |
direction |
Derived from |
after |
Boolean indicating whether it should be inserted after or before
|
candidates |
The |
Find the tokens to update when applying a reference indention
Description
Given a target token and a flattened parse table, the token for which the
spacing information needs to be updated are computed. Since indention is
already embedded in the column lag_spaces
, only tokens at the beginning of
a line are of concern.
Usage
find_tokens_to_update(flattened_pd, target_token)
Arguments
flattened_pd |
A flattened parse table. |
target_token |
The index of the token from which the indention level should be applied to other tokens. |
See Also
apply_ref_indention_one()
Examples
style_text("function(a =
b,
dd
) {}", scope = "indention")
style_text("function(a,
b,
dd
) {}", scope = "indention")
Replace single quotes with double quotes
Description
We do not use deparse()
as in previous implementations but paste0()
since
the former approach escapes the reverse backslash in the line break character
\\n
whereas the solution with paste0()
does not.
Usage
fix_quotes(pd_flat)
Arguments
pd_flat |
A flat parse table. |
Examples
style_text("'here
is a string
'")
Flatten some token in the nested parse table based on operators
Description
Certain tokens are not placed optimally in the nested parse data with
compute_parse_data_nested()
. For example, the token of arithmetic
operations 1 + 1 + 1 should all be on the same level of nesting since the
indention is the same for all but the first two terminals. Setting the
indention correctly is easier to achieve if they are put on the same level of
nesting.
Usage
flatten_operators(pd_nested)
Arguments
pd_nested |
A nested parse table to partially flatten. |
Flatten one level of nesting with its child
Description
Flattening is done in two ways. We can flatten a parse table by moving the left hand token of an operator one level up. Or doing that with the right hand token.
Usage
flatten_operators_one(pd_nested)
Arguments
pd_nested |
A nested parse table. |
Flatten a parse table
Description
Flattens a parse table if certain tokens occur in this table or its child,
either flattening from left or from right. If one of token
is present in
pd_nested
and one of child_token
is present in one of the children next
to token
in pd_nested
, the nested parse table is flattened. Otherwise, it
is returned unmodified.
Usage
flatten_pd(pd_nested, token, child_token = token, left = TRUE)
Arguments
pd_nested |
A nested parse table. |
token |
A character vector with tokens of which at least one has to
occur in |
child_token |
A character vector of tokens of which at least one has to occur in the child in order to flatten the parse table. |
left |
Flag that indicates whether the parse table should be flattened from left or from right. |
Generate a comprehensive collection test cases for comment / insertion interaction Test consist of if / if-else / if-else-if-else cases, paired with various line-break and comment configurations. Used for internal testing.
Description
Generate a comprehensive collection test cases for comment / insertion interaction Test consist of if / if-else / if-else-if-else cases, paired with various line-break and comment configurations. Used for internal testing.
Usage
generate_test_samples()
Value
The function is called for its side effects, i.e. to write the
test cases to *-in.R files that can be tested with test_collection()
. Note
that a few of the test cases are invalid and need to be removed / commented
out manually.
Return the style function or name
Description
Return the style function or name
Usage
get_addins_style_transformer_name()
get_addins_style_transformer()
What's the engine pattern for rmd code chunks?
Description
The function returns the regular expression pattern that identifies
all r engines in Rmd chunks. Defaults to [Rr]
. You probably only want to
change this if you create a knitr engine that processes R code but is not
the default engine r
.
The pattern must be followed by a space (in the case the chunk is given
a name), a comma (if no name is given but further options are passed to the
engine) or a closing curly brace (in case no option and no name is given to
the chunk).
Usage
get_engine_pattern()
Get chunk pattern
Description
Determine a regex pattern for identifying R code chunks.
Usage
get_knitr_pattern(filetype)
Arguments
filetype |
A string indicating the filetype - either 'Rmd' or 'Rnw'. |
Obtain robust parse data
Description
Wrapper around utils::getParseData(parse(text = text))
that returns a flat
parse table. When caching information should be added, make sure that
the cache is activated with cache_activate()
and both transformers
and
cache_dir
are non-NULL
.
Usage
get_parse_data(text, include_text = TRUE, ...)
Arguments
text |
The text to parse. |
include_text |
Passed to |
... |
Other arguments passed to |
Check if a string uses CRLF EOLs
Description
Check if a string uses CRLF EOLs
Usage
has_crlf_as_first_line_sep(message, initial_text)
Arguments
message |
A message returned with |
initial_text |
The initial text to style. |
Standardize text for hashing
Description
Make sure text after styling results in the same hash as text before styling
if it is indeed identical. This function expects trailing blank lines in
text
were removed prior to passing it to this function.
Usage
hash_standardize(text)
Arguments
text |
A character vector. |
Identifies raw Rmd or Rnw code chunks
Description
Raw in the sense that these chunks don't contain pure R code, but they
contain a header and footer of markdown. Only code chunks that have an engine
whose name matches engine-pattern
are considered as R code.
For every opening, we match the next closing. If there are not the same
amount of closing and openings after this matching, we throw an error.
Similarly, if there are two openings before a closing, the closing gets
matched twice, on which we throw an error.
Usage
identify_raw_chunks(lines, filetype, engine_pattern = get_engine_pattern())
Arguments
lines |
A character vector of lines from an Rmd or Rnw file. |
filetype |
A string indicating the filetype - either 'Rmd' or 'Rnw'. |
engine_pattern |
A regular expression that must match the engine name. |
Figure out where code examples start and stop
Description
Finds the sequence from start to stop of the lines in text
that are
code examples in roxygen comments.
Usage
identify_start_to_stop_of_roxygen_examples_from_text(text)
Arguments
text |
A text consisting of code and/or roxygen comments. |
Check if if, for or while loop expression require a braces.
Description
This is the case if they are multi-line and not yet wrapped into curly braces.
Usage
if_for_while_part_requires_braces(pd, key_token)
Arguments
pd |
A parse table. |
key_token |
The token that comes right before the token that contains the expression to be wrapped (ignoring comments). For if and while loops, this is the closing "')'", for a for-loop it's "forcond". |
Initialize attributes
Description
Initialize attributes
Usage
initialize_newlines(pd_flat)
initialize_spaces(pd_flat)
initialize_multi_line(pd_flat)
initialize_indention_ref_pos_id(pd_flat)
initialize_indent(pd_flat)
validate_parse_data(pd_flat)
Arguments
pd_flat |
A parse table. |
Functions
-
initialize_newlines()
: Initializesnewlines
andlag_newlines
. -
initialize_spaces()
: Initializesspaces
. -
initialize_multi_line()
: Initializesmulti_line
. -
initialize_indention_ref_pos_id()
: Initializesindention_ref_ind
. -
initialize_indent()
: Initializesindent
. -
validate_parse_data()
: validates the parse data.
Drop-in replacement for xfun:::invalid_utf8()
Description
Drop-in replacement for xfun:::invalid_utf8()
Usage
invalid_utf8(x)
Check if text is cached
Description
This boils down to check if the hash exists at the caching dir as a file.
Usage
is_cached(text, transformers, more_specs, cache_dir = get_cache_dir())
Arguments
text |
Passed to |
transformers |
Passed to |
more_specs |
Passed to |
cache_dir |
The caching directory relative to the |
Identify spinning code chunk header or xaringan
Description
Wrongly identifies a comment without a preceding line break as a code chunk header. See https://yihui.name/knitr/demo/stitch/#spin-comment-out-texts for details.
Usage
is_code_chunk_header_or_xaringan_or_code_output(pd)
Arguments
pd |
A parse table. |
Examples
style_text(c(
"# title",
"some_code <- function() {}",
"#+ chunk-label, opt1=value1",
"call(3, 2, c(3:2))",
"#> 99"
))
Is the function declaration double indented?
Description
Assumes you already checked if it's a function with
is_function_declaration
. It is double indented if the first token
after the first line break that is a "SYMBOL_FORMALS"
.
Usage
is_double_indent_function_declaration(pd, indent_by = 2L)
Arguments
pd |
A parse table. |
indent_by |
How many spaces of indention should be inserted after operators such as '('. |
Identify strings that were not fully parsed
Description
Identifies strings that were not fully parsed due to their vast length.
Usage
is_insufficiently_parsed_string(pd)
Arguments
pd |
A parse table. |
Details
The meaning of the variable is_problematic_string
in the source code
changes from "all strings" to "all problematic strings", is partly
misleading and this approach was chosen for performance reasons only.
Identify comments that are shebangs
Description
Shebangs should be preserved and no space should be inserted between
#
and !
. A comment is a shebang if it is the first top-level token
(identified with pos_id
) and if it starts with #!
.
Usage
is_shebang(pd)
Arguments
pd |
A parse table. |
Examples
style_text("#!/usr/bin/env Rscript")
Establish testing setup for current environment
Description
Establish testing setup for current environment
Usage
local_test_setup(cache = FALSE, .local_envir = parent.frame())
Arguments
cache |
Whether or not to create and activate a cache in a temporary directory. |
.local_envir |
The environment to use for scoping. |
Details
make styler quiet.
Lookup which new tokens were created from "SPECIAL"
Description
Lookup which new tokens were created from "SPECIAL"
Usage
lookup_new_special(regex = NA)
Arguments
regex |
A regular expression pattern to search for. |
Lookup all tokens that have a unique token-text mapping
Description
Lookup all tokens that have a unique token-text mapping
Usage
lookup_tokens()
Closure to return a transformer function
Description
This function takes a list of transformer functions as input and returns a function that can be applied to character strings that should be transformed.
Usage
make_transformer(
transformers,
include_roxygen_examples,
base_indention,
warn_empty = TRUE
)
Arguments
transformers |
A list of transformer functions that operate on flat parse tables. |
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
warn_empty |
Whether or not a warning should be displayed when |
Map the file type to a corresponding regular expression
Description
Map the file type to a corresponding regular expression
Usage
map_filetype_to_pattern(filetype)
Arguments
filetype |
The file type to map to a regex. |
Examples
styler:::map_filetype_to_pattern(c(".rMd", "R"))
Match a stop candidate to a start
Description
Match a stop candidate to a start
Usage
match_stop_to_start(start, stop_candidates)
Arguments
start |
An integer. |
stop_candidates |
Potential stop candidates. |
Examples
styler:::match_stop_to_start(1, c(3, 4, 5))
Specify spacing around math tokens
Description
Helper function to create the input for the argument math_token_spacing
in
tidyverse_style()
.
Usage
specify_math_token_spacing(zero = "'^'", one = c("'+'", "'-'", "'*'", "'/'"))
tidyverse_math_token_spacing()
Arguments
zero |
Character vector of tokens that should be surrounded with zero spaces. |
one |
Character vector with tokens that should be surrounded by at
least one space (depending on |
Functions
-
specify_math_token_spacing()
: Allows to fully specify the math token spacing. -
tidyverse_math_token_spacing()
: Simple forwarder tospecify_math_token_spacing
with spacing around math tokens according to the tidyverse style guide.
Examples
style_text(
"1+1 -3",
math_token_spacing = specify_math_token_spacing(zero = "'+'"),
strict = FALSE
)
style_text(
"1+1 -3",
math_token_spacing = specify_math_token_spacing(zero = "'+'"),
strict = TRUE
)
style_text(
"1+1 -3",
math_token_spacing = tidyverse_math_token_spacing(),
strict = FALSE
)
style_text(
"1+1 -3",
math_token_spacing = tidyverse_math_token_spacing(),
strict = TRUE
)
Times two function calls with temporarily enabled cache
Description
This can be helpful for benchmarking.
Usage
n_times_faster_with_cache(
x1,
x2 = x1,
...,
fun = styler::style_text,
n = 3L,
clear = "always"
)
Arguments
... |
Arguments passed to |
fun |
The function that should be timed. |
n |
The number of times the experiment should be repeated. |
Value
A scalar indicating the relative difference of the second compared to the first run.
Check whether indention is needed
Description
Checks for each potential trigger token in pd
whether it actually should
cause indention.
Usage
needs_indention(pd, potential_triggers_pos, other_trigger_tokens = NULL)
Arguments
pd |
A parse table. |
potential_triggers_pos |
A vector with indices of the potential trigger
tokens in |
other_trigger_tokens |
Other tokens that are going to cause indention
if on the same line as the token corresponding to |
Check whether indention is needed
Description
Determine whether the tokens corresponding to potential_trigger_pos
should
cause indention, considering that there might be other potential triggers
other_trigger_tokens
that are going to cause indention.
Indention is needed if the two conditions apply:
Usage
needs_indention_one(pd, potential_trigger_pos, other_trigger_tokens)
Arguments
pd |
A parse table. |
potential_trigger_pos |
the index of the token in the parse table for which it should be checked whether it should trigger indention. |
other_trigger_tokens |
Other tokens that are going to cause indention
if on the same line as the token corresponding to |
Details
there is no multi-line token between the trigger and the first line break.
there is no other token between the potential trigger and the first line break that is going to cause indention. Note that such an other trigger only causes indention if there is a line break after that other triggering token, not otherwise. If it causes indention, it is said to be an active trigger, if it does not, it is called an inactive trigger. See 'Details' for an example where there is an other trigger token, but since the next token is on the same line as the other trigger, the trigger is passive.
Value
Returns TRUE
if indention is needed, FALSE
otherwise.
TRUE
if indention is needed, FALSE
otherwise.
Examples
style_text(c(
"call(named = c,",
"named = b)"
), strict = FALSE)
Check if rd emulation is required with roxygen2::roc_proc_text()
Description
Check if rd emulation is required with roxygen2::roc_proc_text()
Usage
needs_rd_emulation(roxygen)
Nest a flat parse table
Description
nest_parse_data
groups pd_flat
into a parse table with tokens that are
a parent to other tokens (called internal) and such that are not (called
child). Then, the token in child are joined to their parents in internal
and all token information of the children is nested into a column "child".
This is done recursively until we are only left with a nested data frame that
contains one row: The nested parse table.
Usage
nest_parse_data(pd_flat)
Arguments
pd_flat |
A flat parse table including both terminals and non-terminals. |
Value
A nested parse table.
See Also
Find the index of the next or previous non-comment in a parse table.
Description
Find the index of the next or previous non-comment in a parse table.
Usage
next_non_comment(pd, pos)
previous_non_comment(pd, pos)
Arguments
pd |
A parse table. |
pos |
The position of the token to start the search from. |
See Also
Other third-party style guide helpers:
pd_is
,
scope_normalize()
Examples
code <- "a <- # hi \n x %>% b()"
writeLines(code)
pd <- compute_parse_data_nested(code)
child <- pd$child[[1]]
previous_non_comment(child, 4L)
next_non_comment(child, 2L)
Tell me what the next terminal is
Description
If the first is a terminal, return it. If not, go inside it and search the next terminal
Usage
next_terminal(
pd,
stack = FALSE,
vars = c("pos_id", "token", "text"),
tokens_exclude = NULL
)
Arguments
pd |
A nest. |
stack |
Whether or not to also return information on the tokens that
are between |
vars |
The variables to return. |
tokens_exclude |
A vector with tokens to exclude. This can be helpful if one wants to find the next token that is not a comment for example. |
Value
Returns a data frame (which is not a valid parse table for
stack = TRUE
), with vars
and another variable position
that denotes
the index each element in the transition. This can be helpful in conjunction
with purrr::pluck()
or purrr::modify_in()
to reach the terminal in the
nested structure.
Examples
withr::with_options(
list(styler.cache_name = NULL), # temporarily deactivate cache
{
pd <- compute_parse_data_nested("if (TRUE) f()")
styler:::next_terminal(pd)
}
)
Get the value of an option
Description
Basically a getOptions()
that fails fast by default.
Usage
option_read(x, default = NULL, error_if_not_found = TRUE)
Arguments
x |
a character string holding an option name. |
default |
if the specified option is not set in the options list, this value is returned. This facilitates retrieving an option and checking whether it is set and setting it separately if not. |
error_if_not_found |
Whether or not an error should be returned if the option was not set. |
Parse roxygen comments into text
Description
Used to parse roxygen code examples. Removes line break before
\\dontrun{...}
and friends because it does not occur for segments other
than \\dont{...}
and friends.
Usage
parse_roxygen(roxygen)
Arguments
roxygen |
Roxygen comments. |
Examples
styler:::parse_roxygen(c(
"#' @examples",
"#' 1+ 1"
))
styler:::parse_roxygen(c(
"#' @examples 33",
"#'1+ 1"
))
Save parsing from text
Description
Parses text safely, i.e. throws an informative error if EOL style does not match LF or indicates the exact position where the parsing failed. Note that we can only detect wrong EOL style if it occurs on the first line already.
Usage
parse_safely(text, ...)
Arguments
text |
Text to parse. |
... |
Parameters passed to |
Examples
try(styler:::parse_safely("a + 3 -4 -> x\r\n glück + 1"))
# This cannot be detected as a EOL style problem because the first
# line ends as expected with \n
try(styler:::parse_safely("a + 3 -4 -> x\nx + 2\r\n glück + 1"))
styler:::parse_safely("a + 3 -4 -> \n glück + 1")
Parse, transform and serialize text
Description
Wrapper function for the common three operations.
Usage
parse_transform_serialize_r(
text,
transformers,
base_indention,
warn_empty = TRUE,
is_roxygen_code_example = FALSE
)
Arguments
text |
The text to parse. |
transformers |
Passed to |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
warn_empty |
Whether or not a warning should be displayed when |
is_roxygen_code_example |
Is code a roxygen examples block? |
See Also
parse_transform_serialize_roxygen()
Parse, transform and serialize a nested parse table
Description
We process blocks of nested parse tables for speed. See cache_find_block()
for details on how a top-level nest is split into blocks.
Usage
parse_transform_serialize_r_block(
pd_nested,
start_line,
transformers,
base_indention
)
Arguments
pd_nested |
A block of the nested parse table. |
start_line |
The line number on which the code starts. |
transformers |
A list of named transformer functions |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
Examples
text_in <- 'x<- function()
"here
is"
NULL
1+ 1
'
style_text(text_in, base_indention = 3)
# not equal to the naive approach
styler:::construct_vertical(
paste0(styler:::add_spaces(3), style_text(text_in), sep = "")
)
Parse, transform and serialize roxygen comments
Description
Splits text
into roxygen code examples and non-roxygen code examples and
then maps over these examples by applying
style_roxygen_code_example()
.
Usage
parse_transform_serialize_roxygen(text, transformers, base_indention)
Hierarchy
Styling involves splitting roxygen example code into segments, and segments
into snippets. This describes the process for input of
parse_transform_serialize_roxygen()
:
Splitting code into roxygen example code and other code. Downstream, we are only concerned about roxygen code. See
parse_transform_serialize_roxygen()
.Every roxygen example code can have zero or more dontrun / dontshow / donttest sequences. We next create segments of roxygen code examples that contain at most one of these. See
style_roxygen_code_example()
.We further split the segment that contains at most one dont* sequence into snippets that are either don* or not. See
style_roxygen_code_example_segment()
.
Finally, that we have roxygen code snippets that are either dont* or not,
we style them in style_roxygen_example_snippet()
using
parse_transform_serialize_r()
.
Check whether a round trip verification can be carried out
Description
If scope was set to "line_breaks" or lower (compare tidyverse_style()
),
we can compare the expression before and after styling and return an error if
it is not the same.
Usage
parse_tree_must_be_identical(transformers)
Arguments
transformers |
The list of transformer functions used for styling. Needed for reverse engineering the scope. |
Work with parser versions
Description
The structure of the parse data affects many operations in styler. There was
unexpected behavior of the parser that styler was initially designed to work
around. Examples are #187,
#216,
#100 and others. With
#419, the structure of the
parse data changes and we need to dispatch for older versions. As it is
inconvenient to pass a parser version down in the call stack in various
places, the environment env_current
is used to store the current version
globally but internally.
Usage
parser_version_set(version)
parser_version_get()
parser_version_find(pd)
Arguments
version |
The version of the parser to be used. |
pd |
A parse table such as the output from
|
Details
We version the parser as follows:
version 1: Before fix mentioned in #419. R < 3.6
version 2: After #419. R >= 3.6
version 3: After #582. R >= 4.0
The following utilities are available:
-
parser_version_set()
sets the parser version in the environmentenv_current
. -
parser_version_get()
retrieves the parser version from the environmentenv_current
. -
parser_version_find()
determines the version of the parser from parse data. This does not necessarily mean that the version found is the actual version, but it behaves like it. For example, code that does not containEQ_ASSIGN
is parsed the same way with version 1 and 2. If the behavior is identical, the version is set to 1.
What is a parse table representing?
Description
Check whether a parse table corresponds to a certain expression.
Usage
is_curly_expr(pd)
is_for_expr(pd)
is_conditional_expr(pd)
is_while_expr(pd)
is_function_call(pd)
is_function_declaration(pd)
is_comment(pd)
is_tilde_expr(pd, tilde_pos = c(1L, 2L))
is_asymmetric_tilde_expr(pd)
is_symmetric_tilde_expr(pd)
Arguments
pd |
A parse table. |
tilde_pos |
Integer vector indicating row-indices that should be checked for tilde. See 'Details'. |
Details
A tilde is on the top row in the parse table if it is an asymmetric tilde
expression (like ~column
), in the second row if it is a symmetric tilde
expression (like a~b
).
Functions
-
is_curly_expr()
: Checks whetherpd
contains an expression wrapped in curly brackets. -
is_for_expr()
: Checks whetherpd
contains afor
loop. -
is_conditional_expr()
: Checks whetherpd
contains is a conditional expression. -
is_while_expr()
: Checks whetherpd
contains awhile
loop. -
is_function_call()
: Checks whetherpd
is a function call. -
is_function_declaration()
: Checks whetherpd
is a function declaration. -
is_comment()
: Checks for every token whether or not it is a comment. -
is_tilde_expr()
: Checks whetherpd
contains a tilde. -
is_asymmetric_tilde_expr()
: Ifpd
contains a tilde, checks whether it is asymmetrical. -
is_symmetric_tilde_expr()
: Ifpd
contains a tilde, checks whether it is symmetrical.
See Also
Other third-party style guide helpers:
next_non_comment()
,
scope_normalize()
Examples
code <- "if (TRUE) { 1 }"
pd <- compute_parse_data_nested(code)
is_curly_expr(pd)
child_of_child <- pd$child[[1]]$child[[5]]
is_curly_expr(child_of_child)
code <- "for (i in 1:5) print(1:i)"
pd <- compute_parse_data_nested(code)
is_for_expr(pd)
is_for_expr(pd$child[[1]])
code <- "if (TRUE) x <- 1 else x <- 0"
pd <- compute_parse_data_nested(code)
is_conditional_expr(pd)
is_conditional_expr(pd$child[[1]])
code <- "x <- list(1:3)"
pd <- compute_parse_data_nested(code)
is_function_call(pd)
child_of_child <- pd$child[[1]]$child[[3]]
is_function_call(child_of_child)
code <- "foo <- function() NULL"
pd <- compute_parse_data_nested(code)
is_function_declaration(pd)
child_of_child <- pd$child[[1]]$child[[3]]
is_function_declaration(child_of_child)
code <- "x <- 1 # TODO: check value"
pd <- compute_parse_data_nested(code)
is_comment(pd)
code <- "lm(wt ~ mpg, mtcars)"
pd <- compute_parse_data_nested(code)
is_tilde_expr(pd$child[[1]]$child[[3]])
is_symmetric_tilde_expr(pd$child[[1]]$child[[3]])
is_asymmetric_tilde_expr(pd$child[[1]]$child[[3]])
Check whether a parse table is a multi-line token
Description
A token is a multi-line expression if and only if:
Usage
pd_is_multi_line(pd)
Arguments
pd |
A parse table. |
Details
it contains a line break.
it has at least one child that is a multi-line expression itself.
Changing the line definition
Description
Input: New line denoted with \\n
. Lines can span across elements.
Output: Each element in the vector is one line.
Usage
post_parse_roxygen(raw)
Arguments
raw |
Raw code to post-process. |
Prettify R code in current working directory
Description
This is a helper function for style_dir.
Usage
prettify_any(
transformers,
filetype,
recursive,
exclude_files,
exclude_dirs,
include_roxygen_examples,
base_indention = 0L,
dry
)
Arguments
transformers |
A set of transformer functions. This argument is most
conveniently constructed via the |
filetype |
Vector of file extensions indicating which file types should
be styled. Case is ignored, and the |
recursive |
A logical value indicating whether or not files in subdirectories should be styled as well. |
exclude_files |
Character vector with regular expressions to files that should be excluded from styling. |
exclude_dirs |
Character vector with directories to exclude
(recursively). Note that the default values were set for consistency with
|
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Prettify a package
Description
Prettify a package
Usage
prettify_pkg(
transformers,
filetype,
exclude_files,
exclude_dirs,
include_roxygen_examples,
base_indention,
dry
)
Arguments
transformers |
A list of transformer functions that operate on flat parse tables. |
filetype |
Vector of file extensions indicating which file types should
be styled. Case is ignored, and the |
exclude_files |
Character vector with regular expressions to files that should be excluded from styling. |
exclude_dirs |
Character vector with directories to exclude
(recursively). Note that the default values were set for consistency with
|
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Print styled code
Description
Print styled code
Usage
## S3 method for class 'vertical'
print(
x,
...,
colored = getOption("styler.colored_print.vertical"),
style = prettycode::default_style()
)
Arguments
x |
A character vector, one element corresponds to one line of code. |
... |
Not currently used. |
colored |
Whether or not the output should be colored with
|
style |
Passed to |
Read UTF-8
Description
Reads an UTF-8 file, returning the content and whether or not the final line was blank. This information is required higher up in the call stack because we should write back if contents changed or if there is no blank line at the EOF. A perfectly styled file with no EOF blank line will gain such a line with this implementation.
Usage
read_utf8(path)
Arguments
path |
A path to a file to read. |
Drop-in replacement for xfun::read_utf8()
, with an optional warn
argument.
Description
Drop-in replacement for xfun::read_utf8()
, with an optional warn
argument.
Usage
read_utf8_bare(con, warn = TRUE)
Specify what is re-indented how
Description
This function returns a list that can be used as an input for the argument
reindention
of the function tidyverse_style()
. It features sensible
defaults, so the user can specify deviations from them conveniently without
the need of setting all arguments explicitly.
Usage
specify_reindention(regex_pattern = NULL, indention = 0L, comments_only = TRUE)
tidyverse_reindention()
Arguments
regex_pattern |
Character vector with regular expression patterns that
are to be re-indented with spaces, |
indention |
The indention tokens should have if they match
|
comments_only |
Whether the |
Functions
-
specify_reindention()
: Allows to specify which tokens are reindented and how. -
tidyverse_reindention()
: Simple forwarder tospecify_reindention
with reindention according to the tidyverse style guide.
Examples
style_text("a <- xyz", reindention = specify_reindention(
regex_pattern = "xyz", indention = 4, comments_only = FALSE
))
style_text("a <- xyz", reindention = tidyverse_reindention())
Remove dont* mask
Description
Remove dont* mask
Usage
remove_dont_mask(roxygen)
Arguments
roxygen |
Roxygen code examples that contains a dont* segment only. |
Remove roxygen header
Description
Can't simply remove the element with the regex because it may happen that the roxygen tag is on the same line as its contents start.
Usage
remove_roxygen_header(text)
Examples
#' @examples c(1, 2)
Repeat elements of a character vector times
times and collapse it
Description
Repeat elements of a character vector times
times and collapse it
Usage
rep_char(char, times)
Arguments
char |
A character vector. |
times |
an integer giving the number of repetitions. |
Value
A character vector.
Fix tools::parse_Rd()
output
Description
Since tools::parse_Rd()
treats braces in quotes as literal braces when
determining brace symmetry, a brace might be added in error to the parsed
data (at the end). We'll remove one at the time, check if output is parsable
until no braces are left. If we end up with no braces left, we signal a
parsing error, otherwise, we return the initial (not parsable input due to
dont sequence) with the trailing braces removed.
Usage
roxygen_remove_extra_brace(parsed)
Examples
styler:::parse_roxygen(
c(
"#' @examples",
"#' x <- '{'",
"#' \\dontrun{",
"#' fu(x = 3)",
"#' }"
)
)
styler:::parse_roxygen(
c(
"#' @examples",
"#' x <- '{'",
"#' \\dontrun{",
"#' c('{', \"'{{{\" ,\"[\")",
"#' }"
)
)
Heuristic to see if a file styled with the addin should be saved or not.
Description
Using the R option "styler.save_after_styling"
and if unset, checks legacy
method via environment variable save_after_styling
.
Usage
save_after_styling_is_active()
Convert the styling scope to its lower-level representation
Description
If scope
is of class character
and of length one, the value of the
argument and all less-invasive levels are included too (e.g.
styling tokens includes styling spaces). If
scope
is of class AsIs
, every level to be included has to be declared
individually. See compare tidyverse_style()
for the possible levels and
their order.
Usage
scope_normalize(scope, name = substitute(scope))
Arguments
scope |
A character vector of length one or a vector of class |
name |
The name of the character vector to be displayed if the construction of the factor fails. |
See Also
Other third-party style guide helpers:
next_non_comment()
,
pd_is
Examples
scope_normalize(I("tokens"))
scope_normalize(I(c("indention", "tokens")))
Separate chunks within Rmd and Rnw contents
Description
Identifies and separates the code and text chunks (the latter includes non-R code) within an Rmd or Rnw file, and returns these separately.
Usage
separate_chunks(lines, filetype)
Arguments
lines |
A character vector of lines from an Rmd or Rnw file. |
filetype |
A string indicating the filetype - either 'Rmd' or 'Rnw'. |
Serialize flattened parse data
Description
Collapses a flattened parse table into character vector representation.
Usage
serialize_parse_data_flattened(flattened_pd, indent_character = "")
Arguments
flattened_pd |
A flattened parse table. |
indent_character |
The character that is used for indention. We strongly advise for using spaces as indention characters. |
Set the file type argument
Description
Sets and asserts the file type argument to a standard format for further internal processing.
Usage
set_and_assert_arg_filetype(filetype)
Arguments
filetype |
A character vector with file types to convert to the internal standard format. |
Examples
styler:::set_and_assert_arg_filetype("rMd")
try(styler:::set_and_assert_arg_filetype("xyz"))
Standardize paths in root
Description
Standardization required to use setdiff()
with paths.
Usage
set_arg_paths(path)
Arguments
path |
A path. |
See Also
dir_without_.
Examples
styler:::set_arg_paths(c("./file.R", "file.R", "../another-file.R"))
Set the write_tree argument
Description
Sets the argument write_tree
in test_collection()
to be TRUE
for R
versions higher or equal to 3.2, and FALSE
otherwise since the second-level
dependency DiagrammeR
from data.tree
is not available for R < 3.2.
Usage
set_arg_write_tree(write_tree)
Arguments
write_tree |
Whether or not to write tree. |
Sets line break after opening parenthesis
Description
Sets line break after opening parenthesis
Usage
set_line_break_after_opening_if_call_is_multi_line(
pd,
except_token_after = NULL,
except_text_before = NULL,
force_text_before = NULL
)
Arguments
pd |
The parse table. |
except_token_after |
The tokens after the token that cause an exception. |
except_text_before |
A character vector with text before a token that does not cause a line break. |
force_text_before |
A character vector with text before "'('" that forces a line break after every argument in the call. |
Details
In general, every call that is multi-line has a line break after the opening parenthesis. Exceptions:
The token right after the parenthesis is a comment, then, the line should be broken after the comment only. Governed by
except_token_after
.The name of the function called is
ifelse()
or similar, where we can allow the condition on the same line as the function name, and we don't impose rules on the line breaks for the subsequent arguments. Governed byexcept_text_before
.Some calls like
switch()
statements are always forced to become multi- line. Governed byforce_text_before
.
Styling around \{\{
Description
With {rlang} version 0.4, a new syntactic sugar is introduced, the
curly-curly operator. It interprets this code in a special way:
call(\{\{ x \}\})
. See this
blog post
on the topic. Here, the curly-curly sugar is understood as two opening
curly braces, followed by an expression followed by two closing curly braces,
e.g. \{\{1\}\}
. \{\{1\} + 1\}
does not contain the curly-curly syntactic
sugar according to the above definition. On the other hand \{\{ x + y \}\}
is recognized by styler as containing it (and is parsable code)
but will most likely give an error at runtime because the way the syntactic
sugar is defined in rlang is to use a single token within curly-curly. In
addition, because rlang parses \{\{
in a special way (just as !!
), the
expression \{\{ x \}\}
will give a runtime error when used outside of a
context that is capable of handling it, e.g. on the top-level (that is, not
within function call like rlang_fun(\{\{ x \}\})
) or within a base R
function such as c()
. However, these differences are assumed to be
irrelevant for styling curly-curly, as much as they were for styling !!
.
curly-curly affects styling of line break and spaces, namely:
Usage
set_line_break_around_curly_curly(pd)
set_space_in_curly_curly(pd)
Arguments
pd |
A parse table. |
Details
No line break after first or second
\{
, before third and fourth\{
.No space after first and third
\{
, one space after second and before third\}
.No line breaks within curly-curly, e.g.
\{\{ x \}\}
can only contain line breaks after the last brace or before the first brace. But these are not dependent on curly-curly specifically.
See Also
style_text_without_curly_curly
Set line break before a curly brace
Description
Rule:
Principle: Function arguments that consist of a braced expression always need to start on a new line
Exception: ... unless it's the last argument and all other arguments fit on the line of the function call
Exception: ... or they are named.
Extension: Also, expressions following on braced expressions also cause a line trigger.
Usage
set_line_break_before_curly_opening(pd)
Examples
tryCatch(
{
f(8)
},
error = function(e) NULL
)
# last-argument case
testthat("braces braces are cool", {
code(to = execute)
})
call2(
x = 2, {
code(to = execute)
},
c = {
# this is the named case
g(x = 7)
}
)
tryGugus(
{
g5(k = na)
},
a + b # line break also here because
# preceded by brace expression
)
# brace expressions go on new line if part of a pipe, in function call...
c(
data %>%
filter(bar) %>%
{
cor(.$col1, .$col2, use = "complete.obs")
}
)
# ... or outside
data %>%
filter(bar) %>%
{
cor(.$col1, .$col2, use = "complete.obs")
}
Set line break for multi-line function calls
Description
Set line break for multi-line function calls
Usage
set_line_break_before_closing_call(pd, except_token_before)
remove_line_break_in_fun_call(pd, strict)
Arguments
pd |
A parse table. |
except_token_before |
A character vector with tokens that do not cause a line break after them. |
Functions
-
set_line_break_before_closing_call()
: Sets line break before closing parenthesis. -
remove_line_break_in_fun_call()
: Remove line breaks in function calls.
Set the multi-line column
Description
Sets the column multi_line
in pd
by checking row-wise whether any child
of a token is a multi-line token.
Usage
set_multi_line(pd)
Arguments
pd |
A parse table. |
Set indention of tokens that match regex
Description
Force the level of indention of tokens whose text matches a regular expression pattern to be a certain amount of spaces. The rule is only active for the first tokens on a line.
Usage
set_regex_indention(
flattened_pd,
pattern,
target_indention = 0L,
comments_only = TRUE
)
Arguments
flattened_pd |
A flattened parse table. |
pattern |
A character with regular expressions to match against the
token in |
target_indention |
The desired level of indention of the tokens that
match |
comments_only |
Boolean indicating whether only comments should be checked or all tokens. |
Value
A flattened parse table with indention set to target_indention
for
the tokens that match regex.
Set spaces around operators
Description
Alignment is kept, if detected.
Usage
set_space_around_op(pd_flat, strict)
Set space between EQ_SUB
and "','"
Description
Set space between EQ_SUB
and "','"
Usage
set_space_between_eq_sub_and_comma(pd)
Arguments
pd |
A parse table. |
Set space between levels of nesting
Description
With the nested approach, certain rules do not have an effect anymore because of the nature of the nested structure. Setting spacing before curly brackets in for / if / while statements and function declarations will be such a case since a curly bracket is always at the first position in a parse table, so spacing cannot be set after the previous token.
Usage
set_space_between_levels(pd_flat)
Arguments
pd_flat |
A flat parse table. |
Helper for setting spaces
Description
Helper for setting spaces
Usage
set_spaces(spaces_after_prefix, force_one)
Arguments
spaces_after_prefix |
An integer vector with the number of spaces after the prefix. |
force_one |
Whether spaces_after_prefix should be set to one in all cases. |
Value
An integer vector of length spaces_after_prefix, which is either
one (if force_one = TRUE
) or space_after_prefix
with all values
below one set to one.
Numeric vector indicating the number of spaces.
Asks the user to supply a style
Description
Asks the user to supply a style
Usage
set_style_transformers()
Unindent a child if necessary
Description
check whether any of the children of pd
has token
on the same line as the
closing token
of pd. If so, unindent that token.
Usage
set_unindention_child(pd, token = "')'", unindent_by)
Arguments
pd |
A parse table. |
token |
The token the unindention should be based on. |
unindent_by |
By how many spaces one level of indention is reversed. |
Shallowify the parse table
Description
Cached expressions don't need to be transformed with transformers
in
parse_transform_serialize_r_block()
, we simply return text
for the
top-level token.
Usage
shallowify(pd)
Details
Expressions that are cached are already styled correctly. We can make the
parse table shallow at these locations, fully relying on the text
column:
remove all children, as they are not needed anymore.
mark the expression as a terminal.
Top-level comments
Note that we do not cache top-level comments. Because package code has a lot
of roxygen comments and each of them is a top-level expression, checking is
very expensive. More expensive than styling, because comments are always
terminals. This will also yield large speed improvements in
compute_parse_data_nested()
because nesting is expensive and will not be
done for cached expressions.
Implementation
Because the structure of the parse table is not always "top-level expression first, then children", this function creates a temporary parse table that has this property and then extract the ids and subset the original parse table so it is shallow in the right places.
Specify which tokens must be absent for a transformer to be dropped
Description
{styler}
can remove transformer functions safely removed from the list of
transformers to be applied on every nest with transformers_drop()
if the
tokens that trigger a manipulation of the parse data are absent in the text
to style. specify_transformers_drop()
helps you specify these
conditions.
Usage
specify_transformers_drop(
spaces = NULL,
indention = NULL,
line_breaks = NULL,
tokens = NULL
)
Arguments
spaces , indention , line_breaks , tokens |
Each a list (or |
Details
Note that the negative formulation (must be absent in order to be dropped) means that when you add a new rule and you forget to add a rule for when to drop it, it will not be dropped. If we required to specify the complement (which tokens must be present for the transformer to be kept), the transformer would be silently removed, which is less save.
Warning
It is the responsibility of the developer to ensure expected behavior, in particular that:
the name of the supplied dropping criteria matches the name of the transformer function.
the dropping criteria (name + token) reflects correctly under which circumstances the transformer does not have an impact on styling and can therefore be safely removed without affecting the styling outcome.
You can use the unexported function test_transformers_drop()
for some
checks.
Examples
dropping <- specify_transformers_drop(
spaces = c(remove_space_after_excl = "'!'")
)
style_guide <- create_style_guide(
space = list(remove_space_after_excl = styler:::remove_space_after_excl),
transformers_drop = dropping
)
# transformers_drop() will remove the transformer when the code does not
# contain an exclamation mark
style_guide_with_some_transformers_dropped <- styler:::transformers_drop(
"x <- 3;2", style_guide
)
setdiff(
names(style_guide$space),
names(style_guide_with_some_transformers_dropped)
)
# note that dropping all transformers of a scope means that this scope
# has an empty named list for this scope
style_guide_with_some_transformers_dropped$space
# this is not the same as if this scope was never specified.
tidyverse_style(scope = "none")$space
# Hence, styler should check for length 0 to decide if a scope is present or
# not, not via `is.null()` and we can use the `is.null()` check to see if
# this scope was initially required by the user.
Split text into roxygen and non-roxygen example segments
Description
Split text into roxygen and non-roxygen example segments
Usage
split_roxygen_segments(text, roxygen_examples)
Arguments
text |
Roxygen comments |
roxygen_examples |
Integer sequence that indicates which lines in |
Value
A list with two elements:
A list that contains elements grouped into roxygen and non-roxygen sections. This list is named
separated
.An integer vector with the indices that correspond to roxygen code examples in
separated
.
Start comments with a space
Description
Forces comments to start with a space, that is, after the regular expression
#+['\\*]
, at least one space must follow if the comment is non-empty, i.e
there is not just spaces within the comment. Multiple spaces may be legit for
indention in some situations.
Usage
start_comments_with_space(pd, force_one = FALSE)
Arguments
pd |
A parse table. |
force_one |
Whether or not to force one space or allow multiple spaces. |
Exceptions
Spaces won't be added to comments when they are:
shebangs
code chunk headers
xaringan markers
Wrapper around style_pkg()
for access via Addin.
Description
Wrapper around style_pkg()
for access via Addin.
Usage
style_active_pkg()
Prettify arbitrary R code
Description
Performs various substitutions in all .R
, .Rmd
, .Rmarkdown
, qmd
and/or .Rnw
files in a directory (by default only .R
files are styled -
see filetype
argument).
Carefully examine the results after running this function!
Usage
style_dir(
path = ".",
...,
style = tidyverse_style,
transformers = style(...),
filetype = c("R", "Rprofile", "Rmd", "Rmarkdown", "Rnw", "Qmd"),
recursive = TRUE,
exclude_files = NULL,
exclude_dirs = c("packrat", "renv"),
include_roxygen_examples = TRUE,
base_indention = 0L,
dry = "off"
)
Arguments
path |
Path to a directory with files to transform. |
... |
Arguments passed on to the |
style |
A function that creates a style guide to use, by default
|
transformers |
A set of transformer functions. This argument is most
conveniently constructed via the |
filetype |
Vector of file extensions indicating which file types should
be styled. Case is ignored, and the |
recursive |
A logical value indicating whether or not files in
sub directories of |
exclude_files |
Character vector with regular expressions to files that should be excluded from styling. |
exclude_dirs |
Character vector with directories to exclude (recursively). |
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Value
Invisibly returns a data frame that indicates for each file considered for
styling whether or not it was actually changed (or would be changed when
dry
is not "off").
Warning
This function overwrites files (if styling results in a change of the
code to be formatted and dry = "off"
). It is strongly suggested to only
style files that are under version control or to create a backup copy.
We suggest to first style with scope < "tokens"
and inspect and commit
changes, because these changes are guaranteed to leave the abstract syntax
tree (AST) unchanged. See section 'Round trip validation' for details.
Then, we suggest to style with scope = "tokens"
(if desired) and carefully
inspect the changes to make sure the AST is not changed in an unexpected way
that invalidates code.
Round trip validation
The following section describes when and how styling is guaranteed to yield correct code.
If tokens are not in the styling scope (as specified with the scope
argument), no tokens are changed and the abstract syntax tree (AST) should
not change.
Hence, it is possible to validate the styling by comparing whether the parsed
expression before and after styling have the same AST.
This comparison omits roxygen code examples and comments. styler throws an
error if the AST has changed through styling.
Note that if tokens are to be styled, such a comparison is not conducted because the AST might well change and such a change is intended. There is no way styler can validate styling, that is why we inform the user to carefully inspect the changes.
See section 'Warning' for a good strategy to apply styling safely.
See Also
Other stylers:
style_file()
,
style_pkg()
,
style_text()
,
styler_addins
Examples
style_dir("path/to/dir", filetype = c("rmd", ".R"))
# the following is identical (because of ... and defaults)
# but the first is most convenient:
style_dir(strict = TRUE)
style_dir(style = tidyverse_style, strict = TRUE)
style_dir(transformers = tidyverse_style(strict = TRUE))
Style files with R source code
Description
Performs various substitutions in the files specified. Carefully examine the results after running this function!
Usage
style_file(
path,
...,
style = tidyverse_style,
transformers = style(...),
include_roxygen_examples = TRUE,
base_indention = 0L,
dry = "off"
)
Arguments
path |
A character vector with paths to files to style. Supported
extensions: |
... |
Arguments passed on to the |
style |
A function that creates a style guide to use, by default
|
transformers |
A set of transformer functions. This argument is most
conveniently constructed via the |
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Encoding
UTF-8 encoding is assumed. Please convert your code to UTF-8 if necessary before applying styler.
Value
Invisibly returns a data frame that indicates for each file considered for
styling whether or not it was actually changed (or would be changed when
dry
is not "off").
Warning
This function overwrites files (if styling results in a change of the
code to be formatted and dry = "off"
). It is strongly suggested to only
style files that are under version control or to create a backup copy.
We suggest to first style with scope < "tokens"
and inspect and commit
changes, because these changes are guaranteed to leave the abstract syntax
tree (AST) unchanged. See section 'Round trip validation' for details.
Then, we suggest to style with scope = "tokens"
(if desired) and carefully
inspect the changes to make sure the AST is not changed in an unexpected way
that invalidates code.
Round trip validation
The following section describes when and how styling is guaranteed to yield correct code.
If tokens are not in the styling scope (as specified with the scope
argument), no tokens are changed and the abstract syntax tree (AST) should
not change.
Hence, it is possible to validate the styling by comparing whether the parsed
expression before and after styling have the same AST.
This comparison omits roxygen code examples and comments. styler throws an
error if the AST has changed through styling.
Note that if tokens are to be styled, such a comparison is not conducted because the AST might well change and such a change is intended. There is no way styler can validate styling, that is why we inform the user to carefully inspect the changes.
See section 'Warning' for a good strategy to apply styling safely.
See Also
Other stylers:
style_dir()
,
style_pkg()
,
style_text()
,
styler_addins
Examples
file <- tempfile("styler", fileext = ".R")
writeLines("1++1", file)
# the following is identical (because of ... and defaults),
# but the first is most convenient:
style_file(file, strict = TRUE)
style_file(file, style = tidyverse_style, strict = TRUE)
style_file(file, transformers = tidyverse_style(strict = TRUE))
# only style indention and less invasive levels (i.e. spaces)
style_file(file, scope = "indention", strict = TRUE)
# name levels explicitly to not style less invasive levels
style_file(file, scope = I(c("tokens", "spaces")), strict = TRUE)
readLines(file)
unlink(file)
Style guides
Description
Format code according to a style guide. Style guides are the input to the
argument style
in style_file()
and friends.
The available style guides are:
the tidyverse style guide (see
tidyverse_style()
).
Prettify R source code
Description
Performs various substitutions in all .R
files in a package
(code and tests), .Rmd
, .Rmarkdown
and/or
.qmd
, .Rnw
files (vignettes and readme).
Carefully examine the results after running this function!
Usage
style_pkg(
pkg = ".",
...,
style = tidyverse_style,
transformers = style(...),
filetype = c("R", "Rprofile", "Rmd", "Rmarkdown", "Rnw", "qmd"),
exclude_files = c("R/RcppExports\\.R", "R/cpp11\\.R",
"R/import-standalone.*\\.R"),
exclude_dirs = c("packrat", "renv"),
include_roxygen_examples = TRUE,
base_indention = 0L,
dry = "off"
)
Arguments
pkg |
Path to a (subdirectory of an) R package. |
... |
Arguments passed on to the |
style |
A function that creates a style guide to use, by default
|
transformers |
A set of transformer functions. This argument is most
conveniently constructed via the |
filetype |
Vector of file extensions indicating which file types should
be styled. Case is ignored, and the |
exclude_files |
Character vector with regular expressions to files that should be excluded from styling. |
exclude_dirs |
Character vector with directories to exclude
(recursively). Note that the default values were set for consistency with
|
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Warning
This function overwrites files (if styling results in a change of the
code to be formatted and dry = "off"
). It is strongly suggested to only
style files that are under version control or to create a backup copy.
We suggest to first style with scope < "tokens"
and inspect and commit
changes, because these changes are guaranteed to leave the abstract syntax
tree (AST) unchanged. See section 'Round trip validation' for details.
Then, we suggest to style with scope = "tokens"
(if desired) and carefully
inspect the changes to make sure the AST is not changed in an unexpected way
that invalidates code.
Round trip validation
The following section describes when and how styling is guaranteed to yield correct code.
If tokens are not in the styling scope (as specified with the scope
argument), no tokens are changed and the abstract syntax tree (AST) should
not change.
Hence, it is possible to validate the styling by comparing whether the parsed
expression before and after styling have the same AST.
This comparison omits roxygen code examples and comments. styler throws an
error if the AST has changed through styling.
Note that if tokens are to be styled, such a comparison is not conducted because the AST might well change and such a change is intended. There is no way styler can validate styling, that is why we inform the user to carefully inspect the changes.
See section 'Warning' for a good strategy to apply styling safely.
Value
Invisibly returns a data frame that indicates for each file considered for
styling whether or not it was actually changed (or would be changed when
dry
is not "off").
See Also
Other stylers:
style_dir()
,
style_file()
,
style_text()
,
styler_addins
Examples
# the following is identical (because of ... and defaults)
# but the first is most convenient:
style_pkg(strict = TRUE)
style_pkg(style = tidyverse_style, strict = TRUE)
style_pkg(transformers = tidyverse_style(strict = TRUE))
# more options from `tidyverse_style()`
style_pkg(
scope = "line_breaks",
math_token_spacing = specify_math_token_spacing(zero = "'+'")
)
# don't write back and fail if input is not already styled
style_pkg("/path/to/pkg/", dry = "fail")
Style a roxygen code example that may contain dontrun and friends
Description
Parses roxygen2 comments into code, breaks it into dont* (dontrun, donttest,
dontshow) and run sections and processes each segment individually using
style_roxygen_example_snippet()
.
Usage
style_roxygen_code_example(example, transformers, base_indention)
Arguments
example |
Roxygen example code. |
transformers |
Passed to |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
Hierarchy
Styling involves splitting roxygen example code into segments, and segments
into snippets. This describes the process for input of
parse_transform_serialize_roxygen()
:
Splitting code into roxygen example code and other code. Downstream, we are only concerned about roxygen code. See
parse_transform_serialize_roxygen()
.Every roxygen example code can have zero or more dontrun / dontshow / donttest sequences. We next create segments of roxygen code examples that contain at most one of these. See
style_roxygen_code_example()
.We further split the segment that contains at most one dont* sequence into snippets that are either don* or not. See
style_roxygen_code_example_segment()
.
Finally, that we have roxygen code snippets that are either dont* or not,
we style them in style_roxygen_example_snippet()
using
parse_transform_serialize_r()
.
Style a roxygen code example with exactly one @example
or @exampleIf
Description
Style a roxygen code example with exactly one @example
or @exampleIf
Usage
style_roxygen_code_example_one(example_one, transformers, base_indention)
Arguments
example_one |
A character vector, one element per line, that contains in total at most one example tag. |
transformers |
Passed to |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
Style a roxygen code example segment
Description
A roxygen code example segment corresponds to roxygen example code that
contains at most one \\dontrun{...}
or friends.
We drop all newline characters first because otherwise the code segment
passed to this function was previously parsed with parse_roxygen()
and
line-breaks in and after the \\dontrun{...}
are expressed with "\n"
,
which contradicts to the definition used elsewhere in this package, where
every element in a vector corresponds to a line. These line-breaks don't get
eliminated because they move to the front of a code_segment
and
style_text("\n1")
gives "\n1"
, i.e. trailing newlines are not
eliminated.
Usage
style_roxygen_code_example_segment(one_dont, transformers, base_indention)
Arguments
one_dont |
Bare R code containing at most one |
transformers |
Passed to |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
Hierarchy
Styling involves splitting roxygen example code into segments, and segments
into snippets. This describes the process for input of
parse_transform_serialize_roxygen()
:
Splitting code into roxygen example code and other code. Downstream, we are only concerned about roxygen code. See
parse_transform_serialize_roxygen()
.Every roxygen example code can have zero or more dontrun / dontshow / donttest sequences. We next create segments of roxygen code examples that contain at most one of these. See
style_roxygen_code_example()
.We further split the segment that contains at most one dont* sequence into snippets that are either don* or not. See
style_roxygen_code_example_segment()
.
Finally, that we have roxygen code snippets that are either dont* or not,
we style them in style_roxygen_example_snippet()
using
parse_transform_serialize_r()
.
Given a code snippet is dont* or run, style it
Description
Given a code snippet is dont* or run, style it
Usage
style_roxygen_example_snippet(
code_snippet,
transformers,
is_dont,
base_indention
)
Arguments
code_snippet |
A character vector with code to style. |
transformers |
Passed to |
is_dont |
Whether the snippet to process is a dontrun, dontshow, donttest segment or not. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
Hierarchy
Styling involves splitting roxygen example code into segments, and segments
into snippets. This describes the process for input of
parse_transform_serialize_roxygen()
:
Splitting code into roxygen example code and other code. Downstream, we are only concerned about roxygen code. See
parse_transform_serialize_roxygen()
.Every roxygen example code can have zero or more dontrun / dontshow / donttest sequences. We next create segments of roxygen code examples that contain at most one of these. See
style_roxygen_code_example()
.We further split the segment that contains at most one dont* sequence into snippets that are either don* or not. See
style_roxygen_code_example_segment()
.
Finally, that we have roxygen code snippets that are either dont* or not,
we style them in style_roxygen_example_snippet()
using
parse_transform_serialize_r()
.
Styles the highlighted selection in a .R
or .Rmd
file.
Description
Styles the highlighted selection in a .R
or .Rmd
file.
Usage
style_selection()
Style spacing around math tokens
Description
Style spacing around math tokens
Usage
style_space_around_math_token(strict, zero, one, pd_flat)
Arguments
strict |
Whether the rules should be applied strictly or not. |
zero |
Character vector of tokens that should be surrounded with zero spaces. |
one |
Character vector with tokens that should be surrounded by at
least one space (depending on |
pd_flat |
A nest or a flat parse table. |
Set spacing of token to a certain level
Description
Set the spacing of all tokens
in pd_flat
to level
if strict = TRUE
or
to at least to level
if strict = FALSE
.
Usage
style_space_around_token(
pd_flat,
strict,
tokens,
level_before,
level_after = level_before
)
Arguments
pd_flat |
A nest or a flat parse table. |
strict |
Whether the rules should be applied strictly or not. |
tokens |
Character vector with tokens that should be styled. |
level_before , level_after |
Scalar indicating the amount of spaces that
should be inserted around the |
Style a string
Description
Styles a character vector. Each element of the character vector corresponds to one line of code.
Usage
style_text(
text,
...,
style = tidyverse_style,
transformers = style(...),
include_roxygen_examples = TRUE,
base_indention = 0L
)
Arguments
text |
A character vector with text to style. |
... |
Arguments passed on to the |
style |
A function that creates a style guide to use, by default
|
transformers |
A set of transformer functions. This argument is most
conveniently constructed via the |
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
See Also
Other stylers:
style_dir()
,
style_file()
,
style_pkg()
,
styler_addins
Examples
style_text("call( 1)")
style_text("1 + 1", strict = FALSE)
# the following is identical (because of ... and defaults)
# but the first is most convenient:
style_text("a<-3++1", strict = TRUE)
style_text("a<-3++1", style = tidyverse_style, strict = TRUE)
style_text("a<-3++1", transformers = tidyverse_style(strict = TRUE))
# more invasive scopes include less invasive scopes by default
style_text("a%>%b", scope = "spaces")
style_text("a%>%b; a", scope = "line_breaks")
style_text("a%>%b; a", scope = "tokens")
# opt out with I() to only style specific levels
style_text("a%>%b; a", scope = I("tokens"))
style_text()
without rules for \{\{
Description
This function mocks style_text()
, but without taking into consideration the
rules for the curly-curly syntactic sugar (introduced in rlang 0.4).
This function (style_text_without_curly_curly()
) is needed for testing
only, namely to test indention
with multiple curly braces in a sequence. It is important to maintain testing
for indention rules even as the curly-curly expression is always kept on the
same line in the tidyverse style guide because we should
ensure the underlying mechanics for indention work correctly. When
indention mechanisms are changed later, e.g. by simplifying
compute_indent_indices()
, we must have
a way of testing this without the interaction of \{\{
.
Usage
style_text_without_curly_curly(
text,
...,
style = tidyverse_style,
transformers = style(...),
include_roxygen_examples = TRUE
)
See Also
set_line_break_around_curly_curly
Examples
styler:::style_text_without_curly_curly("rlang::list2({{ x }} := 2L)")
styler:::style_text("rlang::list2({{ x }} := 3)")
Stylers for RStudio Addins
Description
Helper functions for styling via RStudio Addins.
Addins
Set style: Select the style transformers to use. For flexibility, the user input is passed to the
transformers
argument, not thestyle
argument, so enteringstyler::tidyverse_style(scope = "spaces")
in the Addin is equivalent tostyler::style_text("1+1", scope = "spaces")
andstyler::style_text("1+1", transformers = styler::tidyverse_style(scope = "spaces"))
if the text to style is1+1
. The style transformers are memorized within an R session via the R optionstyler.addins_style_transformer
so if you want it to persist over sessions, set the optionstyler.addins_style_transformer
in your.Rprofile
.Style active file: Styles the active file, by default with
tidyverse_style()
or the value of the optionstyler.addins_style_transformer
if specified.Style selection: Same as Style active file, but styles the highlighted code instead of the whole file.
Auto-Save Option
By default, both of the RStudio Addins will apply styling to the (selected)
file contents without saving changes. Automatic saving can be enabled by
setting the R option styler.save_after_styling
to TRUE
.
Consider setting this in your .Rprofile
file if you want to persist
this setting across multiple sessions. Untitled files will always need to be
saved manually after styling.
Life cycle
The way of specifying the style in the Addin as well as the auto-save option
(see below) are experimental. We are currently considering letting the user
specify the defaults for other style APIs like style_text()
,
either via R options, config files or other ways as well.
See r-lib/styler#319 for
the current status of this.
See Also
Other stylers:
style_dir()
,
style_file()
,
style_pkg()
,
style_text()
Examples
## Not run:
# save after styling when using the Addin
options(styler.save_after_styling = TRUE)
# only style with scope = "spaces" when using the Addin
val <- "styler::tidyverse_style(scope = 'spaces')"
options(
styler.addins_style_transformer = val
)
## End(Not run)
Turn off styling for parts of the code
Description
Using stylerignore markers, you can temporarily turn off styler. Beware that
for styler > 1.2.0
, some alignment is
detected by styler,
making stylerignore redundant. See a few illustrative examples below.
Details
Styling is on for all lines by default when you run styler.
To mark the start of a sequence where you want to turn styling off, use
# styler: off
.To mark the end of this sequence, put
# styler: on
in your code. After that line, styler will again format your code.To ignore an inline statement (i.e. just one line), place
# styler: off
at the end of the line. To use something else as start and stop markers, set the R optionsstyler.ignore_start
andstyler.ignore_stop
usingoptions()
. For styler version > 1.6.2, the option supports character vectors longer than one and the marker are not exactly matched, but using a regular expression, which means you can have multiple marker on one line, e.g.# nolint start styler: off
.
Examples
# as long as the order of the markers is correct, the lines are ignored.
style_text(
"
1+1
# styler: off
1+1
# styler: on
1+1
"
)
# if there is a stop marker before a start marker, styler won't be able
# to figure out which lines you want to ignore and won't ignore anything,
# issuing a warning.
## Not run:
style_text(
"
1+1
# styler: off
1+1
# styler: off
1+1
"
)
## End(Not run)
# some alignment of code is detected, so you don't need to use stylerignore
style_text(
"call(
xyz = 3,
x = 11
)"
)
Consolidate columns after a merge
Description
After base::merge()
, all non-id columns that were present in x
and y
do get a suffix .x
and .y
. If the y
value is missing, use the x
value (because the information for this token was not stylerignored),
otherwise the y
value (i.e. the styled value).
Usage
stylerignore_consolidate_col(
flattened_pd,
col,
col_x = paste0(col, ".x"),
col_y = paste0(col, ".y")
)
Arguments
flattened_pd |
A flattened parse table. |
col |
A string indicating the name of the column that should be consolidated. |
col_x , col_y |
The name of the column from the left (right) parent to consolidate. |
Run a collection of tests
Description
Run transformations on all *-in.R files in a test directory and compare them with their *-out.R counterpart.
Usage
test_collection(
test,
sub_test = NULL,
dry = "off",
write_tree = NA,
transformer,
...
)
Arguments
test |
The test to run. It corresponds to a folder name in tests/testthat. |
sub_test |
A regex pattern to further reduce the amount of test files
to be tested in the test. |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
write_tree |
Whether or not the tree structure of the test should be
computed and written to a file. Note that this needs R >= 3.2
(see |
transformer |
A function to apply to the content of |
... |
Parameters passed to transformer function. |
Details
Each file name that matches test
and sub_test
and ends with
"-in.R" is considered as an input to test. Its counterpart,
the reference to compare it against is the *-out.R file. It is constructed
by taking the substring of the *-in.R file before the
last dash and adding -out.R. In contrast to older versions of this
function, every *-out.R file has just one in file.
Test the dry argument
Description
Test the dry argument
Usage
test_dry(path, styler, styled = FALSE)
Arguments
path |
A path to pass to the |
styler |
A function that takes |
Transforming test input with a transformer function
Description
These functions can be used as inputs for test_collection()
and
transform_and_check()
.
Usage
style_empty(text, base_indention = 0L)
style_op(text, base_indention = 0L)
Arguments
text |
A character vector to transform. |
Details
As inputs for test_collection()
, we can also use top-level functions such
as style_text()
.
Functions
-
style_empty()
: Nest and unnesttext
without applying any transformations but remove EOL spaces and indention due to the way the serialization is set up. -
style_op()
: Transformations for indention based on operators
Test transformers_drop
for consistency
Description
Check if the argument transformers_drop
in create_style_guide()
is
consistent with the transformers specified in that function.
Usage
test_transformers_drop(transformers)
Arguments
transformers |
The output of |
Create the path to a test that file
Description
Create the path to a test that file
Usage
testthat_file(...)
Arguments
... |
Arguments passed to |
Creates a flat parse table with minimal initialization
Description
Creates a flat parse table with minimal initialization and makes the parse table shallow where appropriate.
Usage
text_to_flat_pd(text, transformers, more_specs)
Arguments
text |
The text to parse. |
transformers |
Passed to |
more_specs |
Passed to |
Details
This includes:
token before and after.
stylerignore attribute.
caching attributes.
Note that the parse table might be shallow if caching is enabled and some values are cached.
The tidyverse style
Description
Style code according to the tidyverse style guide.
Usage
tidyverse_style(
scope = "tokens",
strict = TRUE,
indent_by = 2L,
start_comments_with_one_space = FALSE,
reindention = tidyverse_reindention(),
math_token_spacing = tidyverse_math_token_spacing()
)
Arguments
scope |
The extent of manipulation. Can range from "none" (least
invasive) to "tokens" (most invasive). See 'Details'. This argument is a
string or a vector of class |
strict |
A logical value indicating whether a set of strict
or not so strict transformer functions should be returned. Compare the
functions returned with or without |
indent_by |
How many spaces of indention should be inserted after operators such as '('. |
start_comments_with_one_space |
Whether or not comments should start
with only one space (see |
reindention |
A list of parameters for regex re-indention, most
conveniently constructed using |
math_token_spacing |
A list of parameters that define spacing around
math token, conveniently constructed using |
Details
The following levels for scope
are available:
"none": Performs no transformation at all.
"spaces": Manipulates spacing between token on the same line.
"indention": Manipulates the indention, i.e. number of spaces at the beginning of each line.
"line_breaks": Manipulates line breaks between tokens.
"tokens": manipulates tokens.
scope
can be specified in two ways:
As a string: In this case all less invasive scope levels are implied, e.g. "line_breaks" includes "indention", "spaces". This is brief and what most users need.
As vector of class
AsIs
: Each level has to be listed explicitly by wrapping one ore more levels of the scope inI()
. This offers more granular control at the expense of more verbosity.
See 'Examples' for details.
Examples
style_text("call( 1)", style = tidyverse_style, scope = "spaces")
style_text("call( 1)", transformers = tidyverse_style(strict = TRUE))
style_text(c("ab <- 3", "a <-3"), strict = FALSE) # keeps alignment of "<-"
style_text(c("ab <- 3", "a <-3"), strict = TRUE) # drops alignment of "<-"
# styling line breaks only without spaces
style_text(c("ab <- 3", "a =3"), strict = TRUE, scope = I(c("line_breaks", "tokens")))
Check if tokens are aligned
Description
If all tokens are aligned, TRUE
is returned, otherwise FALSE
. The
function only checks for alignment of function calls. This can be
recycled conveniently later if needed as a vector with length > 1.
Usage
token_is_on_aligned_line(pd_flat)
Arguments
pd_flat |
A flat parse table. |
Details
Multiple lines are called aligned if the following conditions hold for all but the first line of the expression:
lag spaces of column 1 must agree.
spacing around comma (0 before, > 1 after) and spacing around
=
(at least one around).all positions of commas of col > 2 must agree (needs recursive creation of
text
).
Because of the last requirement, this function is very expensive to run. For this reason, the following approach is taken:
Only invoke the function when certain that alignment is possible.
Check the cheap conditions first.
For the recursive creation of text, greedily check column by column to make sure we can stop as soon as we found that columns are not aligned.
Examples
library("magrittr")
withr::with_options(
list(styler.cache_name = NULL), # temporarily deactivate cache
{
transformers <- tidyverse_style()
pd_nested <- compute_parse_data_nested(c(
"call(",
" ab = 1L,",
" a = 2",
")"
)) %>%
styler:::post_visit(transformers$initialize)
nest <- pd_nested$child[[1L]]
styler:::token_is_on_aligned_line(nest)
}
)
Obtain token table from text
Description
utils::getParseData()
is used to obtain a flat parse table from text
.
Usage
tokenize(text)
Arguments
text |
The text to parse. |
Details
Apart from the columns provided by utils::getParseData()
, the following
columns are added:
A column "short" with the first five characters of "text".
A column "pos_id" for (positional id) which can be used for sorting (because "id" cannot be used in general). Note that the nth value of this column corresponds to n as long as no tokens are inserted.
A column "child" that contains nests.
Value
A flat parse table
Transform a file an check the result
Description
Transform an file and check whether it is identical to a reference.
Usage
transform_and_check(
in_item,
out_item,
in_name = in_item,
out_name = out_item,
transformer,
dry,
write_tree = NA,
out_tree = "_tree",
...
)
Arguments
in_item |
An path to an file to transform. |
out_item |
The path to a file that contains the expected result. |
in_name |
The label of the in_item, defaults to |
out_name |
The label of the out_item, defaults to |
transformer |
A function to apply to the content of |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
write_tree |
Whether or not the tree structure of the test should be
computed and written to a file. Note that this needs R >= 3.2
(see |
out_tree |
Name of tree file if written out. |
... |
Parameters passed to transformer function. |
Transform code from R, Rmd or Rnw files
Description
A wrapper which initiates the styling of either R, Rmd or Rnw files by passing the relevant transformer function for each case.
Usage
transform_code(path, fun, ..., dry)
Arguments
path |
A vector with file paths to transform. |
fun |
A function that returns a character vector. |
... |
Further arguments passed to |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Transform a file and output a customized message
Description
Transforms file contents and outputs customized messages.
Usage
transform_file(
path,
fun,
max_char_path,
message_before = "",
message_after = " [DONE]",
message_after_if_changed = " *",
...,
dry
)
Arguments
path |
A vector with file paths to transform. |
fun |
A function that returns a character vector. |
max_char_path |
The number of characters of the longest path. Determines
the indention level of |
message_before |
The message to print before the path. |
message_after |
The message to print after the path. |
message_after_if_changed |
The message to print after |
... |
Further arguments passed to |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Transform files with transformer functions
Description
transform_files
applies transformations to file contents and writes back
the result.
Usage
transform_files(
files,
transformers,
include_roxygen_examples,
base_indention,
dry
)
Arguments
files |
A character vector with paths to the file that should be transformed. |
transformers |
A list of transformer functions that operate on flat parse tables. |
include_roxygen_examples |
Whether or not to style code in roxygen examples. |
base_indention |
Integer scalar indicating by how many spaces the whole
output text should be indented. Note that this is not the same as splitting
by line and add a |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Value
Invisibly returns a data frame that indicates for each file considered for
styling whether or not it was actually changed (or would be changed when
dry
is not "off").
Transform mixed contents
Description
Applies the supplied transformer function to code chunks identified within an Rmd or Rnw file and recombines the resulting (styled) code chunks with the text chunks.
Usage
transform_mixed(lines, transformer_fun, filetype)
Arguments
lines |
A character vector of lines from an Rmd or Rnw file. |
transformer_fun |
A styler transformer function. |
filetype |
A string indicating the filetype - either 'Rmd' or 'Rnw'. |
Ensure for .Rmd
and friends that a code chunk without code is formatted as
a code chunk without any lines.
Description
Ensure for .Rmd
and friends that a code chunk without code is formatted as
a code chunk without any lines.
Usage
transform_mixed_non_empty(r_chunk, transformer_fun)
Apply a function to the contents of a file
Description
Transforms a file with a function.
Usage
transform_utf8(path, fun, dry)
Arguments
path |
A vector with file paths to transform. |
fun |
A function that returns a character vector. |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Potentially transform a file
Description
Potentially transform a file
Usage
transform_utf8_one(path, fun, dry)
Arguments
path |
A vector with file paths to transform. |
fun |
A function that returns a character vector. |
dry |
To indicate whether styler should run in dry mode, i.e. refrain
from writing back to files . |
Remove transformers that are not needed
Description
The goal is to speed up styling by removing all rules that are only
applicable in contexts that don't occur often, e.g. for most code, we don't
expect ";" to be in it, so we don't need to apply resolve_semicolon()
on
every nest.
Usage
transformers_drop(text, transformers)
Arguments
text |
Text to parse. Can also be the column |
transformers |
the transformers. |
See Also
specify_transformers_drop
Style a file as if it was an .R file
Description
If not successful, the file is most likely not a .R file, so saving the file and try styling again will work if the file is an .Rmd file. Otherwise, we can throw an error that the file must be a .R or .Rmd file.
Usage
try_transform_as_r_file(context, transformer)
Arguments
context |
The context from |
transformer |
A transformer function most conveniently constructed with
|
Unindent a child
Description
Unindent a child
Usage
unindent_child(pd, token = c("')'", "'}'"), unindent_by = 2L)
Arguments
pd |
A parse table. |
token |
The token the unindention should be based on. |
unindent_by |
By how many spaces one level of indention is reversed. |
Revert the indention of function declaration header
Description
Necessary for consistent indention of the function declaration header.
Usage
unindent_fun_dec(pd, indent_by = 2L)
Arguments
pd |
A parse table. |
indent_by |
How many spaces of indention should be inserted after operators such as '('. |
See Also
set_unindention_child update_indention_ref_fun_dec
Update indention information of parse data
Description
Update indention information of parse data
Usage
indent_without_paren_for_while_fun(pd, indent_by)
indent_without_paren_if_else(pd, indent_by)
indent_braces(pd, indent_by)
indent_op(
pd,
indent_by,
token = c(math_token, logical_token, special_token, "PIPE", "LEFT_ASSIGN", "EQ_ASSIGN",
"'$'", "'~'")
)
indent_eq_sub(pd, indent_by, token = c("EQ_SUB", "EQ_FORMALS"))
indent_without_paren(pd, indent_by = 2L)
Arguments
pd |
A nested or flat parse table that is already enhanced with
line break and space information via |
indent_by |
How many spaces should be added after the token of interest. |
token |
The token the indention should be based on. |
Functions
-
indent_without_paren_for_while_fun()
: Is used to indent for and statements and function definitions without parenthesis. -
indent_without_paren_if_else()
: Is used to indent if and if-else statements. -
indent_braces()
: Inserts indention based on round, square and curly brackets. -
indent_op()
: Indents all tokens aftertoken
- including the last token. -
indent_eq_sub()
: Updates indention for token EQ_SUB. Only differs fromindent_op()
in the sense that not all subsequent tokens in the parse table are necessarily indented, asEQ_SUB
andEQ_FORMALS
can occur multiple times in a parse table. occurs is not indented (seecompute_indent_indices()
) -
indent_without_paren()
: Is used to indent for / while / if / if-else statements that do not have curly parenthesis.
Update the indention reference
Description
Update the indention reference
Usage
update_indention_ref_fun_dec(pd_nested)
Arguments
pd_nested |
A nested parse table. |
Functions
-
update_indention_ref_fun_dec()
: Updates the reference pos_id for all tokens inpd_nested
ifpd_nested
contains a function declaration. Tokens inside a function declaration are are re-indented, that is, they are indented up to the level at which the token FUNCTION ends in terms of col2.
Examples
## Not run:
a <- function(x,
y) {
x + y
}
## End(Not run)
Update the newlines attribute
Description
As we work only with the lag_newlines
attribute for setting the line
breaks (R/rules-line_breaks.R
), but we need newlines
to determine
whether or not to set spaces
(R/rules-spaces.R
), we have to update the
attribute. We cannot simply use dplyr::lead(pd$lag_newlines)
since we would
lose information for the last token. spaces
is left as is in
R/rules-spacing.R for tokens at the end of a line since this allows styling
without touching indention.
Usage
update_newlines(pd)
Arguments
pd |
A parse table. |
Value
A parse table with synchronized lag_newlines
and newlines
columns.
See Also
choose_indention
Validate sequence of new position ids
Description
Ids created with after = TRUE
can have pos_id
values between x.0 and
x.5 and ids created with after = FALSE
can have pos_id
values between
1+ x.0 and 1 + x.5 where x is the pos_id
integer which was used as a
reference to create the new pos_ids
.
Usage
validate_new_pos_ids(new_ids, after)
Arguments
new_ids |
A vector with new ids |
after |
Whether the ids are created with |
See Also
Other token creators:
create_pos_ids()
,
create_tokens()
Verify the styling
Description
If scope was set to "line_breaks" or lower (compare tidyverse_style()
),
we can compare the expression before and after styling and return an error if
it is not the same.
If that's not possible, a weaker guarantee that we want to give is that the
resulting code is parsable.
Usage
verify_roundtrip(old_text, new_text, parsable_only = FALSE)
Arguments
old_text |
The initial expression in its character representation. |
new_text |
The styled expression in its character representation. |
parsable_only |
If we should only check for the code to be parsable. |
Limitation
Note that this method ignores roxygen code examples and comments and no verification can be conducted if tokens are in the styling scope.
Examples
styler:::verify_roundtrip("a+1", "a + 1")
styler:::verify_roundtrip("a+1", "a + 1 # comments are dropped")
try(styler:::verify_roundtrip("a+1", "b - 3"))
Visit'em all
Description
Apply a list of functions to each level in a nested parse table.
pre_visit()
applies funs
before it proceeds to the children,
(that is, starts from the outermost level of nesting progressing
to the innermost level), post_visit()
proceeds to its children
before applying the functions (meaning it first applies the functions
to the innermost level of nesting first and then going outwards).
Usage
pre_visit(pd_nested, funs)
pre_visit_one(pd_nested, fun)
post_visit(pd_nested, funs)
post_visit_one(pd_nested, fun)
Arguments
pd_nested |
A nested parse table. |
funs |
A list of transformer functions. |
See Also
Other visitors:
visit_one()
Transform a flat parse table with a list of transformers
Description
Uses Reduce()
to apply each function of funs
sequentially to
pd_flat
.
Usage
visit_one(pd_flat, funs)
Arguments
pd_flat |
A flat parse table. |
funs |
A list of transformer functions. |
See Also
Other visitors:
visit
Add curly braces to else
Description
Wrap the else part of a conditional expression into curly braces if not already wrapped into a such.
Usage
wrap_else_multiline_curly(pd, indent_by = 2L, space_after = 0L)
Arguments
pd |
A parse table. |
indent_by |
The amount of spaces used to indent an expression in curly braces. Used for unindention. |
space_after |
How many spaces should be inserted after the closing brace. |
Wrap an expression in curly braces
Description
Adds curly braces to an expression (represented as a parse table) if there are none.
Usage
wrap_expr_in_curly(pd, stretch_out = c(FALSE, FALSE), space_after = 1L)
Arguments
pd |
A parse table. |
stretch_out |
Whether or not to create a line break after the opening curly brace and before the closing curly brace. |
space_after |
How many spaces should be inserted after the closing brace. |
Wrap an expression into an expression
Description
Takes a parse table and wraps it in a new parse table that contains the expression as a child.
Usage
wrap_expr_in_expr(pd)
Arguments
pd |
A parse table. |
Wrap if-else, while and for statements in curly braces
Description
Wrap statements in curly braces if it is not already wrapped in a such.
Usage
wrap_if_else_while_for_fun_multi_line_in_curly(pd, indent_by = 2L)
Arguments
pd |
A parse table. |
indent_by |
The amount of spaces used to indent an expression in curly braces. Used for unindention. |
Wrap a multi-line statement in curly braces
Description
Wrap a multi-line statement in curly braces
Usage
wrap_multiline_curly(pd, indent_by, key_token, space_after = 1L)
Arguments
pd |
A parse table. |
indent_by |
The amount of spaces used to indent an expression in curly braces. Used for unindention. |
key_token |
The token that comes right before the token that contains the expression to be wrapped (ignoring comments). For if and while loops, this is the closing "')'", for a for-loop it's "forcond". |
space_after |
How many spaces should be inserted after the closing brace. |
Wrap a sub-expression in curly braces
Description
Wraps some rows of a parse table into a sub-expression.
Usage
wrap_subexpr_in_curly(pd, ind_to_be_wrapped, indent_by, space_after)
Arguments
pd |
A parse table. |
ind_to_be_wrapped |
The indices of the rows that should be wrapped into a new expression. |
space_after |
How many spaces should be inserted after the closing brace. |
Drop-in replacement for xfun::write_utf8()
Description
Drop-in replacement for xfun::write_utf8()
Usage
write_utf8(text, con, ...)