From 3a8057a2977bc8a0132a84ec7e97a830b9efe489 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 14 Jul 2021 14:48:25 +0200 Subject: [PATCH 01/29] remove already done todo --- R/print.R | 4 ---- 1 file changed, 4 deletions(-) diff --git a/R/print.R b/R/print.R index eec71fd..9eac7c3 100644 --- a/R/print.R +++ b/R/print.R @@ -45,10 +45,6 @@ ic_print <- function(loc, parent_ref, deparsed_expression = missing_arg(), value # We need to check what options are set to decide what to print - whether to include the context # or not. - # - # TODO: Shall icecream.include.context be reanamed to something like - # icecream.always.include.context? This may be misleading as context is printed when no - # expression is evaluated regardless of option value prefix <- getOption("icecream.prefix", "ic|") output <- if (!is.null(expression_string)) { if (getOption("icecream.always.include.context")) { From d0d606550b897473dca8905c730ea35618665a92 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 14 Jul 2021 16:10:10 +0200 Subject: [PATCH 02/29] add peeking --- R/peek.R | 33 +++++++++++++++++++++++++++++++++ R/print.R | 6 +----- R/zzz.R | 4 ++++ man/ic_peek.Rd | 41 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 5 deletions(-) create mode 100644 R/peek.R create mode 100644 man/ic_peek.Rd diff --git a/R/peek.R b/R/peek.R new file mode 100644 index 0000000..817b550 --- /dev/null +++ b/R/peek.R @@ -0,0 +1,33 @@ +#' Peek at value of expression +#' +#' This function is a proxy for calling peeking function. +#' +#' @param value The result of evaluating an expression inside the `ic()` function. +#' @param peeking_function The function used to peek at the value. Default value is set by the +#' "icecream.peeking.function" option. +#' @param max_lines Maximum number of lines printed. Default value is set by the +#' "icecream.max.lines" option. +#' +#' @details Default value of `icecream.peeking.function` is `str`. Suggested possible alternatives +#' are: +#' +#' * `print` +#' * `head` +#' * `summary` +#' * `tibble::glimpse` +#' +#' @return A string to be printed. +#' +#' @seealso [utils::str()] [base::print()] [utils::head()] [base::summary()] [tibble::glimpse()] +#' @keywords internal +#' @importFrom utils capture.output +ic_peek <- function(value, + peeking_function = getOption("icecream.peeking.function"), + max_lines = getOption("icecream.max.lines")) { + output <- capture.output(peeking_function(value)) + if (max_lines == 1) trimws(output) + else { + output <- trimws(output[1:min(length(output), max_lines - 1)]) + paste0(c("", output), collapse = "\n") + } +} \ No newline at end of file diff --git a/R/print.R b/R/print.R index 9eac7c3..c008010 100644 --- a/R/print.R +++ b/R/print.R @@ -35,11 +35,7 @@ ic_print <- function(loc, parent_ref, deparsed_expression = missing_arg(), value # Formatting result if (!is_missing(deparsed_expression)) { # We want to print a one-line summary for complex objects like lists and data frames. - # - # TODO: Taking the first line of output from `str()` is a quick way of getting this but it - # doesn't produce great output (try passing in a `lm()` object - ugly). It would be nice - # to fix this at some point. - str_res <- trimws(capture.output(str(value)))[[1]] + str_res <- ic_peek(value) expression_string <- glue("{{.var {deparsed_expression}}}: {str_res}") } diff --git a/R/zzz.R b/R/zzz.R index 4ef30b7..a5619a6 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -4,6 +4,8 @@ icecream.enabled = TRUE, icecream.prefix = "ic|", icecream.output.function = NULL, + icecream.peeking.function = str, + icecream.max.lines = 1, icecream.arg.to.string.function = NULL, icecream.always.include.context = FALSE ) @@ -15,6 +17,8 @@ icecream.enabled = NULL, icecream.prefix = NULL, icecream.output.function = NULL, + icecream.peeking.function = NULL, + icecream.max.lines = NULL, icecream.arg.to.string.function = NULL, icecream.always.include.context = NULL ) diff --git a/man/ic_peek.Rd b/man/ic_peek.Rd new file mode 100644 index 0000000..9132d95 --- /dev/null +++ b/man/ic_peek.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/peek.R +\name{ic_peek} +\alias{ic_peek} +\title{Peek at value of expression} +\usage{ +ic_peek( + value, + peeking_function = getOption("icecream.peeking.function"), + max_lines = 1 +) +} +\arguments{ +\item{value}{The result of evaluating an expression inside the \code{ic()} function.} + +\item{peeking_function}{The function used to peek at the value. Default value is set by the +"icecream.peeking.function" option.} + +\item{max_lines}{Maximum number of lines printed. Default value is set by the +"icecream.max.lines" option.} +} +\value{ +A string to be printed. +} +\description{ +This function is a proxy for calling peeking function. +} +\details{ +Default value of \code{icecream.peeking.function} is \code{str}. Suggested possible alternatives +are: +\itemize{ +\item \code{print} +\item \code{head} +\item \code{summary} +\item \code{tibble::glimpse} +} +} +\seealso{ +\code{\link[utils:str]{utils::str()}} \code{\link[base:print]{base::print()}} \code{\link[utils:head]{utils::head()}} \code{\link[base:summary]{base::summary()}} \code{\link[tibble:reexports]{tibble::glimpse()}} +} +\keyword{internal} From 5781bd2398c86cad92d2f9ffa8e462260725873d Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 14 Jul 2021 17:26:25 +0200 Subject: [PATCH 03/29] max lines is now about length of summary --- R/peek.R | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/R/peek.R b/R/peek.R index 817b550..5ad963e 100644 --- a/R/peek.R +++ b/R/peek.R @@ -25,9 +25,10 @@ ic_peek <- function(value, peeking_function = getOption("icecream.peeking.function"), max_lines = getOption("icecream.max.lines")) { output <- capture.output(peeking_function(value)) - if (max_lines == 1) trimws(output) + real_lines <- min(length(output), max_lines) + if (real_lines == 1) trimws(output[[1]]) else { - output <- trimws(output[1:min(length(output), max_lines - 1)]) + output <- trimws(output[1:real_lines]) paste0(c("", output), collapse = "\n") } } \ No newline at end of file From 17e06c0f5458dee591a9028a91b43f4fdf012480 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 14 Jul 2021 17:26:45 +0200 Subject: [PATCH 04/29] update readme --- README.Rmd | 28 ++++++++++++++++++++++++++++ README.md | 39 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/README.Rmd b/README.Rmd index b2efc9b..943d3ba 100644 --- a/README.Rmd +++ b/README.Rmd @@ -220,6 +220,34 @@ of the call is the only reason to call `ic()` on its own. options(icecream.always.include.context = old.ctx) ``` +### `icecream.peeking.function` and `icecream.max.lines` +These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that summarizes the object. Default value is `str`. `icecream.max.lines` determines maximum number of lines that the peek of an obejct occupies; defaults to 1. + +For more complex data you may want to use e.g. `head` function and 5 lines. + +```{r, include=FALSE} +old.fun <- getOption("icecream.peeking.function") +old.lines <- getOption("icecream.max.lines") +``` + +```{r, include=TRUE} +data(iris) + +ic(iris) # not too informative + +options(icecream.peeking.function = head, + icecream.max.lines = 5) + +ic(iris) +``` + +```{r, include=FALSE} +options(icecream.peeking.function = old.fun, + icecream.max.lines = old.lines) +``` + +Note that if `icecream.max.lines` is greater than 1 and summary of an object is longer than 1, the alert occupies one line more due to the header. + ### `icecream.output.function`, `icecream.arg.to.string.function` Not implemented yet. See the [configuration](https://github.com/gruns/icecream#configuration) section of the original project docs for details of what they will do. diff --git a/README.md b/README.md index fe679c2..afbb14d 100644 --- a/README.md +++ b/README.md @@ -207,6 +207,39 @@ When `ic()` is called with no arguments, the context is always printed because showing the location of the call is the only reason to call `ic()` on its own. +### `icecream.peeking.function` and `icecream.max.lines` + +These two options control how the result of evaluation of an expression +is printed. `icecream.peeking.function` indicates the function that +summarizes the object. Default value is `str`. `icecream.max.lines` +determines maximum number of lines that the peek of an obejct occupies; +defaults to 1. + +For more complex data you may want to use e.g. `head` function and 5 +lines. + +``` r +data(iris) + +ic(iris) # not too informative +#> ℹ ic| `iris`: 'data.frame': 150 obs. of 5 variables: + +options(icecream.peeking.function = head, + icecream.max.lines = 5) + +ic(iris) +#> ℹ ic| `iris`: +#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species +#> 1 5.1 3.5 1.4 0.2 setosa +#> 2 4.9 3.0 1.4 0.2 setosa +#> 3 4.7 3.2 1.3 0.2 setosa +#> 4 4.6 3.1 1.5 0.2 setosa +``` + +Note that if `icecream.max.lines` is greater than 1 and summary of an +object is longer than 1, the alert occupies one line more due to the +header. + ### `icecream.output.function`, `icecream.arg.to.string.function` Not implemented yet. See the @@ -215,8 +248,8 @@ of the original project docs for details of what they will do. ## TODO: - - Implement `ic.format()` (see +- Implement `ic.format()` (see [here](https://github.com/gruns/icecream#miscellaneous)). - - Implement `ic.output.function`. At the moment it uses +- Implement `ic.output.function`. At the moment it uses `cli::cli_alert_info()` - - Implement `ic.arg.to.string.function` +- Implement `ic.arg.to.string.function` From 2921151858b914602e66a1ceb88dae952094800d Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 14 Jul 2021 17:45:50 +0200 Subject: [PATCH 05/29] fix docs --- man/ic_peek.Rd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/ic_peek.Rd b/man/ic_peek.Rd index 9132d95..9a229f3 100644 --- a/man/ic_peek.Rd +++ b/man/ic_peek.Rd @@ -7,7 +7,7 @@ ic_peek( value, peeking_function = getOption("icecream.peeking.function"), - max_lines = 1 + max_lines = getOption("icecream.max.lines") ) } \arguments{ From ca85792a0dc022c4cafa26ba1e40d0d37aea44e1 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Thu, 15 Jul 2021 14:10:58 +0200 Subject: [PATCH 06/29] add autopeek function, set it as deafult peeking function --- NAMESPACE | 7 +++++ R/autopeek.R | 68 ++++++++++++++++++++++++++++++++++++++++++++++ R/peek.R | 10 ++++--- R/zzz.R | 2 +- man/ic_autopeek.Rd | 42 ++++++++++++++++++++++++++++ man/ic_peek.Rd | 8 ++++-- 6 files changed, 129 insertions(+), 8 deletions(-) create mode 100644 R/autopeek.R create mode 100644 man/ic_autopeek.Rd diff --git a/NAMESPACE b/NAMESPACE index dda605b..e66f085 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,10 +1,17 @@ # Generated by roxygen2: do not edit by hand export(ic) +export(ic_autopeek) +export(ic_autopeek.default) export(ic_disable) export(ic_enable) importFrom(cli,cli_alert_info) importFrom(glue,glue) +importFrom(pillar,obj_sum) +importFrom(purrr,detect_index) +importFrom(purrr,map2_chr) +importFrom(purrr,map_chr) +importFrom(purrr,map_int) importFrom(rlang,caller_env) importFrom(rlang,caller_fn) importFrom(rlang,enquo) diff --git a/R/autopeek.R b/R/autopeek.R new file mode 100644 index 0000000..e0822f7 --- /dev/null +++ b/R/autopeek.R @@ -0,0 +1,68 @@ +#' Get descriptive one-line summary of an object +#' +#' This function is created as a modification of [utils::str()] function. It is supposed to +#' create more compacted yet informative summary about an object. It's default value of +#' "icecream.peeking.function" +#' +#' @param x The object to be summarized. +#' @param ... Other algorithms passed to methods. +#' +#' @details This is a generic function. Default method simply calls `utils::str` function. +#' +#' @return A string to be printed. +#' +#' @seealso [utils::str()] [ic_peek()] +#' @export +ic_autopeek <- function(x, ...) UseMethod("ic_autopeek") + +#' @export +ic_autopeek.default <- str + +#' @importFrom glue glue +#' @importFrom purrr map2_chr map_chr map_int detect_index +#' @importFrom pillar obj_sum +ic_autopeek_list_or_data.frame <- function(x, + max_summary_length = 70, + ...) { + # names of columns or their index if it does not exist + col_name <- if (is.null(names(x))) seq_along(x) else ifelse(is.na(names(x)), + seq_along(x), + glue("'{names(x)}'")) + + # short type summary as in pillar package + type_summary <- map_chr(x, obj_sum) + + # combine name of column and type summary + col_summary <- map2_chr(col_name, type_summary, function(name, sum) glue("${name}: {sum}")) + + # get header of the summary + header <- ic_autopeek_header(x) + + # calculate how many columns summaries can fit into the console + index <- detect_index(cumsum(map_int(col_summary, nchar) + 2), + ~ . > max_summary_length - nchar(header)) + + # paste summary of all columns + summary <- paste0(if (index == 0) col_summary else c(col_summary[1:(index - 1)], "..."), + collapse = ", ") + + glue("{header}{summary}") +} + +#' @param max_summary_length Integer. Maximum length of string summarizing the +#' +#' @describeIn ic_autopeek Method for list +ic_autopeek.list <- ic_autopeek_list_or_data.frame + +#' @param max_summary_length Integer. Maximum length of string summarizing the +#' +#' @describeIn ic_autopeek Method for data.frame +ic_autopeek.data.frame <- ic_autopeek_list_or_data.frame + +ic_autopeek_header <- function(x, ...) UseMethod("ic_autopeek_header") + +ic_autopeek_header.default <- function(x, ...) glue("{class(x)[[1]]}: ") + +ic_autopeek_header.list <- function(x, ...) glue("{class(x)[[1]]} [{length(x)}]: ") + +ic_autopeek_header.data.frame <- function(x, ...) glue("{class(x)[[1]]} [{nrow(x)} x {ncol(x)}]: ") diff --git a/R/peek.R b/R/peek.R index 5ad963e..d3f3dc7 100644 --- a/R/peek.R +++ b/R/peek.R @@ -8,9 +8,10 @@ #' @param max_lines Maximum number of lines printed. Default value is set by the #' "icecream.max.lines" option. #' -#' @details Default value of `icecream.peeking.function` is `str`. Suggested possible alternatives -#' are: +#' @details Default value of `icecream.peeking.function` is `ic_autopeek`. Suggested possible +#' alternatives are: #' +#' * `utils::str` #' * `print` #' * `head` #' * `summary` @@ -18,7 +19,8 @@ #' #' @return A string to be printed. #' -#' @seealso [utils::str()] [base::print()] [utils::head()] [base::summary()] [tibble::glimpse()] +#' @seealso [ic_autopeek()] [utils::str()] [base::print()] [utils::head()] [base::summary()] +#' [tibble::glimpse()] #' @keywords internal #' @importFrom utils capture.output ic_peek <- function(value, @@ -31,4 +33,4 @@ ic_peek <- function(value, output <- trimws(output[1:real_lines]) paste0(c("", output), collapse = "\n") } -} \ No newline at end of file +} diff --git a/R/zzz.R b/R/zzz.R index a5619a6..70ce58e 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -4,7 +4,7 @@ icecream.enabled = TRUE, icecream.prefix = "ic|", icecream.output.function = NULL, - icecream.peeking.function = str, + icecream.peeking.function = ic_autopeek, icecream.max.lines = 1, icecream.arg.to.string.function = NULL, icecream.always.include.context = FALSE diff --git a/man/ic_autopeek.Rd b/man/ic_autopeek.Rd new file mode 100644 index 0000000..1d0d169 --- /dev/null +++ b/man/ic_autopeek.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/autopeek.R +\name{ic_autopeek} +\alias{ic_autopeek} +\alias{ic_autopeek.list} +\alias{ic_autopeek.data.frame} +\title{Get descriptive one-line summary of an object} +\usage{ +ic_autopeek(x, ...) + +\method{ic_autopeek}{list}(x, max_summary_length = 70, ...) + +\method{ic_autopeek}{data.frame}(x, max_summary_length = 70, ...) +} +\arguments{ +\item{x}{The object to be summarized.} + +\item{...}{Other algorithms passed to methods.} + +\item{max_summary_length}{Integer. Maximum length of string summarizing the} +} +\value{ +A string to be printed. +} +\description{ +This function is created as a modification of \code{\link[utils:str]{utils::str()}} function. It is supposed to +create more compacted yet informative summary about an object. It's default value of +"icecream.peeking.function" +} +\details{ +This is a generic function. Default method simply calls \code{utils::str} function. +} +\section{Methods (by class)}{ +\itemize{ +\item \code{list}: Method for list + +\item \code{data.frame}: Method for data.frame +}} + +\seealso{ +\code{\link[utils:str]{utils::str()}} \code{\link[=ic_peek]{ic_peek()}} +} diff --git a/man/ic_peek.Rd b/man/ic_peek.Rd index 9a229f3..050a3c4 100644 --- a/man/ic_peek.Rd +++ b/man/ic_peek.Rd @@ -26,9 +26,10 @@ A string to be printed. This function is a proxy for calling peeking function. } \details{ -Default value of \code{icecream.peeking.function} is \code{str}. Suggested possible alternatives -are: +Default value of \code{icecream.peeking.function} is \code{ic_autopeek}. Suggested possible +alternatives are: \itemize{ +\item \code{utils::str} \item \code{print} \item \code{head} \item \code{summary} @@ -36,6 +37,7 @@ are: } } \seealso{ -\code{\link[utils:str]{utils::str()}} \code{\link[base:print]{base::print()}} \code{\link[utils:head]{utils::head()}} \code{\link[base:summary]{base::summary()}} \code{\link[tibble:reexports]{tibble::glimpse()}} +\code{\link[=ic_autopeek]{ic_autopeek()}} \code{\link[utils:str]{utils::str()}} \code{\link[base:print]{base::print()}} \code{\link[utils:head]{utils::head()}} \code{\link[base:summary]{base::summary()}} +\code{\link[tibble:reexports]{tibble::glimpse()}} } \keyword{internal} From c2ef3d04ca0facc5225a85f7d30a3c66b59fa767 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Thu, 15 Jul 2021 14:24:30 +0200 Subject: [PATCH 07/29] missing imports --- DESCRIPTION | 2 ++ 1 file changed, 2 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index 3ab1f70..4432ed8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -23,6 +23,8 @@ BugReports: https://github.com/lewinfox/icecream/issues Imports: cli, glue, + pillar (>= 1.6.1), + purrr (>= 0.3.4), rlang Suggests: testthat (>= 3.0.0), From 7544cd39ebfcf0f1f590390a6d7b1b8e2cee3da9 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Thu, 15 Jul 2021 14:24:49 +0200 Subject: [PATCH 08/29] rename x to object for consistency with str, docs fix --- NAMESPACE | 1 - R/autopeek.R | 26 +++++++++++++------------- man/ic_autopeek.Rd | 8 ++++---- 3 files changed, 17 insertions(+), 18 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index e66f085..44de215 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,7 +2,6 @@ export(ic) export(ic_autopeek) -export(ic_autopeek.default) export(ic_disable) export(ic_enable) importFrom(cli,cli_alert_info) diff --git a/R/autopeek.R b/R/autopeek.R index e0822f7..fbf243f 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -4,7 +4,7 @@ #' create more compacted yet informative summary about an object. It's default value of #' "icecream.peeking.function" #' -#' @param x The object to be summarized. +#' @param object The object to be summarized. #' @param ... Other algorithms passed to methods. #' #' @details This is a generic function. Default method simply calls `utils::str` function. @@ -13,30 +13,30 @@ #' #' @seealso [utils::str()] [ic_peek()] #' @export -ic_autopeek <- function(x, ...) UseMethod("ic_autopeek") +ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") -#' @export ic_autopeek.default <- str #' @importFrom glue glue #' @importFrom purrr map2_chr map_chr map_int detect_index #' @importFrom pillar obj_sum -ic_autopeek_list_or_data.frame <- function(x, +ic_autopeek_list_or_data.frame <- function(object, max_summary_length = 70, ...) { # names of columns or their index if it does not exist - col_name <- if (is.null(names(x))) seq_along(x) else ifelse(is.na(names(x)), - seq_along(x), - glue("'{names(x)}'")) + col_name <- if (is.null(names(object))) seq_along(object) else ifelse( + is.na(names(object)), + seq_along(object), + glue("'{names(object)}'")) # short type summary as in pillar package - type_summary <- map_chr(x, obj_sum) + type_summary <- map_chr(object, obj_sum) # combine name of column and type summary col_summary <- map2_chr(col_name, type_summary, function(name, sum) glue("${name}: {sum}")) # get header of the summary - header <- ic_autopeek_header(x) + header <- ic_autopeek_header(object) # calculate how many columns summaries can fit into the console index <- detect_index(cumsum(map_int(col_summary, nchar) + 2), @@ -59,10 +59,10 @@ ic_autopeek.list <- ic_autopeek_list_or_data.frame #' @describeIn ic_autopeek Method for data.frame ic_autopeek.data.frame <- ic_autopeek_list_or_data.frame -ic_autopeek_header <- function(x, ...) UseMethod("ic_autopeek_header") +ic_autopeek_header <- function(object, ...) UseMethod("ic_autopeek_header") -ic_autopeek_header.default <- function(x, ...) glue("{class(x)[[1]]}: ") +ic_autopeek_header.default <- function(object, ...) glue("{class(object)[[1]]}: ") -ic_autopeek_header.list <- function(x, ...) glue("{class(x)[[1]]} [{length(x)}]: ") +ic_autopeek_header.list <- function(object, ...) glue("{class(object)[[1]]} [{length(object)}]: ") -ic_autopeek_header.data.frame <- function(x, ...) glue("{class(x)[[1]]} [{nrow(x)} x {ncol(x)}]: ") +ic_autopeek_header.data.frame <- function(object, ...) glue("{class(object)[[1]]} [{nrow(object)} x {ncol(object)}]: ") diff --git a/man/ic_autopeek.Rd b/man/ic_autopeek.Rd index 1d0d169..4e56703 100644 --- a/man/ic_autopeek.Rd +++ b/man/ic_autopeek.Rd @@ -6,14 +6,14 @@ \alias{ic_autopeek.data.frame} \title{Get descriptive one-line summary of an object} \usage{ -ic_autopeek(x, ...) +ic_autopeek(object, ...) -\method{ic_autopeek}{list}(x, max_summary_length = 70, ...) +\method{ic_autopeek}{list}(object, max_summary_length = 70, ...) -\method{ic_autopeek}{data.frame}(x, max_summary_length = 70, ...) +\method{ic_autopeek}{data.frame}(object, max_summary_length = 70, ...) } \arguments{ -\item{x}{The object to be summarized.} +\item{object}{The object to be summarized.} \item{...}{Other algorithms passed to methods.} From 29ab61ea1bb495e904d10784c3bf7f4bba0b82af Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Thu, 15 Jul 2021 14:28:24 +0200 Subject: [PATCH 09/29] update README --- README.Rmd | 4 ++-- README.md | 16 +++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.Rmd b/README.Rmd index 943d3ba..86a36f2 100644 --- a/README.Rmd +++ b/README.Rmd @@ -221,7 +221,7 @@ options(icecream.always.include.context = old.ctx) ``` ### `icecream.peeking.function` and `icecream.max.lines` -These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that summarizes the object. Default value is `str`. `icecream.max.lines` determines maximum number of lines that the peek of an obejct occupies; defaults to 1. +These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that summarizes the object. Default value is `ic_autopeek`, which works like `utils::str` for most of the time, but gives more informative output for `lists`, `data.frames` and their subclasses in a more compact way. `icecream.max.lines` determines maximum number of lines that the peek of an object occupies; defaults to 1. For more complex data you may want to use e.g. `head` function and 5 lines. @@ -233,7 +233,7 @@ old.lines <- getOption("icecream.max.lines") ```{r, include=TRUE} data(iris) -ic(iris) # not too informative +ic(iris) # we would like to see header of the data options(icecream.peeking.function = head, icecream.max.lines = 5) diff --git a/README.md b/README.md index afbb14d..157a507 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,10 @@ cluttering the terminal. ``` r df <- ic(iris) -#> ℹ ic| `iris`: 'data.frame': 150 obs. of 5 variables: +#> ℹ ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... my_list <- ic(list(a = 1, b = 3, c = 1:100)) -#> ℹ ic| `list(a = 1, b = 3, c = 1:100)`: List of 3 +#> ℹ ic| `list(a = 1, b = 3, c = 1:100)`: list [3]: $'a': dbl [1], $'b': dbl [1], $'c': int [100] ``` ## Inspect execution @@ -211,9 +211,11 @@ because showing the location of the call is the only reason to call These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that -summarizes the object. Default value is `str`. `icecream.max.lines` -determines maximum number of lines that the peek of an obejct occupies; -defaults to 1. +summarizes the object. Default value is `ic_autopeek`, which works like +`utils::str` for most of the time, but gives more informative output for +`lists`, `data.frames` and their subclasses in a more compact way. +`icecream.max.lines` determines maximum number of lines that the peek of +an object occupies; defaults to 1. For more complex data you may want to use e.g. `head` function and 5 lines. @@ -221,8 +223,8 @@ lines. ``` r data(iris) -ic(iris) # not too informative -#> ℹ ic| `iris`: 'data.frame': 150 obs. of 5 variables: +ic(iris) # we would like to see header of the data +#> ℹ ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... options(icecream.peeking.function = head, icecream.max.lines = 5) From caa17f2173aaea1090f7a116a9f8f83f44caead0 Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 17:04:43 +0200 Subject: [PATCH 10/29] add checkmate to use in tests --- DESCRIPTION | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DESCRIPTION b/DESCRIPTION index 3ab1f70..8890b4d 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,6 +21,7 @@ URL: https://lewinfox.github.io/icecream/, https://github.com/lewinfox/icecream BugReports: https://github.com/lewinfox/icecream/issues Imports: + checkmate (>= 2.0.0), cli, glue, rlang @@ -33,3 +34,5 @@ Language: en-GB LazyData: true Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.1 +Remotes: + mllg/checkmate From ce061aae1b8afe1f0032c5ec5d7b82c029302f3b Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 17:05:53 +0200 Subject: [PATCH 11/29] create a few tests for ic_autopeek --- tests/testthat/setup-lists.R | 13 ++++++++ tests/testthat/test-autopeek.R | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/testthat/setup-lists.R create mode 100644 tests/testthat/test-autopeek.R diff --git a/tests/testthat/setup-lists.R b/tests/testthat/setup-lists.R new file mode 100644 index 0000000..7d4b67f --- /dev/null +++ b/tests/testthat/setup-lists.R @@ -0,0 +1,13 @@ +unnamed_list <- list( + sample.int(70, size = 8), + sample(letters, size = 4), + logical() +) +partially_named_list <- setNames(unnamed_list, c("first", NA, "last")) +named_list <- setNames(unnamed_list, c("first", "2.", "last")) + +all_lists <- list( + unnamed_list, + partially_named_list, + named_list +) \ No newline at end of file diff --git a/tests/testthat/test-autopeek.R b/tests/testthat/test-autopeek.R new file mode 100644 index 0000000..a0dd555 --- /dev/null +++ b/tests/testthat/test-autopeek.R @@ -0,0 +1,59 @@ +library(checkmate) +library(glue) + +test_that("`ic_autopeek()` has specific format for lists", { + purrr::walk( + all_lists, + ~ expect_string( + ic_autopeek(.x), + pattern = "^list \\[\\d+\\]: (?:\\$[^:]+: \\S+ \\[\\d+\\](?:, )?)+(?:\\.{3})?$" + ) + ) +}) + +# header tests ---- +test_that("`ic_autopeek()` prints correct list length", { + expect_string( + ic_autopeek(unnamed_list), + pattern = glue("^list \\[{length(unnamed_list)}\\]:") + ) +}) + +# element names tests ---- +test_that("`ic_autopeek()` prints indices for unnamed lists", { + #> list [3]: $1: int [8], $2: chr [4], $3: lgl [0] + expect_string( + ic_autopeek(unnamed_list), + pattern = glue_collapse(glue("\\${seq_along(unnamed_list)}:.*")) + ) +}) + +test_that("`ic_autopeek()` prints names for named lists", { + #> list [3]: $'first': int [8], $'2.': chr [4], $'last': lgl [0] + expect_string( + ic_autopeek(named_list), + pattern = glue_collapse(glue("\\$'{names(named_list)}':.*")) + ) +}) + +test_that("`ic_autopeek()` mixes names and indices for partially named lists", { + #> list [3]: $'first': int [8], $2: chr [4], $'last': lgl [0] + list_names <- names(partially_named_list) + list_names[!is.na(list_names)] <- glue("'{list_names[!is.na(list_names)]}'") + list_names[is.na(list_names)] <- which(is.na(list_names)) + expect_string( + ic_autopeek(partially_named_list), + pattern = glue_collapse(glue("\\${list_names}:.*")) + ) +}) + +# element description tests ---- +test_that("`ic_autopeek()` displays element lengths", { + purrr::walk( + all_lists, + ~ expect_string( + ic_autopeek(.x), + pattern = glue_collapse(glue("\\S+ \\[{lengths(.x)}\\].*")) + ) + ) +}) From 2270d791cfb6f3ab112ad94102622d6c9bd6d7ee Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 17:49:36 +0200 Subject: [PATCH 12/29] fix truncated param description --- R/autopeek.R | 4 +--- man/ic_autopeek.Rd | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/R/autopeek.R b/R/autopeek.R index fbf243f..f800cfe 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -49,13 +49,11 @@ ic_autopeek_list_or_data.frame <- function(object, glue("{header}{summary}") } -#' @param max_summary_length Integer. Maximum length of string summarizing the +#' @param max_summary_length Integer. Maximum length of string summarizing the object. #' #' @describeIn ic_autopeek Method for list ic_autopeek.list <- ic_autopeek_list_or_data.frame -#' @param max_summary_length Integer. Maximum length of string summarizing the -#' #' @describeIn ic_autopeek Method for data.frame ic_autopeek.data.frame <- ic_autopeek_list_or_data.frame diff --git a/man/ic_autopeek.Rd b/man/ic_autopeek.Rd index 4e56703..66afa03 100644 --- a/man/ic_autopeek.Rd +++ b/man/ic_autopeek.Rd @@ -17,7 +17,7 @@ ic_autopeek(object, ...) \item{...}{Other algorithms passed to methods.} -\item{max_summary_length}{Integer. Maximum length of string summarizing the} +\item{max_summary_length}{Integer. Maximum length of string summarizing the object.} } \value{ A string to be printed. From 0878488493e26dfa68166687ef72f9c862042ea8 Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 18:08:42 +0200 Subject: [PATCH 13/29] add ic_autopeek tests --- tests/testthat/test-autopeek.R | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-autopeek.R b/tests/testthat/test-autopeek.R index a0dd555..348ba6d 100644 --- a/tests/testthat/test-autopeek.R +++ b/tests/testthat/test-autopeek.R @@ -48,12 +48,22 @@ test_that("`ic_autopeek()` mixes names and indices for partially named lists", { }) # element description tests ---- +test_that("`ic_autopeek()` contains vector abbreviations", { + purrr::walk( + all_lists, + ~ expect_string( + ic_autopeek(.x), + pattern = glue_collapse(glue("{purrr::map_chr(.x, vctrs::vec_ptype_abbr)}.*")) + ) + ) +}) + test_that("`ic_autopeek()` displays element lengths", { purrr::walk( all_lists, ~ expect_string( - ic_autopeek(.x), - pattern = glue_collapse(glue("\\S+ \\[{lengths(.x)}\\].*")) - ) + ic_autopeek(.x), + pattern = glue_collapse(glue("\\S+ \\[{lengths(.x)}\\].*")) + ) ) }) From 345554fc172bc1b93faf495e0493d938dbccea6a Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 19:12:01 +0200 Subject: [PATCH 14/29] add ic_autopeek truncation tests --- tests/testthat/setup-lists.R | 14 ++++++++----- tests/testthat/test-autopeek.R | 36 +++++++++++++++++++++++++++++----- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/tests/testthat/setup-lists.R b/tests/testthat/setup-lists.R index 7d4b67f..f796677 100644 --- a/tests/testthat/setup-lists.R +++ b/tests/testthat/setup-lists.R @@ -6,8 +6,12 @@ unnamed_list <- list( partially_named_list <- setNames(unnamed_list, c("first", NA, "last")) named_list <- setNames(unnamed_list, c("first", "2.", "last")) -all_lists <- list( - unnamed_list, - partially_named_list, - named_list -) \ No newline at end of file +long_list <- list( + c(TRUE, TRUE, FALSE), + sample.int(11, size = 3), + list(a = 1, b = 3:6), + seq_len(10), + LETTERS[19:11], + seq_len(4) +) +long_list_2 <- long_list[c(5, 2, 6, 1, 4, 3)] \ No newline at end of file diff --git a/tests/testthat/test-autopeek.R b/tests/testthat/test-autopeek.R index 348ba6d..cb0f719 100644 --- a/tests/testthat/test-autopeek.R +++ b/tests/testthat/test-autopeek.R @@ -3,10 +3,11 @@ library(glue) test_that("`ic_autopeek()` has specific format for lists", { purrr::walk( - all_lists, + list(unnamed_list, partially_named_list, named_list, long_list, + long_list_2), ~ expect_string( ic_autopeek(.x), - pattern = "^list \\[\\d+\\]: (?:\\$[^:]+: \\S+ \\[\\d+\\](?:, )?)+(?:\\.{3})?$" + pattern = "^list \\[\\d+\\]: (?:\\$[^:]+: .+ \\[\\d+\\](?:, )?)+(?:\\.{3})?$" ) ) }) @@ -50,7 +51,7 @@ test_that("`ic_autopeek()` mixes names and indices for partially named lists", { # element description tests ---- test_that("`ic_autopeek()` contains vector abbreviations", { purrr::walk( - all_lists, + list(unnamed_list, partially_named_list, named_list), ~ expect_string( ic_autopeek(.x), pattern = glue_collapse(glue("{purrr::map_chr(.x, vctrs::vec_ptype_abbr)}.*")) @@ -60,10 +61,35 @@ test_that("`ic_autopeek()` contains vector abbreviations", { test_that("`ic_autopeek()` displays element lengths", { purrr::walk( - all_lists, + list(unnamed_list, partially_named_list, named_list), ~ expect_string( ic_autopeek(.x), - pattern = glue_collapse(glue("\\S+ \\[{lengths(.x)}\\].*")) + pattern = glue_collapse(glue("\\[{lengths(.x)}\\].*")) + ) + ) +}) + +# max length tests ---- +test_that("`ic_autopeek()` truncates description with three dots", { + purrr::walk( + list(long_list, long_list_2), + ~ { + trunc_summary <- ic_autopeek(.x, max_summary_length = 70) + expect_string( + trunc_summary, + pattern = "\\.{3}$", + ) + expect_lte(nchar(trunc_summary), 70) + } + ) +}) + +test_that("`ic_autopeek()` doesn't truncate in the middle of a summary", { + purrr::walk( + list(long_list, long_list_2), + ~ expect_string( + ic_autopeek(.x, max_summary_length = 70), + pattern = "(?:\\$[^:]+: .+ \\[\\d+\\], )+\\.{3}$" ) ) }) From 9101648c6bf6f5f7745672c6a5bab81380bbede8 Mon Sep 17 00:00:00 2001 From: Laura Date: Thu, 15 Jul 2021 19:44:00 +0200 Subject: [PATCH 15/29] simplified test logic --- tests/testthat/test-autopeek.R | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tests/testthat/test-autopeek.R b/tests/testthat/test-autopeek.R index cb0f719..6c80f0f 100644 --- a/tests/testthat/test-autopeek.R +++ b/tests/testthat/test-autopeek.R @@ -39,9 +39,11 @@ test_that("`ic_autopeek()` prints names for named lists", { test_that("`ic_autopeek()` mixes names and indices for partially named lists", { #> list [3]: $'first': int [8], $2: chr [4], $'last': lgl [0] - list_names <- names(partially_named_list) - list_names[!is.na(list_names)] <- glue("'{list_names[!is.na(list_names)]}'") - list_names[is.na(list_names)] <- which(is.na(list_names)) + list_names <- ifelse( + is.na(names(partially_named_list)), + seq_along(partially_named_list), + glue("'{names(partially_named_list)}'") + ) expect_string( ic_autopeek(partially_named_list), pattern = glue_collapse(glue("\\${list_names}:.*")) From 1a653cf6bd9307dfe0b962b001b3cfa1778ce34a Mon Sep 17 00:00:00 2001 From: Laura Date: Fri, 16 Jul 2021 22:52:46 +0200 Subject: [PATCH 16/29] fix case of the first element not fitting in supposed space --- NAMESPACE | 1 + R/autopeek.R | 10 ++++++---- .../{test-autopeek.R => test-autopeek-lists.R} | 0 3 files changed, 7 insertions(+), 4 deletions(-) rename tests/testthat/{test-autopeek.R => test-autopeek-lists.R} (100%) diff --git a/NAMESPACE b/NAMESPACE index 44de215..c441da8 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,6 +6,7 @@ export(ic_disable) export(ic_enable) importFrom(cli,cli_alert_info) importFrom(glue,glue) +importFrom(glue,glue_collapse) importFrom(pillar,obj_sum) importFrom(purrr,detect_index) importFrom(purrr,map2_chr) diff --git a/R/autopeek.R b/R/autopeek.R index f800cfe..770bd6f 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -17,7 +17,7 @@ ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") ic_autopeek.default <- str -#' @importFrom glue glue +#' @importFrom glue glue glue_collapse #' @importFrom purrr map2_chr map_chr map_int detect_index #' @importFrom pillar obj_sum ic_autopeek_list_or_data.frame <- function(object, @@ -40,11 +40,13 @@ ic_autopeek_list_or_data.frame <- function(object, # calculate how many columns summaries can fit into the console index <- detect_index(cumsum(map_int(col_summary, nchar) + 2), - ~ . > max_summary_length - nchar(header)) + ~ . > max_summary_length - nchar(header) - 3) # paste summary of all columns - summary <- paste0(if (index == 0) col_summary else c(col_summary[1:(index - 1)], "..."), - collapse = ", ") + summary <- glue_collapse( + if (index == 0) col_summary else c(col_summary[seq_len(index - 1)], "..."), + sep = ", " + ) glue("{header}{summary}") } diff --git a/tests/testthat/test-autopeek.R b/tests/testthat/test-autopeek-lists.R similarity index 100% rename from tests/testthat/test-autopeek.R rename to tests/testthat/test-autopeek-lists.R From b0fff1d83035ac831bec2ec95513cf972337048a Mon Sep 17 00:00:00 2001 From: Laura Date: Fri, 16 Jul 2021 23:04:34 +0200 Subject: [PATCH 17/29] add test to cover fixed case --- tests/testthat/test-autopeek-lists.R | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tests/testthat/test-autopeek-lists.R b/tests/testthat/test-autopeek-lists.R index 6c80f0f..30dd15c 100644 --- a/tests/testthat/test-autopeek-lists.R +++ b/tests/testthat/test-autopeek-lists.R @@ -95,3 +95,13 @@ test_that("`ic_autopeek()` doesn't truncate in the middle of a summary", { ) ) }) + +test_that("`ic_autopeek()` prints only header and '...' when the first element has too wide description already", { + purrr::walk( + list(long_list, long_list_2), + ~ expect_string( + ic_autopeek(.x, max_summary_length = 10), + fixed = glue("list [{length(.x)}]: ...") + ) + ) +}) From 7fc9e8cfbb4abde8a82bd3f9765f6620c4e17d41 Mon Sep 17 00:00:00 2001 From: Laura Date: Sat, 17 Jul 2021 10:45:36 +0200 Subject: [PATCH 18/29] use glue vectorization and specialized functions --- R/autopeek.R | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/R/autopeek.R b/R/autopeek.R index 770bd6f..b15d399 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -17,7 +17,7 @@ ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") ic_autopeek.default <- str -#' @importFrom glue glue glue_collapse +#' @importFrom glue glue glue_collapse single_quote #' @importFrom purrr map2_chr map_chr map_int detect_index #' @importFrom pillar obj_sum ic_autopeek_list_or_data.frame <- function(object, @@ -27,13 +27,13 @@ ic_autopeek_list_or_data.frame <- function(object, col_name <- if (is.null(names(object))) seq_along(object) else ifelse( is.na(names(object)), seq_along(object), - glue("'{names(object)}'")) + single_quote(names(object))) # short type summary as in pillar package type_summary <- map_chr(object, obj_sum) # combine name of column and type summary - col_summary <- map2_chr(col_name, type_summary, function(name, sum) glue("${name}: {sum}")) + col_summary <- glue("${col_name}: {type_summary}") # get header of the summary header <- ic_autopeek_header(object) From 730d9622f58819b9fda5bbe5ac834edf235cffd7 Mon Sep 17 00:00:00 2001 From: Laura Date: Sat, 17 Jul 2021 10:50:07 +0200 Subject: [PATCH 19/29] glue vectorization doesn't work when summary is 0-length vector --- R/autopeek.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/autopeek.R b/R/autopeek.R index b15d399..fde5765 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -48,7 +48,7 @@ ic_autopeek_list_or_data.frame <- function(object, sep = ", " ) - glue("{header}{summary}") + paste0(header, summary) } #' @param max_summary_length Integer. Maximum length of string summarizing the object. From 5e1bd1c9b6617c86fc021a27d2f459ef208d3711 Mon Sep 17 00:00:00 2001 From: Laura Date: Sat, 17 Jul 2021 10:57:14 +0200 Subject: [PATCH 20/29] move checkmate to Suggests --- DESCRIPTION | 4 +--- NAMESPACE | 1 + 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 87cfb2d..c92feb2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -21,13 +21,13 @@ URL: https://lewinfox.github.io/icecream/, https://github.com/lewinfox/icecream BugReports: https://github.com/lewinfox/icecream/issues Imports: - checkmate (>= 2.0.0), cli, glue, pillar (>= 1.6.1), purrr (>= 0.3.4), rlang Suggests: + checkmate (>= 2.0.0), testthat (>= 3.0.0), withr Config/testthat/edition: 3 @@ -36,5 +36,3 @@ Language: en-GB LazyData: true Roxygen: list(markdown = TRUE) RoxygenNote: 7.1.1 -Remotes: - mllg/checkmate diff --git a/NAMESPACE b/NAMESPACE index c441da8..3e95941 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -7,6 +7,7 @@ export(ic_enable) importFrom(cli,cli_alert_info) importFrom(glue,glue) importFrom(glue,glue_collapse) +importFrom(glue,single_quote) importFrom(pillar,obj_sum) importFrom(purrr,detect_index) importFrom(purrr,map2_chr) From 76e980a227150f7018608aa76a292b9b15597886 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 13:42:57 +0200 Subject: [PATCH 21/29] changes in docs, reorganize data.frames and lists --- R/autopeek.R | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/R/autopeek.R b/R/autopeek.R index fde5765..60eb540 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -5,24 +5,29 @@ #' "icecream.peeking.function" #' #' @param object The object to be summarized. -#' @param ... Other algorithms passed to methods. +#' @param ... Other arguments passed to methods. #' #' @details This is a generic function. Default method simply calls `utils::str` function. #' #' @return A string to be printed. #' #' @seealso [utils::str()] [ic_peek()] -#' @export ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") +#' @export ic_autopeek.default <- str +#' @param max_summary_length Integer. Maximum length of string summarizing the object. +#' +#' @describeIn ic_autopeek Method for list +#' #' @importFrom glue glue glue_collapse single_quote #' @importFrom purrr map2_chr map_chr map_int detect_index #' @importFrom pillar obj_sum -ic_autopeek_list_or_data.frame <- function(object, - max_summary_length = 70, - ...) { +#' @export +ic_autopeek.list <- function(object, + max_summary_length = 70, + ...) { # names of columns or their index if it does not exist col_name <- if (is.null(names(object))) seq_along(object) else ifelse( is.na(names(object)), @@ -51,18 +56,28 @@ ic_autopeek_list_or_data.frame <- function(object, paste0(header, summary) } -#' @param max_summary_length Integer. Maximum length of string summarizing the object. -#' #' @describeIn ic_autopeek Method for list -ic_autopeek.list <- ic_autopeek_list_or_data.frame - -#' @describeIn ic_autopeek Method for data.frame -ic_autopeek.data.frame <- ic_autopeek_list_or_data.frame +#' @export +ic_autopeek.data.frame <- ic_autopeek.list +#' Get a header of the object peeked at +#' +#' @param object The object peeked at. +#' @param ... Other arguments passed to methods. +#' +#' @details This function is used by `ic_autopeek` to get a header of the summary of a object. +#' It should return object's top-level class name and its dimension. +#' ic_autopeek_header <- function(object, ...) UseMethod("ic_autopeek_header") +#' @importFrom glue glue +#' @export ic_autopeek_header.default <- function(object, ...) glue("{class(object)[[1]]}: ") +#' @importFrom glue glue +#' @export ic_autopeek_header.list <- function(object, ...) glue("{class(object)[[1]]} [{length(object)}]: ") +#' @importFrom glue glue +#' @export ic_autopeek_header.data.frame <- function(object, ...) glue("{class(object)[[1]]} [{nrow(object)} x {ncol(object)}]: ") From bb2a2b17bba4d64ba3e7bea9a37fcd909d95911b Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 13:43:07 +0200 Subject: [PATCH 22/29] options docs --- R/icecream-package.R | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/R/icecream-package.R b/R/icecream-package.R index 6a9ffb5..08cd96d 100644 --- a/R/icecream-package.R +++ b/R/icecream-package.R @@ -14,6 +14,11 @@ #' complicated debugging but produces a lot of output so is disabled by default. When `ic()` is #' called with no arguments, the context is always printed because showing the location of the #' call is the only reason to call `ic()` on its own. +#' * `icecream.peeking.function`: indicates the function that summarizes the object. Default value +#' is `ic_autopeek`, which works like `utils::str` for most of the time, but gives more +#' informative output for `lists`, `data.frames` and their subclasses in a more compact way. +#' * `icecream.max.lines` Integer. Determines maximum number of lines that the peek of an object +#' occupies; defaults to 1. #' * `icecream.output.function`: Not implemented yet. See the #' [configuration](https://github.com/gruns/icecream#configuration) section of the original #' project docs for details of what it will do. From a1430f1eafb01a302db5b0249c3560e5c2dde46d Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 13:51:40 +0200 Subject: [PATCH 23/29] rebuild docs --- NAMESPACE | 7 ++++++- R/autopeek.R | 2 +- man/ic_autopeek.Rd | 2 +- man/ic_autopeek_header.Rd | 20 ++++++++++++++++++++ man/icecream.Rd | 5 +++++ 5 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 man/ic_autopeek_header.Rd diff --git a/NAMESPACE b/NAMESPACE index 3e95941..bade18d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,7 +1,12 @@ # Generated by roxygen2: do not edit by hand +S3method(ic_autopeek,data.frame) +S3method(ic_autopeek,list) +S3method(ic_autopeek_header,data.frame) +S3method(ic_autopeek_header,default) +S3method(ic_autopeek_header,list) export(ic) -export(ic_autopeek) +export(ic_autopeek.default) export(ic_disable) export(ic_enable) importFrom(cli,cli_alert_info) diff --git a/R/autopeek.R b/R/autopeek.R index 60eb540..5c4db01 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -56,7 +56,7 @@ ic_autopeek.list <- function(object, paste0(header, summary) } -#' @describeIn ic_autopeek Method for list +#' @describeIn ic_autopeek Method for data.frame #' @export ic_autopeek.data.frame <- ic_autopeek.list diff --git a/man/ic_autopeek.Rd b/man/ic_autopeek.Rd index 66afa03..83c852f 100644 --- a/man/ic_autopeek.Rd +++ b/man/ic_autopeek.Rd @@ -15,7 +15,7 @@ ic_autopeek(object, ...) \arguments{ \item{object}{The object to be summarized.} -\item{...}{Other algorithms passed to methods.} +\item{...}{Other arguments passed to methods.} \item{max_summary_length}{Integer. Maximum length of string summarizing the object.} } diff --git a/man/ic_autopeek_header.Rd b/man/ic_autopeek_header.Rd new file mode 100644 index 0000000..a440d56 --- /dev/null +++ b/man/ic_autopeek_header.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/autopeek.R +\name{ic_autopeek_header} +\alias{ic_autopeek_header} +\title{Get a header of the object peeked at} +\usage{ +ic_autopeek_header(object, ...) +} +\arguments{ +\item{object}{The object peeked at.} + +\item{...}{Other arguments passed to methods.} +} +\description{ +Get a header of the object peeked at +} +\details{ +This function is used by \code{ic_autopeek} to get a header of the summary of a object. +It should return object's top-level class name and its dimension. +} diff --git a/man/icecream.Rd b/man/icecream.Rd index 5577b6c..4314f3b 100644 --- a/man/icecream.Rd +++ b/man/icecream.Rd @@ -20,6 +20,11 @@ or environment will be printed along with the expression and value. This can be complicated debugging but produces a lot of output so is disabled by default. When \code{ic()} is called with no arguments, the context is always printed because showing the location of the call is the only reason to call \code{ic()} on its own. +\item \code{icecream.peeking.function}: indicates the function that summarizes the object. Default value +is \code{ic_autopeek}, which works like \code{utils::str} for most of the time, but gives more +informative output for \code{lists}, \code{data.frames} and their subclasses in a more compact way. +\item \code{icecream.max.lines} Integer. Determines maximum number of lines that the peek of an object +occupies; defaults to 1. \item \code{icecream.output.function}: Not implemented yet. See the \href{https://github.com/gruns/icecream#configuration}{configuration} section of the original project docs for details of what it will do. From 3834051531e50ad474234a0938b501d0dbbf229d Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 13:53:27 +0200 Subject: [PATCH 24/29] restylize code --- R/autopeek.R | 19 +++++++++++++------ R/ic.R | 3 +-- R/peek.R | 5 +++-- R/print.R | 8 ++++++-- tests/testthat/test-autopeek-lists.R | 6 ++++-- tests/testthat/test-icecream.R | 5 ++++- 6 files changed, 31 insertions(+), 15 deletions(-) diff --git a/R/autopeek.R b/R/autopeek.R index 5c4db01..aa40ec8 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -29,10 +29,15 @@ ic_autopeek.list <- function(object, max_summary_length = 70, ...) { # names of columns or their index if it does not exist - col_name <- if (is.null(names(object))) seq_along(object) else ifelse( - is.na(names(object)), - seq_along(object), - single_quote(names(object))) + col_name <- if (is.null(names(object))) { + seq_along(object) + } else { + ifelse( + is.na(names(object)), + seq_along(object), + single_quote(names(object)) + ) + } # short type summary as in pillar package type_summary <- map_chr(object, obj_sum) @@ -44,8 +49,10 @@ ic_autopeek.list <- function(object, header <- ic_autopeek_header(object) # calculate how many columns summaries can fit into the console - index <- detect_index(cumsum(map_int(col_summary, nchar) + 2), - ~ . > max_summary_length - nchar(header) - 3) + index <- detect_index( + cumsum(map_int(col_summary, nchar) + 2), + ~ . > max_summary_length - nchar(header) - 3 + ) # paste summary of all columns summary <- glue_collapse( diff --git a/R/ic.R b/R/ic.R index 54addea..4d3bdf0 100644 --- a/R/ic.R +++ b/R/ic.R @@ -11,7 +11,6 @@ #' ic(f(1)) #' #' ic(f(-1)) -#' #' @importFrom rlang enquo quo_is_missing trace_back quo_get_expr caller_fn caller_env expr_deparse eval_tidy fn_env env_label maybe_missing #' @importFrom glue glue #' @export @@ -27,7 +26,7 @@ ic <- function(x) { trace <- trace_back() num_calls <- length(trace$calls) - parent_ref <- if (num_calls > 1) trace$calls[[num_calls - 1]][[1]] else NULL + parent_ref <- if (num_calls > 1) trace$calls[[num_calls - 1]][[1]] else NULL ref <- attr(trace$calls[[num_calls]], "srcref") loc <- src_loc(ref) diff --git a/R/peek.R b/R/peek.R index d3f3dc7..342e965 100644 --- a/R/peek.R +++ b/R/peek.R @@ -28,8 +28,9 @@ ic_peek <- function(value, max_lines = getOption("icecream.max.lines")) { output <- capture.output(peeking_function(value)) real_lines <- min(length(output), max_lines) - if (real_lines == 1) trimws(output[[1]]) - else { + if (real_lines == 1) { + trimws(output[[1]]) + } else { output <- trimws(output[1:real_lines]) paste0(c("", output), collapse = "\n") } diff --git a/R/print.R b/R/print.R index c008010..30fdcf4 100644 --- a/R/print.R +++ b/R/print.R @@ -45,8 +45,12 @@ ic_print <- function(loc, parent_ref, deparsed_expression = missing_arg(), value output <- if (!is.null(expression_string)) { if (getOption("icecream.always.include.context")) { glue("{context_string} | {expression_string}") - } else expression_string - } else context_string + } else { + expression_string + } + } else { + context_string + } output <- paste(prefix, output) cli_alert_info(output) diff --git a/tests/testthat/test-autopeek-lists.R b/tests/testthat/test-autopeek-lists.R index 30dd15c..f56ee8c 100644 --- a/tests/testthat/test-autopeek-lists.R +++ b/tests/testthat/test-autopeek-lists.R @@ -3,8 +3,10 @@ library(glue) test_that("`ic_autopeek()` has specific format for lists", { purrr::walk( - list(unnamed_list, partially_named_list, named_list, long_list, - long_list_2), + list( + unnamed_list, partially_named_list, named_list, long_list, + long_list_2 + ), ~ expect_string( ic_autopeek(.x), pattern = "^list \\[\\d+\\]: (?:\\$[^:]+: .+ \\[\\d+\\](?:, )?)+(?:\\.{3})?$" diff --git a/tests/testthat/test-icecream.R b/tests/testthat/test-icecream.R index aa565f1..a781d10 100644 --- a/tests/testthat/test-icecream.R +++ b/tests/testthat/test-icecream.R @@ -52,7 +52,10 @@ test_that("setting prefixes works", { test_that("function environment is correctly identified", { - f <- function() {ic(); 1} + f <- function() { + ic() + 1 + } # Remove the srcref to ensure we fall back on the environment f <- utils::removeSource(f) From 073d2be7b0f74033ecc1dfec73996f690e94b120 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 14:00:55 +0200 Subject: [PATCH 25/29] wrap README to 100 chars --- README.Rmd | 7 +++++-- README.md | 24 ++++++++++++------------ man/ic.Rd | 1 - 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.Rmd b/README.Rmd index 86a36f2..b3a6b93 100644 --- a/README.Rmd +++ b/README.Rmd @@ -221,7 +221,9 @@ options(icecream.always.include.context = old.ctx) ``` ### `icecream.peeking.function` and `icecream.max.lines` -These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that summarizes the object. Default value is `ic_autopeek`, which works like `utils::str` for most of the time, but gives more informative output for `lists`, `data.frames` and their subclasses in a more compact way. `icecream.max.lines` determines maximum number of lines that the peek of an object occupies; defaults to 1. +These two options control how the result of evaluation of an expression is printed. `icecream.peeking.function` indicates the function that summarizes the object. Default value is `ic_autopeek`, which works like `utils::str` for most of the time, but gives more informative output +for `lists`, `data.frames` and their subclasses in a more compact way. `icecream.max.lines` +determines maximum number of lines that the peek of an object occupies; defaults to 1. For more complex data you may want to use e.g. `head` function and 5 lines. @@ -246,7 +248,8 @@ options(icecream.peeking.function = old.fun, icecream.max.lines = old.lines) ``` -Note that if `icecream.max.lines` is greater than 1 and summary of an object is longer than 1, the alert occupies one line more due to the header. +Note that if `icecream.max.lines` is greater than 1 and summary of an object is longer than 1, the +alert occupies one line more due to the header. ### `icecream.output.function`, `icecream.arg.to.string.function` Not implemented yet. See the [configuration](https://github.com/gruns/icecream#configuration) diff --git a/README.md b/README.md index 157a507..d886e1d 100644 --- a/README.md +++ b/README.md @@ -44,10 +44,10 @@ library(icecream) is_negative <- function(x) x < 0 ic(is_negative(1)) -#> ℹ ic| `is_negative(1)`: logi FALSE +#> i ic| `is_negative(1)`: logi FALSE ic(is_negative(-1)) -#> ℹ ic| `is_negative(-1)`: logi TRUE +#> i ic| `is_negative(-1)`: logi TRUE ``` You’re more likely to want to do this within a function: @@ -60,11 +60,11 @@ some_function <- function(x) { } some_function(1) -#> ℹ ic| `intermediate_value / 2`: num 5 +#> i ic| `intermediate_value / 2`: num 5 #> [1] 5 some_function(10) -#> ℹ ic| `intermediate_value / 2`: num 50 +#> i ic| `intermediate_value / 2`: num 50 #> [1] 50 ``` @@ -73,10 +73,10 @@ cluttering the terminal. ``` r df <- ic(iris) -#> ℹ ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... +#> i ic| `iris`: [1] "data.frame [150 x 5]: $'Sepal.Length': dbl [150], ..." my_list <- ic(list(a = 1, b = 3, c = 1:100)) -#> ℹ ic| `list(a = 1, b = 3, c = 1:100)`: list [3]: $'a': dbl [1], $'b': dbl [1], $'c': int [100] +#> i ic| `list(a = 1, b = 3, c = 1:100)`: [1] "list [3]: $'a': dbl [1], $'b': dbl [1], $'c': int [100]" ``` ## Inspect execution @@ -150,7 +150,7 @@ evaluating its input but will not print anything. ic_enable() # This is TRUE by default ic(mean(1:100)) -#> ℹ ic| `mean(1:100)`: num 50.5 +#> i ic| `mean(1:100)`: num 50.5 ic_disable() @@ -174,15 +174,15 @@ This is printed at the beginning of every line. Defaults to `"ic|"`. ``` r ic(mean(1:5)) -#> ℹ ic| `mean(1:5)`: num 3 +#> i ic| `mean(1:5)`: num 3 options(icecream.prefix = "DEBUG:") ic(mean(1:5)) -#> ℹ DEBUG: `mean(1:5)`: num 3 +#> i DEBUG: `mean(1:5)`: num 3 options(icecream.prefix = "\U1F366") ic(mean(1:5)) -#> ℹ 🍦 `mean(1:5)`: num 3 +#> i 🍦 `mean(1:5)`: num 3 ``` ### `icecream.always.include.context` @@ -224,13 +224,13 @@ lines. data(iris) ic(iris) # we would like to see header of the data -#> ℹ ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... +#> i ic| `iris`: [1] "data.frame [150 x 5]: $'Sepal.Length': dbl [150], ..." options(icecream.peeking.function = head, icecream.max.lines = 5) ic(iris) -#> ℹ ic| `iris`: +#> i ic| `iris`: #> Sepal.Length Sepal.Width Petal.Length Petal.Width Species #> 1 5.1 3.5 1.4 0.2 setosa #> 2 4.9 3.0 1.4 0.2 setosa diff --git a/man/ic.Rd b/man/ic.Rd index 62f4874..ce3e597 100644 --- a/man/ic.Rd +++ b/man/ic.Rd @@ -22,5 +22,4 @@ f <- function(x) x < 0 ic(f(1)) ic(f(-1)) - } From 91552794185301f4fc10ecd34a28320a70e7b1e2 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 14:34:41 +0200 Subject: [PATCH 26/29] cat the result of peeking instead of returning it directly --- R/autopeek.R | 7 +++++-- man/ic_autopeek.Rd | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/R/autopeek.R b/R/autopeek.R index aa40ec8..5383f71 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -9,7 +9,8 @@ #' #' @details This is a generic function. Default method simply calls `utils::str` function. #' -#' @return A string to be printed. +#' @return The function is mainly used for its side effects -- outputting to the terminal. +#' However, it also returns an invisible string of the printed summary. #' #' @seealso [utils::str()] [ic_peek()] ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") @@ -60,7 +61,9 @@ ic_autopeek.list <- function(object, sep = ", " ) - paste0(header, summary) + ret <- paste0(header, summary) + cat(ret) + invisible(ret) } #' @describeIn ic_autopeek Method for data.frame diff --git a/man/ic_autopeek.Rd b/man/ic_autopeek.Rd index 83c852f..b663afe 100644 --- a/man/ic_autopeek.Rd +++ b/man/ic_autopeek.Rd @@ -20,7 +20,8 @@ ic_autopeek(object, ...) \item{max_summary_length}{Integer. Maximum length of string summarizing the object.} } \value{ -A string to be printed. +The function is mainly used for its side effects -- outputting to the terminal. +However, it also returns an invisible string of the printed summary. } \description{ This function is created as a modification of \code{\link[utils:str]{utils::str()}} function. It is supposed to From ce02487ad666f2335ee94937a9be800796fca13a Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 14:34:58 +0200 Subject: [PATCH 27/29] update tests to match autopeek interface --- tests/testthat/test-autopeek-lists.R | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/testthat/test-autopeek-lists.R b/tests/testthat/test-autopeek-lists.R index f56ee8c..e180619 100644 --- a/tests/testthat/test-autopeek-lists.R +++ b/tests/testthat/test-autopeek-lists.R @@ -7,7 +7,7 @@ test_that("`ic_autopeek()` has specific format for lists", { unnamed_list, partially_named_list, named_list, long_list, long_list_2 ), - ~ expect_string( + ~ expect_output( ic_autopeek(.x), pattern = "^list \\[\\d+\\]: (?:\\$[^:]+: .+ \\[\\d+\\](?:, )?)+(?:\\.{3})?$" ) @@ -16,7 +16,7 @@ test_that("`ic_autopeek()` has specific format for lists", { # header tests ---- test_that("`ic_autopeek()` prints correct list length", { - expect_string( + expect_output( ic_autopeek(unnamed_list), pattern = glue("^list \\[{length(unnamed_list)}\\]:") ) @@ -25,7 +25,7 @@ test_that("`ic_autopeek()` prints correct list length", { # element names tests ---- test_that("`ic_autopeek()` prints indices for unnamed lists", { #> list [3]: $1: int [8], $2: chr [4], $3: lgl [0] - expect_string( + expect_output( ic_autopeek(unnamed_list), pattern = glue_collapse(glue("\\${seq_along(unnamed_list)}:.*")) ) @@ -33,7 +33,7 @@ test_that("`ic_autopeek()` prints indices for unnamed lists", { test_that("`ic_autopeek()` prints names for named lists", { #> list [3]: $'first': int [8], $'2.': chr [4], $'last': lgl [0] - expect_string( + expect_output( ic_autopeek(named_list), pattern = glue_collapse(glue("\\$'{names(named_list)}':.*")) ) @@ -46,7 +46,7 @@ test_that("`ic_autopeek()` mixes names and indices for partially named lists", { seq_along(partially_named_list), glue("'{names(partially_named_list)}'") ) - expect_string( + expect_output( ic_autopeek(partially_named_list), pattern = glue_collapse(glue("\\${list_names}:.*")) ) @@ -56,7 +56,7 @@ test_that("`ic_autopeek()` mixes names and indices for partially named lists", { test_that("`ic_autopeek()` contains vector abbreviations", { purrr::walk( list(unnamed_list, partially_named_list, named_list), - ~ expect_string( + ~ expect_output( ic_autopeek(.x), pattern = glue_collapse(glue("{purrr::map_chr(.x, vctrs::vec_ptype_abbr)}.*")) ) @@ -66,7 +66,7 @@ test_that("`ic_autopeek()` contains vector abbreviations", { test_that("`ic_autopeek()` displays element lengths", { purrr::walk( list(unnamed_list, partially_named_list, named_list), - ~ expect_string( + ~ expect_output( ic_autopeek(.x), pattern = glue_collapse(glue("\\[{lengths(.x)}\\].*")) ) @@ -78,7 +78,7 @@ test_that("`ic_autopeek()` truncates description with three dots", { purrr::walk( list(long_list, long_list_2), ~ { - trunc_summary <- ic_autopeek(.x, max_summary_length = 70) + trunc_summary <- capture.output(ic_autopeek(.x, max_summary_length = 70)) expect_string( trunc_summary, pattern = "\\.{3}$", @@ -91,7 +91,7 @@ test_that("`ic_autopeek()` truncates description with three dots", { test_that("`ic_autopeek()` doesn't truncate in the middle of a summary", { purrr::walk( list(long_list, long_list_2), - ~ expect_string( + ~ expect_output( ic_autopeek(.x, max_summary_length = 70), pattern = "(?:\\$[^:]+: .+ \\[\\d+\\], )+\\.{3}$" ) @@ -101,7 +101,7 @@ test_that("`ic_autopeek()` doesn't truncate in the middle of a summary", { test_that("`ic_autopeek()` prints only header and '...' when the first element has too wide description already", { purrr::walk( list(long_list, long_list_2), - ~ expect_string( + ~ expect_output( ic_autopeek(.x, max_summary_length = 10), fixed = glue("list [{length(.x)}]: ...") ) From a5d9b725f460e5c52230e7bd49640ce7a2fd0365 Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Wed, 21 Jul 2021 14:39:33 +0200 Subject: [PATCH 28/29] reknit README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index d886e1d..f7fa099 100644 --- a/README.md +++ b/README.md @@ -73,10 +73,10 @@ cluttering the terminal. ``` r df <- ic(iris) -#> i ic| `iris`: [1] "data.frame [150 x 5]: $'Sepal.Length': dbl [150], ..." +#> i ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... my_list <- ic(list(a = 1, b = 3, c = 1:100)) -#> i ic| `list(a = 1, b = 3, c = 1:100)`: [1] "list [3]: $'a': dbl [1], $'b': dbl [1], $'c': int [100]" +#> i ic| `list(a = 1, b = 3, c = 1:100)`: list [3]: $'a': dbl [1], $'b': dbl [1], $'c': int [100] ``` ## Inspect execution @@ -224,7 +224,7 @@ lines. data(iris) ic(iris) # we would like to see header of the data -#> i ic| `iris`: [1] "data.frame [150 x 5]: $'Sepal.Length': dbl [150], ..." +#> i ic| `iris`: data.frame [150 x 5]: $'Sepal.Length': dbl [150], ... options(icecream.peeking.function = head, icecream.max.lines = 5) From f30dc0956613cf6a043934c413ffb513417e087a Mon Sep 17 00:00:00 2001 From: DominikRafacz Date: Fri, 23 Jul 2021 14:11:02 +0200 Subject: [PATCH 29/29] export ic_autopeek.default --- NAMESPACE | 2 +- R/autopeek.R | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index bade18d..660a42c 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,12 +1,12 @@ # Generated by roxygen2: do not edit by hand S3method(ic_autopeek,data.frame) +S3method(ic_autopeek,default) S3method(ic_autopeek,list) S3method(ic_autopeek_header,data.frame) S3method(ic_autopeek_header,default) S3method(ic_autopeek_header,list) export(ic) -export(ic_autopeek.default) export(ic_disable) export(ic_enable) importFrom(cli,cli_alert_info) diff --git a/R/autopeek.R b/R/autopeek.R index 5383f71..a4fd2eb 100644 --- a/R/autopeek.R +++ b/R/autopeek.R @@ -16,7 +16,9 @@ ic_autopeek <- function(object, ...) UseMethod("ic_autopeek") #' @export -ic_autopeek.default <- str +ic_autopeek.default <- function(object, ...) { + str(object, ...) +} #' @param max_summary_length Integer. Maximum length of string summarizing the object. #'