Skip to content

Cache styling #538

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 69 commits into from
Dec 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
938c9f9
implement basic caching
lorenzwalthert Aug 15, 2019
94c48ae
cache administration tools
lorenzwalthert Aug 15, 2019
f57a7c5
set all options in .onLoad(), do not use the default in getOptions().
lorenzwalthert Aug 15, 2019
cc02ccd
don't use cache in general
lorenzwalthert Aug 15, 2019
bf658be
handle situation where R.cache is not available.
lorenzwalthert Aug 15, 2019
f2a8d2e
assert that the R.cache is installed
lorenzwalthert Aug 15, 2019
fc9ec71
drop fs dependency.
lorenzwalthert Aug 15, 2019
4ceb7c5
fix naming.
lorenzwalthert Aug 15, 2019
59168c2
fix R cmd check
lorenzwalthert Aug 15, 2019
219a73c
res-style with stylermd
lorenzwalthert Aug 16, 2019
b721904
add more cache manipulators.
lorenzwalthert Aug 16, 2019
3fe9bbd
don't use technical name cache_subdir (as it would be from the R.cach…
lorenzwalthert Aug 16, 2019
6aef9ff
fix spacing.
lorenzwalthert Aug 16, 2019
390d2b4
be consistent: all cache functions start with cache_
lorenzwalthert Aug 16, 2019
fa3dc16
also export deactivate
lorenzwalthert Aug 16, 2019
3ff182a
don't read the cache, just check if it exists
lorenzwalthert Aug 17, 2019
1ab8be0
make styling work without R.chache installed.
lorenzwalthert Aug 17, 2019
e48b5ec
add line break at end of message.
lorenzwalthert Aug 17, 2019
bb52ea0
add action = "abort" as optional.
lorenzwalthert Aug 17, 2019
fb98b79
return a default path stlyer/:version instead instead of just styler …
lorenzwalthert Aug 19, 2019
0d0fa92
remove option styler.use_cache. If styler.cache_name is NULL, this is…
lorenzwalthert Aug 19, 2019
43c58c9
also test when R.cache is not installed.
lorenzwalthert Aug 19, 2019
87d782a
add new option "both" for cache_info(), argument "format".
lorenzwalthert Aug 22, 2019
b2b4213
outsource logic to get cache name from input, get it from the option …
lorenzwalthert Aug 22, 2019
865c6e8
cache_is_activated() can now return information about a specific cach…
lorenzwalthert Aug 22, 2019
73d0220
random doc update
lorenzwalthert Aug 22, 2019
6fad8c4
improve tests
lorenzwalthert Aug 22, 2019
f51c707
add a verbose argument to cache_deactivate
lorenzwalthert Aug 22, 2019
94d5891
split R/ui.R into R/ui-caching.R and R/ui-styling.R
lorenzwalthert Aug 22, 2019
18807d1
test that after clearing a cache, no cache is active.
lorenzwalthert Aug 22, 2019
2f85b12
describe caching.
lorenzwalthert Aug 22, 2019
cea1922
cache_activate gains new argument verbose for consistency.
lorenzwalthert Aug 22, 2019
66b276d
tidy description.
lorenzwalthert Aug 22, 2019
8c2c7ed
don't add another style_file that convolutes full text search and "go…
lorenzwalthert Aug 22, 2019
2fc8808
minor fixes and simplification
lorenzwalthert Aug 22, 2019
dd19539
assume R_REMOVE_RCACHE is false when not set to true.
lorenzwalthert Aug 22, 2019
2848ac1
make file less nicely styled
lorenzwalthert Aug 22, 2019
6eba449
round values to make tests pass on all plattforms.
lorenzwalthert Aug 22, 2019
3f91267
round two digits
lorenzwalthert Aug 22, 2019
fac1558
style with stylermd
lorenzwalthert Aug 23, 2019
346f76b
cache NULL, not the sysdate, which can also be derived from the creat…
lorenzwalthert Aug 23, 2019
813d4e8
add news section on caching.
lorenzwalthert Aug 23, 2019
f170c27
adapt test for hashing NULL
lorenzwalthert Aug 29, 2019
90f927a
use the shallow cache only (needs my fork or R.cache).
lorenzwalthert Sep 10, 2019
1b3814d
use R.cache
lorenzwalthert Sep 10, 2019
ab3ed59
unrelated wording NEWS
lorenzwalthert Sep 23, 2019
9674200
doc wording
lorenzwalthert Sep 23, 2019
fe74f9e
don't o$
lorenzwalthert Sep 23, 2019
b1cf70d
derive cache more cheaply
lorenzwalthert Sep 23, 2019
f2b16a5
chache size should be 0 with shallow option
lorenzwalthert Sep 23, 2019
427a1c0
move R.cache to suggest as initially thought
lorenzwalthert Sep 23, 2019
2996302
replace cache_derive_name() with constant
lorenzwalthert Sep 23, 2019
9326f44
random roxygenize
lorenzwalthert Sep 23, 2019
0a81566
capsule line break conversion in a function
lorenzwalthert Sep 23, 2019
c0e1292
make cache work when text is supplied with embedded line breaks
lorenzwalthert Sep 23, 2019
c2c8e63
need pkg qualifier for example with internal function
lorenzwalthert Oct 22, 2019
6993203
some version that seems to work
lorenzwalthert Nov 1, 2019
4f3ab57
make commit to keep reproducible example where hashes of transformers…
lorenzwalthert Nov 1, 2019
172ad9a
document edge cases
lorenzwalthert Nov 1, 2019
5efc656
add test
lorenzwalthert Nov 1, 2019
d013cea
again remove xfun reference
lorenzwalthert Nov 1, 2019
4fb19f9
Merge branch 'master' into caching
krlmlr Dec 1, 2019
abb204e
Tweaks
krlmlr Dec 1, 2019
36606a2
use upstream R.cache for caching
lorenzwalthert Dec 4, 2019
c6c3aff
new documentation roxygen version
lorenzwalthert Dec 4, 2019
6d3cd88
don't cat info on cached
lorenzwalthert Dec 13, 2019
6f15cc8
R.cache version we depend on now on CRAN
lorenzwalthert Dec 13, 2019
1db8262
Merge branch 'master' into caching
lorenzwalthert Dec 14, 2019
0d41f9b
more info
lorenzwalthert Dec 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# All available hooks: https://pre-commit.com/hooks.html
repos:
- repo: https://github.com/lorenzwalthert/precommit
rev: v0.0.0.9018
rev: v0.0.0.9024
hooks:
- id: lintr
# - id: lintr
- id: parsable-R
- id: no-browser-statement
- id: readme-rmd-rendered
Expand Down
5 changes: 4 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Usually you shouldn't need to change the first part of the file

