Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/lewinfox/icecream
Never use `print()` to debug again.
https://github.com/lewinfox/icecream
debugging r
Last synced: 3 months ago
JSON representation
Never use `print()` to debug again.
- Host: GitHub
- URL: https://github.com/lewinfox/icecream
- Owner: lewinfox
- License: other
- Created: 2021-03-31T23:40:00.000Z (over 3 years ago)
- Default Branch: master
- Last Pushed: 2024-02-18T00:32:41.000Z (9 months ago)
- Last Synced: 2024-06-05T02:31:29.996Z (5 months ago)
- Topics: debugging, r
- Language: R
- Homepage: http://www.lewinfox.com/icecream/
- Size: 377 KB
- Stars: 51
- Watchers: 4
- Forks: 6
- Open Issues: 6
-
Metadata Files:
- Readme: README.Rmd
- License: LICENSE
Awesome Lists containing this project
- jimsghstars - lewinfox/icecream - Never use `print()` to debug again. (R)
README
---
output: github_document
---```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)demo_file <- file.path(tempdir(TRUE), "demo.R")
demo_fns <- "# demo.R
f1 <- function(x) {
ic()
if (x > 0) {
f2()
}
}f2 <- function() {
ic()
}f3 <- function(x) {
ic(x)
}
"cat(demo_fns, file = demo_file)
source(demo_file)
```# icecream
[![](http://cranlogs.r-pkg.org/badges/grand-total/icecream)](https://cran.r-project.org/package=icecream)
[![R-CMD-check](https://github.com/lewinfox/icecream/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/lewinfox/icecream/actions/workflows/R-CMD-check.yaml)icecream is designed to make print debugging easier. It allows you to print out an expression, its
value and (optionally) which function and file the call originated in.This is an R port of [gruns/icecream](https://github.com/gruns/icecream). All credit for the idea
belongs to [Ansgar Grunseid](https://github.com/gruns).## Installation
Install from CRAN with:
``` r
install.packages("icecream")
```Or you can install the development version from GitHub with:
``` r
devtools::install_github("lewinfox/icecream")
```## Inspect variables
The `ic()` function prints its argument and its value. It also returns the value of the evaluated
argument, meaning that it is effectively transparent in code - just wrap an expression in `ic()` to
get debugging output.```{r example}
library(icecream)is_negative <- function(x) x < 0
ic(is_negative(1))
ic(is_negative(-1))
```You're more likely to want to do this within a function:
```{r}
some_function <- function(x) {
intermediate_value <- x * 10
answer <- ic(intermediate_value / 2)
return(answer)
}some_function(1)
some_function(10)
```More complex inputs like lists and data frames are summarised to avoid cluttering the terminal.
```{r}
df <- ic(iris)my_list <- ic(list(a = 1, b = 3, c = 1:100))
```## Inspect execution
Calling `ic()` with no arguments causes it to print out the file, line and parent function it was
called from.In this example we have a file `demo.R` that contains two functions. We've inserted `ic()` calls at
strategic points so we can track what's being executed.```{r code=readLines(demo_file)}
`````` r
source("demo.R")f1(-1)
#> ℹ ic| `global::f1()` in demo.R:3:2f1(1)
#> ℹ ic| `global::f1()` in demo.R:3:2
#> ℹ ic| `global::f2()` in demo.R:10:2
```In the case of functions that haven't been `source()`d or loaded from a package there is no source
code to refer to. In these cases the function's environment will be displayed.``` r
orphan_func <- function() {
ic()
TRUE
}orphan_func()
#> ℹ ic| `global::orphan_func()` in
#> [1] TRUEe <- new.env()
attr(e, "name") <- "icecream_van"
environment(orphan_func) <- eorphan_func()
#> ℹ ic| `orphan_func()` in
#> [1] TRUE
```## Enable / disable
The `ic_enable()` and `ic_disable()` functions enable or disable the `ic()` function. If disabled,
`ic()` will return the result of evaluating its input but will not print anything.```{r}
ic_enable() # This is TRUE by defaultic(mean(1:100))
ic_disable()
ic(mean(1:100))
``````{r, include=FALSE}
ic_enable()
```Convenience functions `with_ic_enable()` and `with_ic_disable()` are also provided.
```{r}
ic_enable()with_ic_disable(ic(mean(1:100)))
ic_disable()
with_ic_enable(ic(mean(1:100)))
``````{r, include=FALSE}
ic_enable()
```## Options
The following options can be used to control behaviour:
### `icecream.enabled`
Boolean. If `FALSE`, calls to `ic(foo)` simply evaluate and return `foo`. No output is printed. This
option can be set directly or with the `ic_enable()` and `ic_disable()` functions.### `icecream.prefix`
This is printed at the beginning of every line. Defaults to `"ic|"`.```{r, include=FALSE}
old.prefix <- getOption("icecream.prefix")
``````{r}
ic(mean(1:5))options(icecream.prefix = "DEBUG:")
ic(mean(1:5))options(icecream.prefix = "\U1F366")
ic(mean(1:5))
``````{r, include=FALSE}
options(icecream.prefix = old.prefix)
```### `icecream.always.include.context`
Boolean. If `TRUE`, when calling `ic(foo)` the source file and line will be printed along with the
expression and value. If no `srcref()` is available the function's environment will be displayed
instead. This can be useful for more complicated debugging but produces a lot of output so is
disabled by default.```{r, include=FALSE}
old.ctx <- getOption("icecream.always.include.context")
`````` r
f3(1)
#> ℹ ic| `x`: num 1options(icecream.always.include.context = TRUE)
f3(1)
#> ℹ ic| `global::f3()` in demo.R:14:2 | `x`: num 1
```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.```{r, include=FALSE}
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.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) # we would like to see header of the data
options(
icecream.peeking.function = head,
icecream.max.lines = 5
)ic(iris)
```**NOTE**: Due to [r-lib/cli#626](https://github.com/r-lib/cli/issues/626), newlines are currently
being removed from `ic()`'s multi-line output.```{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.## TODO:
* Implement `ic.format()` (see [here](https://github.com/gruns/icecream#miscellaneous)).
* Implement `ic.output.function`. At the moment it uses `cli::cli_alert_info()`
* Implement `ic.arg.to.string.function`