Title: | Prepare Reproducible Example Code via the Clipboard |
---|---|
Description: | Convenience wrapper that uses the 'rmarkdown' package to render small snippets of code to target formats that include both code and output. The goal is to encourage the sharing of small, reproducible, and runnable examples on code-oriented websites, such as <https://stackoverflow.com> and <https://github.com>, or in email. The user's clipboard is the default source of input code and the default target for rendered output. 'reprex' also extracts clean, runnable R code from various common formats, such as copy/paste from an R session. |
Authors: | Jennifer Bryan [aut, cre] , Jim Hester [aut] , David Robinson [aut], Hadley Wickham [aut] , Christophe Dervieux [aut] , Posit Software, PBC [cph, fnd] |
Maintainer: | Jennifer Bryan <[email protected]> |
License: | MIT + file LICENSE |
Version: | 2.1.1.9000 |
Built: | 2024-10-10 05:30:29 UTC |
Source: | https://github.com/tidyverse/reprex |
Run a bit of R code using rmarkdown::render()
and write the rendered result
to user's clipboard. If the clipboard is unavailable, the file containing
the rendered result is opened for manual copy. The goal is to make it easy to
share a small reproducible example ("reprex"), e.g., in a GitHub issue.
Reprex source can be
read from clipboard
provided directly as expression, character vector, or string
read from file
read from current selection or active document in RStudio
reprex can also be used for syntax highlighting (with or without rendering); see below for more.
reprex( x = NULL, input = NULL, wd = NULL, venue = c("gh", "r", "rtf", "html", "slack", "so", "ds"), render = TRUE, advertise = NULL, session_info = opt(FALSE), style = opt(FALSE), comment = opt("#>"), tidyverse_quiet = opt(TRUE), std_out_err = opt(FALSE), html_preview = opt(TRUE), outfile = deprecated(), show = deprecated(), si = deprecated() )
reprex( x = NULL, input = NULL, wd = NULL, venue = c("gh", "r", "rtf", "html", "slack", "so", "ds"), render = TRUE, advertise = NULL, session_info = opt(FALSE), style = opt(FALSE), comment = opt("#>"), tidyverse_quiet = opt(TRUE), std_out_err = opt(FALSE), html_preview = opt(TRUE), outfile = deprecated(), show = deprecated(), si = deprecated() )
x |
An expression. If not given, When the clipboard is structurally unavailable, e.g., on RStudio Server or
RStudio Cloud, |
input |
Character. If has length one and lacks a terminating newline,
interpreted as the path to a file containing reprex code. Otherwise,
assumed to hold reprex code as character vector. When |
wd |
An optional filepath that is consulted when The most common use of |
venue |
Character. Must be one of the following (case insensitive):
|
render |
Logical. Whether to call |
advertise |
Logical. Whether to include a footer that describes when and
how the reprex was created. If unspecified, the option |
session_info |
Logical. Whether to include
|
style |
Logical. Whether to set the knitr chunk option |
comment |
Character. Prefix with which to comment out output, defaults
to |
tidyverse_quiet |
Logical. Sets the options |
std_out_err |
Logical. Whether to append a section for output sent to
stdout and stderr by the reprex rendering process. This can be necessary to
reveal output if the reprex spawns child processes or |
html_preview |
Logical. Whether to show rendered output in a viewer
(RStudio or browser). Always |
outfile |
in favor of |
show |
in favor of |
si |
Character vector of rendered reprex, invisibly.
The usual "code + commented output" is returned invisibly, written to file,
and, whenever possible, put on the clipboard. An HTML preview displays in
RStudio's Viewer pane, if available, or in the default browser, otherwise.
Leading "> "
prompts, are stripped from the input code. Read more at
https://reprex.tidyverse.org/.
reprex sets specific knitr options:
Chunk options default to collapse = TRUE
, comment = "#>"
,
error = TRUE
. Note that error = TRUE
, because a common use case is bug
reporting.
reprex also sets knitr's upload.fun
. It defaults to
knitr::imgur_upload()
so figures produced by the reprex appear properly
on GitHub, Stack Overflow, Discourse, and Slack. Note that imgur_upload()
requires the packages httr and xml2. When venue = "r"
, upload.fun
is
set to identity()
, so that figures remain local. In that case, you may
also want to provide a filepath to input
or set wd
, to control where
the reprex files are written.
You can supplement or override these options with special comments in your
code (see examples).
To use rlang::last_error()
or rlang::last_trace()
within a reprex,
you must place them in a different "chunk" to the code that generates an
error. The easiest way to do is to insert a line containing the special
comment #'
after error-causing code:
f <- function() rlang::abort('foo') f() #' rlang::last_error() rlang::last_trace()
Read more in rlang's documentation: Errors in RMarkdown.
A secondary use case for reprex is to produce syntax highlighted code
snippets, with or without rendering, to paste into applications like
Microsoft Word, PowerPoint, or Keynote. Use venue = "rtf"
for this.
This feature is experimental and requires the installation of the
highlight
command line tool. The "rtf"
venue is documented in its own article
## Not run: # put some code like this on the clipboard # (y <- 1:4) # mean(y) reprex() # provide code as an expression reprex(rbinom(3, size = 10, prob = 0.5)) reprex({y <- 1:4; mean(y)}) reprex({y <- 1:4; mean(y)}, style = TRUE) # note that you can include newlines in those brackets # in fact, that is often a good idea reprex({ x <- 1:4 y <- 2:5 x + y }) ## provide code via character vector reprex(input = c("x <- 1:4", "y <- 2:5", "x + y")) ## if just one line, terminate with '\n' reprex(input = "rnorm(3)\n") ## customize the output comment prefix reprex(rbinom(3, size = 10, prob = 0.5), comment = "#;-)") # override a default chunk option reprex({ #+ setup, include = FALSE knitr::opts_chunk$set(collapse = FALSE) #+ actual-reprex-code (y <- 1:4) median(y) }) # add prose, use general markdown formatting reprex({ #' # A Big Heading #' #' Look at my cute example. I love the #' [reprex](https://github.com/tidyverse/reprex#readme) package! y <- 1:4 mean(y) }, advertise = FALSE) # read reprex from file and write resulting files to that location tmp <- file.path(tempdir(), "foofy.R") writeLines(c("x <- 1:4", "mean(x)"), tmp) reprex(input = tmp) list.files(dirname(tmp), pattern = "foofy") # clean up file.remove(list.files(dirname(tmp), pattern = "foofy", full.names = TRUE)) # write reprex to file AND keep figure local too, i.e. don't post to imgur tmp <- file.path(tempdir(), "foofy") dir.create(tmp) reprex({ #+ setup, include = FALSE knitr::opts_knit$set(upload.fun = identity) #+ actual-reprex-code #' Some prose ## regular comment (x <- 1:4) median(x) plot(x) }, wd = tmp) list.files(dirname(tmp), pattern = "foofy") # clean up unlink(tmp, recursive = TRUE) ## target venue = R, also good for email or Slack snippets ret <- reprex({ x <- 1:4 y <- 2:5 x + y }, venue = "R") ret ## target venue = html ret <- reprex({ x <- 1:4 y <- 2:5 x + y }, venue = "html") ret ## include prompt and don't comment the output ## use this when you want to make your code hard to execute :) reprex({ #+ setup, include = FALSE knitr::opts_chunk$set(comment = NA, prompt = TRUE) #+ actual-reprex-code x <- 1:4 y <- 2:5 x + y }) ## leading prompts are stripped from source reprex(input = c("> x <- 1:3", "> median(x)")) ## End(Not run)
## Not run: # put some code like this on the clipboard # (y <- 1:4) # mean(y) reprex() # provide code as an expression reprex(rbinom(3, size = 10, prob = 0.5)) reprex({y <- 1:4; mean(y)}) reprex({y <- 1:4; mean(y)}, style = TRUE) # note that you can include newlines in those brackets # in fact, that is often a good idea reprex({ x <- 1:4 y <- 2:5 x + y }) ## provide code via character vector reprex(input = c("x <- 1:4", "y <- 2:5", "x + y")) ## if just one line, terminate with '\n' reprex(input = "rnorm(3)\n") ## customize the output comment prefix reprex(rbinom(3, size = 10, prob = 0.5), comment = "#;-)") # override a default chunk option reprex({ #+ setup, include = FALSE knitr::opts_chunk$set(collapse = FALSE) #+ actual-reprex-code (y <- 1:4) median(y) }) # add prose, use general markdown formatting reprex({ #' # A Big Heading #' #' Look at my cute example. I love the #' [reprex](https://github.com/tidyverse/reprex#readme) package! y <- 1:4 mean(y) }, advertise = FALSE) # read reprex from file and write resulting files to that location tmp <- file.path(tempdir(), "foofy.R") writeLines(c("x <- 1:4", "mean(x)"), tmp) reprex(input = tmp) list.files(dirname(tmp), pattern = "foofy") # clean up file.remove(list.files(dirname(tmp), pattern = "foofy", full.names = TRUE)) # write reprex to file AND keep figure local too, i.e. don't post to imgur tmp <- file.path(tempdir(), "foofy") dir.create(tmp) reprex({ #+ setup, include = FALSE knitr::opts_knit$set(upload.fun = identity) #+ actual-reprex-code #' Some prose ## regular comment (x <- 1:4) median(x) plot(x) }, wd = tmp) list.files(dirname(tmp), pattern = "foofy") # clean up unlink(tmp, recursive = TRUE) ## target venue = R, also good for email or Slack snippets ret <- reprex({ x <- 1:4 y <- 2:5 x + y }, venue = "R") ret ## target venue = html ret <- reprex({ x <- 1:4 y <- 2:5 x + y }, venue = "html") ret ## include prompt and don't comment the output ## use this when you want to make your code hard to execute :) reprex({ #+ setup, include = FALSE knitr::opts_chunk$set(comment = NA, prompt = TRUE) #+ actual-reprex-code x <- 1:4 y <- 2:5 x + y }) ## leading prompts are stripped from source reprex(input = c("> x <- 1:3", "> median(x)")) ## End(Not run)
reprex_addin()
opens an RStudio gadget and
addin that allows you to say
where the reprex source is (clipboard? current selection? active file?
other file?) and to control a few other arguments. Appears as "Render
reprex" in the RStudio Addins menu.
reprex_selection()
is an
addin that reprexes the current
selection, optionally customised by options. Appears as "Reprex selection"
in the RStudio Addins menu. Heavy users might want to create a keyboard shortcut.
Suggested shortcut: Cmd + Shift + R (macOS) or Ctrl + Shift + R (Windows).
reprex_addin() reprex_selection(venue = getOption("reprex.venue", "gh"))
reprex_addin() reprex_selection(venue = getOption("reprex.venue", "gh"))
venue |
Character. Must be one of the following (case insensitive):
|
This is an R Markdown output format designed specifically for making
"reprexes", typically created via the reprex()
function, which ultimately
renders the document with reprex_render()
. It is a heavily modified version
of rmarkdown::md_document()
. The arguments have different spheres of
influence:
venue
potentially affects input preparation and reprex_render()
.
Add content to the primary input, prior to rendering:
advertise
session_info
std_out_err
(also consulted by reprex_render()
)
Influence knitr package or chunk options:
style
comment
tidyverse_quiet
RStudio users can create new R Markdown documents with the
reprex_document()
format using built-in templates. Do
File > New File > R Markdown ... > From Template and choose one of:
reprex (minimal)
reprex (lots of features)
Both include knit: reprex::reprex_render
in the YAML, which causes the
RStudio "Knit" button to use reprex_render()
. If you render these documents
yourself, you should do same.
reprex_document( venue = c("gh", "r", "rtf", "html", "slack", "so", "ds"), advertise = NULL, session_info = opt(FALSE), style = opt(FALSE), comment = opt("#>"), tidyverse_quiet = opt(TRUE), std_out_err = opt(FALSE), pandoc_args = NULL )
reprex_document( venue = c("gh", "r", "rtf", "html", "slack", "so", "ds"), advertise = NULL, session_info = opt(FALSE), style = opt(FALSE), comment = opt("#>"), tidyverse_quiet = opt(TRUE), std_out_err = opt(FALSE), pandoc_args = NULL )
venue |
Character. Must be one of the following (case insensitive):
|
advertise |
Logical. Whether to include a footer that describes when and
how the reprex was created. If unspecified, the option |
session_info |
Logical. Whether to include
|
style |
Logical. Whether to set the knitr chunk option |
comment |
Character. Prefix with which to comment out output, defaults
to |
tidyverse_quiet |
Logical. Sets the options |
std_out_err |
Logical. Whether to append a section for output sent to
stdout and stderr by the reprex rendering process. This can be necessary to
reveal output if the reprex spawns child processes or |
pandoc_args |
Additional command line options to pass to pandoc |
An R Markdown output format to pass to rmarkdown::render()
.
reprex_document()
reprex_document()
Render a reprex()
, with control over the localization of error messages and
aspects of the locale. Note that these are related but distinct issues!
Typical usage is for someone on a Spanish system to create a reprex that is
easier for an English-speaking audience to follow.
reprex_locale(..., language = "en", locale = NULL)
reprex_locale(..., language = "en", locale = NULL)
... |
Inputs passed through to |
language |
A string specifying the preferred language for messages. It
is enacted via the |
locale |
A named character vector, specifying aspects of the locale, in
the |
Character vector of rendered reprex, invisibly.
language
Use the language
argument to express the preferred language of error
messages. The output of dir(system.file(package = "translations"))
may
provide some helpful ideas. The language
should generally follow "XPG
syntax": a two-letter language code, optionally followed by other modifiers.
Examples: "en"
, "de"
, "en_GB"
, "pt_BR"
.
locale
Use the locale
argument only if you want to affect something like how
day-of-the-week or month is converted to character. You are less likely to
need to set this than the language
argument. You may have more success
setting specific categories, such as "LC_TIME"
, than multi-category
shortcuts like "LC_ALL"
or "LANG"
. The locale
values must follow the
format dictated by your operating system and the requested locale must be
installed. On *nix systems, locale -a
is a good way to see which locales
are installed. Note that the format for locale
and language
are different
from each other on Windows.
Examples: "en_CA.UTF-8"
(macOS), "French_France.1252"
(Windows).
The Locale Names section of the GNU C docs, for more about XPG syntax
The Internationalization and Localization section of the R Installation and Administration manual
## Not run: # if all you want to do is make sure messages are in English reprex_locale("a" / 2) # change messages to a specific language reprex_locale( { "a" / 2 }, language = "it" ) reprex_locale( { "a" / 2 }, language = "fr_CA" ) reprex_locale( { "a" / 2 }, language = "pt_BR" ) # get day-of-week and month to print in French (not Windows) reprex_locale( { format(as.Date(c("2019-01-01", "2019-02-01")), "%a %b %d") }, locale = c(LC_TIME = "fr_FR") ) # get day-of-week and month to print in French (Windows) # assumes that the relevant language is installed on the system # LC_TIME can also be specified as "French" or "French_France" here reprex_locale( { format(as.Date(c("2019-01-01", "2019-02-01")), "%a %b %d") }, locale = c(LC_TIME = "French_France.1252") ) ## End(Not run)
## Not run: # if all you want to do is make sure messages are in English reprex_locale("a" / 2) # change messages to a specific language reprex_locale( { "a" / 2 }, language = "it" ) reprex_locale( { "a" / 2 }, language = "fr_CA" ) reprex_locale( { "a" / 2 }, language = "pt_BR" ) # get day-of-week and month to print in French (not Windows) reprex_locale( { format(as.Date(c("2019-01-01", "2019-02-01")), "%a %b %d") }, locale = c(LC_TIME = "fr_FR") ) # get day-of-week and month to print in French (Windows) # assumes that the relevant language is installed on the system # LC_TIME can also be specified as "French" or "French_France" here reprex_locale( { format(as.Date(c("2019-01-01", "2019-02-01")), "%a %b %d") }, locale = c(LC_TIME = "French_France.1252") ) ## End(Not run)
Some reprex()
behaviour can be controlled via an option, providing a way
for the user to set personal defaults. The pattern for such option names is
reprex.<arg>
, where <arg>
is an argument of reprex()
. Here are the main
ones:
reprex.advertise
reprex.session_info
(previously, reprex.si
)
reprex.style
reprex.html_preview
(previously, reprex.show
)
reprex.comment
reprex.tidyverse_quiet
reprex.std_out_err
A few more options exist, but are only relevant to specific situations:
reprex.venue
: Can be used to control the venue
used by the
reprex_selection()
addin.
reprex.current_venue
: Read-only option that is set during
reprex_render()
. Other packages that want to generate reprex-compatible
output can consult it via getOption("reprex.current_venue")
, if they want
to tailor their output to the venue
.
reprex.clipboard
: When FALSE
, reprex makes no attempt to access the
user's clipboard, ever. This exists mostly for internal use, i.e. we set it
to FALSE
when we detect use from RStudio Server. But a user could set
this to FALSE
to explicitly opt-out of clipboard functionality. A Linux
user with no intention of installing xclip
or xsel
might also do this.
reprex.highlight.hl_style
: Only relevant to venue = "rtf
. Details are
in the article
reprex venue RTF.
reprex.highlight.font
: See above.
reprex.highlight.font_size
: See above.
reprex.highlight.other
: See above.
Here's code you could put in .Rprofile
to set reprex options. It would be
rare to want non-default behaviour for all of these! We only do so here for
the sake of exposition:
options( reprex.advertise = FALSE, reprex.session_info = TRUE, reprex.style = TRUE, reprex.html_preview = FALSE, reprex.comment = "#;-)", reprex.tidyverse_quiet = FALSE, reprex.std_out_err = TRUE, reprex.venue = "html", # NOTE: only affects reprex_selection()! reprex.highlight.hl_style = "acid", # NOTE: only affects RTF venue reprex.highlight.font = "Andale Mono Regular", reprex.highlight.font_size = 35, reprex.highlight.other = "--line-numbers" )
The function usethis::edit_r_profile()
is handy for creating and/or opening
your .Rprofile
.
opt()
helperArguments that appear like so in reprex()
:
reprex(..., arg = opt(DEFAULT), ...)
get their value according to this logic:
user-specified value or, if not given, getOption("reprex.arg") or, if does not exist, DEFAULT
It's shorthand for:
f(..., arg = getOption("reprex.arg", DEFAULT), ...)
This is not an exported function and should not be called directly.
This is a wrapper around rmarkdown::render()
that enforces the "reprex"
mentality. Here's a simplified version of what happens:
callr::r( function(input) { rmarkdown::render(input, envir = globalenv(), encoding = "UTF-8") }, args = list(input = input), spinner = is_interactive(), stdout = std_file, stderr = std_file )
Key features to note
rmarkdown::render()
is executed in a new R session, by using
callr::r()
. The goal is to eliminate the leakage of objects, attached
packages, and other aspects of session state from the current session into
the rendering session. Also, the system and user-level .Rprofile
s are
ignored.
Code is evaluated in the globalenv()
of this new R session, which means
that method dispatch works the way most people expect it to.
The input file is assumed to be UTF-8, which is a knitr requirement as of v1.24.
If the YAML frontmatter includes std_err_out: TRUE
, standard output and
error of the rendering R session are captured in std_file
, which is
then injected into the rendered result.
reprex_render()
is designed to work with the reprex_document()
output
format, typically through a call to reprex()
. reprex_render()
may work
with other R Markdown output formats, but it is not well-tested.
reprex_render(input, html_preview = NULL, encoding = "UTF-8")
reprex_render(input, html_preview = NULL, encoding = "UTF-8")
input |
The input file to be rendered. This can be a |
html_preview |
Logical. Whether to show rendered output in a viewer
(RStudio or browser). Always |
encoding |
The encoding of the input file. Note that the only acceptable value is "UTF-8", which is required by knitr as of v1.24. This is exposed as an argument purely for technical convenience, relating to the "Knit" button in the RStudio IDE. |
The output of rmarkdown::render()
is passed through, i.e. the path
of the output file.
## Not run: reprex_render("input.Rmd") ## End(Not run)
## Not run: reprex_render("input.Rmd") ## End(Not run)
These are thin wrappers around reprex()
that incorporate the target venue
as a suffix in the function name, for easier access via auto-completion.
reprex_html(...) reprex_r(...) reprex_rtf(...) reprex_slack(...)
reprex_html(...) reprex_r(...) reprex_rtf(...) reprex_slack(...)
... |
Passed along to |
Recover clean, runnable code from a reprex captured in the wild and write it to user's clipboard. The code is also returned invisibly and optionally written to file. Three different functions address various forms of wild-caught reprex:
reprex_invert()
attempts to reverse the effect of reprex()
. When
venue = "r"
, this just calls reprex_clean()
.
reprex_clean()
removes commented output. This assumes that R code is
top-level, possibly interleaved with commented output, e.g., a displayed
reprex copied from GitHub or the output of reprex(..., venue = "R")
.
reprex_rescue()
removes lines of output and strips prompts from lines
holding R commands. This assumes that R code lines start with a prompt and
that printed output is top-level, e.g., what you'd if you've copied from
the R Console.
reprex_invert( input = NULL, wd = NULL, venue = c("gh", "r"), comment = opt("#>"), outfile = deprecated() ) reprex_clean( input = NULL, wd = NULL, comment = opt("#>"), outfile = deprecated() ) reprex_rescue( input = NULL, wd = NULL, prompt = getOption("prompt"), continue = getOption("continue"), outfile = deprecated() )
reprex_invert( input = NULL, wd = NULL, venue = c("gh", "r"), comment = opt("#>"), outfile = deprecated() ) reprex_clean( input = NULL, wd = NULL, comment = opt("#>"), outfile = deprecated() ) reprex_rescue( input = NULL, wd = NULL, prompt = getOption("prompt"), continue = getOption("continue"), outfile = deprecated() )
input |
Character. If has length one and lacks a terminating newline, interpreted as the path to a file containing the reprex. Otherwise, assumed to hold the reprex as a character vector. If not provided, the clipboard is consulted for input. If the clipboard is unavailable and we're in RStudio, the current selection is used. |
wd |
An optional filepath that is consulted when The most common use of |
venue |
Character. Must be one of the following (case insensitive):
|
comment |
regular expression that matches commented output lines |
outfile |
in favor of |
prompt |
character, the prompt at the start of R commands |
continue |
character, the prompt for continuation lines |
Character vector holding just the clean R code, invisibly
## Not run: # a roundtrip: R code --> rendered reprex, as gfm --> R code original <- file.path(tempdir(), "original.R") writeLines(glue::glue(" #' Some text #+ chunk-label-and-options-cannot-be-recovered, message = TRUE (x <- 1:4) #' More text y <- 2:5 x + y"), con = original) reprex(input = original, html_preview = FALSE, advertise = FALSE) reprexed <- sub("[.]R$", "_reprex.md", original) writeLines(readLines(reprexed)) unreprexed <- reprex_invert(input = reprexed) writeLines(unreprexed) # clean up file.remove( list.files(dirname(original), pattern = "original", full.names = TRUE) ) ## End(Not run) ## Not run: # a roundtrip: R code --> rendered reprex, as R code --> original R code code_in <- c( "# a regular comment, which is retained", "(x <- 1:4)", "median(x)" ) reprexed <- reprex(input = code_in, venue = "r", advertise = FALSE) writeLines(reprexed) code_out <- reprex_clean(input = reprexed) writeLines(code_out) identical(code_in, code_out) ## End(Not run) ## Not run: # rescue a reprex that was copied from a live R session from_r_console <- c( "> # a regular comment, which is retained", "> (x <- 1:4)", "[1] 1 2 3 4", "> median(x)", "[1] 2.5" ) rescued <- reprex_rescue(input = from_r_console) writeLines(rescued) ## End(Not run)
## Not run: # a roundtrip: R code --> rendered reprex, as gfm --> R code original <- file.path(tempdir(), "original.R") writeLines(glue::glue(" #' Some text #+ chunk-label-and-options-cannot-be-recovered, message = TRUE (x <- 1:4) #' More text y <- 2:5 x + y"), con = original) reprex(input = original, html_preview = FALSE, advertise = FALSE) reprexed <- sub("[.]R$", "_reprex.md", original) writeLines(readLines(reprexed)) unreprexed <- reprex_invert(input = reprexed) writeLines(unreprexed) # clean up file.remove( list.files(dirname(original), pattern = "original", full.names = TRUE) ) ## End(Not run) ## Not run: # a roundtrip: R code --> rendered reprex, as R code --> original R code code_in <- c( "# a regular comment, which is retained", "(x <- 1:4)", "median(x)" ) reprexed <- reprex(input = code_in, venue = "r", advertise = FALSE) writeLines(reprexed) code_out <- reprex_clean(input = reprexed) writeLines(code_out) identical(code_in, code_out) ## End(Not run) ## Not run: # rescue a reprex that was copied from a live R session from_r_console <- c( "> # a regular comment, which is retained", "> (x <- 1:4)", "[1] 1 2 3 4", "> median(x)", "[1] 2.5" ) rescued <- reprex_rescue(input = from_r_console) writeLines(rescued) ## End(Not run)