# DO NOT CHANGE THE CODE BELOW
before_install: R -q -e 'install.packages(c("remotes", "curl", "knitr", "rmarkdown")); remotes::install_github("ropenscilabs/tic"); tic::prepare_all_stages(); remotes::install_deps(dependencies = TRUE); tic::before_install()'
before_install: R -q -e 'install.packages(c("remotes", "curl", "knitr", "rmarkdown")); remotes::install_github("ropenscilabs/tic"); tic::prepare_all_stages(); remotes::install_deps(dependencies = TRUE); if (isTRUE(as.logical(toupper(Sys.getenv("R_REMOVE_RCACHE"))))) remove.packages("R.cache"); tic::before_install()'
install: R -q -e 'tic::install()'
after_install: R -q -e 'tic::after_install()'
before_script: R -q -e 'tic::before_script()'
Expand Down Expand Up @@ -38,6 +38,9 @@ matrix:
- r: release
env:
- BUILD_PKGDOWN: true
- r: release
env:
- R_REMOVE_RCACHE: true
- r: devel

#env
Expand Down
4 changes: 4 additions & 0 deletions API
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Exported functions

cache_activate(cache_name = NULL, verbose = TRUE)
cache_clear(cache_name = NULL, ask = TRUE)
cache_deactivate(verbose = TRUE)
cache_info(cache_name = NULL, format = "both")
create_style_guide(initialize = default_style_guide_attributes, line_break = NULL, space = NULL, token = NULL, indention = NULL, use_raw_indention = FALSE, reindention = tidyverse_reindention())
default_style_guide_attributes(pd_flat)
specify_math_token_spacing(zero = "'^'", one = c("'+'", "'-'", "'*'", "'/'"))
Expand Down
11 changes: 8 additions & 3 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Package: styler
Type: Package
Package: styler
Title: Non-Invasive Pretty Printing of R Code
Version: 1.2.0.9000
Authors@R:
Expand Down Expand Up @@ -30,14 +30,17 @@ Imports:
xfun (>= 0.1)
Suggests:
data.tree (>= 0.1.6),
digest,
dplyr,
here,
knitr,
prettycode,
R.cache (>= 0.14.0),
rmarkdown,
rstudioapi (>= 0.7),
testthat (>= 2.1.0)
VignetteBuilder: knitr
VignetteBuilder:
knitr
Encoding: UTF-8
LazyData: true
Roxygen: list(markdown = TRUE, roclets = c("rd", "namespace",
Expand Down Expand Up @@ -80,8 +83,10 @@ Collate:
'token-create.R'
'transform-code.R'
'transform-files.R'
'ui.R'
'ui-caching.R'
'ui-styling.R'
'unindent.R'
'utils-cache.R'
'utils-files.R'
'utils-navigate-nest.R'
'utils-strings.R'
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Generated by roxygen2: do not edit by hand

S3method(print,vertical)
export(cache_activate)
export(cache_clear)
export(cache_deactivate)
export(cache_info)
export(create_style_guide)
export(default_style_guide_attributes)
export(specify_math_token_spacing)
Expand Down
13 changes: 10 additions & 3 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,16 @@

## New features

* Aligned function calls are detected and kept as is if they match the styler
[definition for aligned function calls](https://styler.r-lib.org/articles/detect-alignment.html)
(#537).
* styler caches results of styling, so applying styler to code it has styled
before will be instantaneous. This brings large speed boosts in many
situations, e.g. when `style_pkg()` is run but only a few files have changed
since the last styling or when using the [styler pre-commit
hook](https://github.com/lorenzwalthert/pre-commit-hooks). See the README for
details (#538).

* Aligned function calls are detected and remain unchanged if they match the styler
[definition for aligned function
calls](https://styler.r-lib.org/articles/detect-alignment.html) (#537).

* curly-curly (`{{`) syntactic sugar introduced with rlang 0.4.0 is now
explicitly handled, where previously it was just treated as two consecutive
Expand Down
2 changes: 1 addition & 1 deletion R/addins.R
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ set_style_transformers <- function() {
#'
#' @keywords internal
get_addins_style_transformer_name <- function() {
getOption("styler.addins_style_transformer", default = "styler::tidyverse_style()")
getOption("styler.addins_style_transformer")
}

#' @rdname get_addins_style_transformer_name
Expand Down
34 changes: 34 additions & 0 deletions R/communicate.R
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,37 @@ assert_data.tree_installation <- function() {
abort("The package data.tree needs to be installed for this functionality.")
}
}

#' Assert the R.cache installation in conjunction with the cache config
#'
#' R.cache needs to be installed if caching functionality is enabled
#' @param installation_only Whether or not to only check if R.cache is
#' installed.
#' @keywords internal
assert_R.cache_installation <- function(installation_only = FALSE,
action = "abort") {
# fail if R.cache is not installed but feature is actiavted.
if (!rlang::is_installed("R.cache") &&
ifelse(installation_only, TRUE, cache_is_activated())
) {
msg_basic <- paste(
"R package R.cache is not installed, which is needed when the caching ",
"feature is activated. Please install the package with ",
"`install.packages('R.cache')` and then restart R to enable the ",
"caching feature of styler or permanently deactivate the feature by ",
"adding `styler::cache_deactivate()` to your .Rprofile, e.g. via ",
"`usethis::edit_r_profile()`.",
sep = ""
)

if (action == "abort") {
rlang::abort(msg_basic)
} else {
rlang::warn(paste0(
msg_basic, " ",
"Deactivating the caching feature for the current session."
))
cache_deactivate(verbose = FALSE)
}
}
}
4 changes: 2 additions & 2 deletions R/io.R
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ read_utf8 <- function(path) {
}
}

#' Drop-in replacement for [xfun::read_utf8()], with an optional `warn`
#' Drop-in replacement for `xfun::read_utf8()`, with an optional `warn`
#' argument.
#' @keywords internal
read_utf8_bare <- function(con, warn = TRUE) {
Expand All @@ -80,7 +80,7 @@ read_utf8_bare <- function(con, warn = TRUE) {
x
}

#' Drop-in replacement for `xfun:::invalid_utf8()`.
#' Drop-in replacement for [xfun:::invalid_utf8()]
#' @keywords internal
invalid_utf8 <- function(x) {
which(!is.na(x) & is.na(iconv(x, "UTF-8", "UTF-8")))
Expand Down
5 changes: 2 additions & 3 deletions R/roxygen-examples-parse.R
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ parse_roxygen <- function(roxygen) {
#' @param raw Raw code to post-process.
#' @keywords internal
post_parse_roxygen <- function(raw) {
split <- raw %>%
raw %>%
paste0(collapse = "") %>%
strsplit("\n", fixed = TRUE)
split[[1]]
convert_newlines_to_linebreaks()
}
2 changes: 1 addition & 1 deletion R/serialize.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ serialize_parse_data_flattened <- function(flattened_pd, start_line = 1) {
map(lag_newlines, add_newlines), map(lag_spaces, add_spaces), text
)
)
strsplit(res, "\n")[[1L]]
convert_newlines_to_linebreaks(res)
}
48 changes: 39 additions & 9 deletions R/transform-files.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,47 @@ transform_file <- function(path,
#' @inheritParams parse_transform_serialize_r
#' @keywords internal
#' @importFrom purrr when
make_transformer <- function(transformers, include_roxygen_examples, warn_empty = TRUE) {
make_transformer <- function(transformers,
include_roxygen_examples,
warn_empty = TRUE) {
force(transformers)
cache_dir <- c("styler", cache_get_name())
assert_R.cache_installation(action = "warn")

is_R.cache_installed <- rlang::is_installed("R.cache")

function(text) {
transformed_code <- text %>%
parse_transform_serialize_r(transformers, warn_empty = warn_empty) %>%
when(
include_roxygen_examples ~
parse_transform_serialize_roxygen(., transformers),
~.
)
transformed_code
should_use_cache <- is_R.cache_installed && cache_is_activated()

if (should_use_cache) {
use_cache <- R.cache::generateCache(
key = cache_make_key(text, transformers),
dirs = cache_dir
) %>%
file.exists()
} else {
use_cache <- FALSE
}

if (!use_cache) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an early return like if (use_cache) return(text) ?

transformed_code <- text %>%
parse_transform_serialize_r(transformers, warn_empty = warn_empty) %>%
when(
include_roxygen_examples ~
parse_transform_serialize_roxygen(., transformers),
~.
)
if (should_use_cache) {
R.cache::generateCache(
key = cache_make_key(transformed_code, transformers),
dirs = cache_dir
) %>%
file.create()
}
transformed_code
} else {
text
}
}
}

Expand Down
105 changes: 105 additions & 0 deletions R/ui-caching.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
#' Clear the cache
#'
#' 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 stystem) won't be deleted, but it will be empty after calling
#' `cache_clear`.
#' @param cache_name The name of the styler cache to use. If
#' `NULL`, the option "styler.cache_name" is considered which defaults to
#' the version of styler used.
#' @details
#' Each version of styler has it's own cache by default, because styling is
#' potentially different with different versions of styler.
#' @param ask Whether or not to interactively ask the user again.
#' @family cache managers
#' @export
cache_clear <- function(cache_name = NULL, ask = TRUE) {
assert_R.cache_installation(installation_only = TRUE)
path_cache <- cache_find_path(cache_name)
R.cache::clearCache(path_cache, prompt = ask)
cache_deactivate(verbose = FALSE)
}

#' Show information about the styler cache
#'
#' 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 innode is
#' excluded from this displayed size but negligible.
#' @param cache_name The name of the cache for which to show details. If
#' `NULL`, the active cache is used. If none is active the cache corresponding
#' to the installed styler version is used.
#' @param format Either "lucid" for a summary emitted with [base::cat()],
#' "tabular" for a tabular summary from [base::file.info()] or "both" for
#' both.
#' @family cache managers
#' @export
cache_info <- function(cache_name = NULL, format = "both") {
assert_R.cache_installation(installation_only = TRUE)
rlang::arg_match(format, c("tabular", "lucid", "both"))
path_cache <- cache_find_path(cache_name)
files <- list.files(path_cache, full.names = TRUE)
file_info <- file.info(files) %>%
as_tibble()
tbl <- tibble(
n = nrow(file_info),
size = sum(file_info$size),
last_modified = suppressWarnings(max(file_info$mtime)),
created = file.info(path_cache)$ctime,
location = path_cache,
activated = cache_is_activated(cache_name)
)
if (format %in% c("lucid", "both")) {
cat(
"Size:\t\t", tbl$size, " bytes (", tbl$n, " cached expressions)",
"\nLast modified:\t", as.character(tbl$last_modified),
"\nCreated:\t", as.character(tbl$created),
"\nLocation:\t", path_cache,
"\nActivated:\t", tbl$activated,
"\n",
sep = ""
)
}
if (format == "tabular") {
tbl
} else if (format == "both") {
invisible(tbl)
}
}

#' Activate or deactivate the styler cache
#'
#' Helper functions to control the behavior of caching. Simple wrappers around
#' [base::options()].
#' @inheritParams cache_clear
#' @param verbose Whether or not to print an informative message about what the
#' function is doing.
#' @family cache managers
#' @export
cache_activate <- function(cache_name = NULL, verbose = TRUE) {
assert_R.cache_installation(installation_only = TRUE)
if (!is.null(cache_name)) {
options("styler.cache_name" = cache_name)
} else {
options("styler.cache_name" = styler_version)
}
path <- cache_find_path(cache_name)
if (verbose) {
cat(
"Using cache ", cache_get_name(), " at ",
path, ".\n",
sep = ""
)
}
invisible(path)
}

#' @rdname cache_activate
#' @export
cache_deactivate <- function(verbose = TRUE) {
options("styler.cache_name" = NULL)

if (verbose) {
cat("Deactivated cache.\n")
}
}
File renamed without changes.
Loading