diff --git a/.Rbuildignore b/.Rbuildignore index 91114bf..33cc41e 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,2 +1,5 @@ ^.*\.Rproj$ ^\.Rproj\.user$ +^_pkgdown\.yml$ +^docs$ +^pkgdown$ diff --git a/.gitignore b/.gitignore index 8e0effd..62effa7 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,3 @@ # Example code in package build process *-Ex.R - diff --git a/DESCRIPTION b/DESCRIPTION index 2f5c71a..1582d94 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,26 +1,23 @@ -Package: oveRflow -Version: 0.1-0 -Date: 2013-03-24 +Package: overflow +Version: 0.2-4 +Date: 2020-06-19 Title: Utility functions for answering R question on StackOverflow -Authors@R: c(person("Sebastian", "Campbell", role = c("aut", "cre"), +Authors@R: c(person("Sebastian", "Campbell", role = "aut", email="sebastian.campbell@sydney.edu.au"), - person("Ananda", "Mahto", role="aut", + person("Ananda", "Mahto", role=c("aut", "cre"), email="ananda@mahto.info"), person("Julien", "Barnier", role="aut", email="julien@nozav.org"), - person("Tyler", "Rinker", role="ctb")) -Author: Sebastian Campbell, Ananda Mahto, Julien Barnier -Maintainer: Sebastian Campbell + person("Tyler", "Rinker", role="aut"), + person("Richard", "Cotton", role="aut"), + person("Brodie", "Gaslam", role="aut")) Description: On StackOverflow, there are several tasks which are performed repeatedly including temporarily installing a package and copying code into an R session. This package automates some of these processes, making answering questions easier. License: GPL-3 -URL: http://github.com/sebastian-c/oveRflow -BugReports: http://github.com/sebastian-c/oveRflow/issues -Collate: - 'readSO.R' - 'tmp_install_packages.R' - 'readClip.R' - 'writeClip.R' - 'SOdput.R' +URL: http://mrdwab.github.io/overflow-mrdwab, https://github.com/mrdwab/overflow-mrdwab +BugReports: https://github.com/mrdwab/overflow-mrdwab/issues +RoxygenNote: 7.1.0 +Suggests: testthat +Encoding: UTF-8 diff --git a/NAMESPACE b/NAMESPACE index a4b61f7..66ae3d0 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,3 +1,17 @@ -export(readSO) -export(SOdput) -export(tmp_install_packages) +# Generated by roxygen2: do not edit by hand + +S3method(sotrunc,data.frame) +S3method(sotrunc,default) +S3method(sotrunc,list) +S3method(sotrunc,matrix) +export(lastcall) +export(soanswer) +export(sodput) +export(solast) +export(sopkgs) +export(sorandf) +export(sorandf_add) +export(sorandf_reset) +export(soread) +export(sotrunc) +importFrom(utils,capture.output) diff --git a/NEWS b/NEWS deleted file mode 100644 index 111306c..0000000 --- a/NEWS +++ /dev/null @@ -1,11 +0,0 @@ -* New function: SOdput - Sends `dput` to clipboard with assignment operator. -* readSO now strips out ## comments and leading whitespace. -* Bugfix - tmp_install_packages no longer overwrites libraries which are not - the base and user libraries. -* New function: tmp_install_packages - installs packages to a temporary library. -* Bugfix - readSO now works on Mac. - -overflow 0.1-0 --------------------------------------------------------------------------------- - -* New function: readSO - reads in data from StackOverflow. \ No newline at end of file diff --git a/NEWS.md b/NEWS.md new file mode 100644 index 0000000..5bf06eb --- /dev/null +++ b/NEWS.md @@ -0,0 +1,29 @@ +# overflow 0.2-4 + +* Modified `soread` to allow skipping lines after header, for example when +using with outpt from a `tibble`. + +# overflow 0.2-3 + +* `solast` added to capture the output from `.Last.value` along with the last +expression from the history. + +# overflow 0.2-1 + +* Added `sorandf` for creating random datasets. + +# overflow 0.2-0 + +* Renamed package from 'oveRflow' to 'overflow' +* Renamed function `SOread`, `SOdput` and `tmp_install_packages to `soread` and + `sodput` and `sopkgs` for easier use. +* New function: SOdput - Sends `dput` to clipboard with assignment operator. +* readSO now strips out ## comments and leading whitespace. +* Bugfix - tmp_install_packages no longer overwrites libraries which are not + the base and user libraries. +* New function: tmp_install_packages - installs packages to a temporary library. +* Bugfix - readSO now works on Mac. + +# overflow 0.1-0 + +* New function: readSO - reads in data from StackOverflow. diff --git a/R/clipboard.R b/R/clipboard.R new file mode 100644 index 0000000..7b129da --- /dev/null +++ b/R/clipboard.R @@ -0,0 +1,75 @@ +#' Read Clipboard Regardless of OS +#' +#' Different operating systems have different ways of handling the clipboard. +#' Given the frequency with which text is copied to the clipboard to place in +#' an answer on StackOverflow, this utility is provided. +#' +#' @return character string containing text on the clipboard. +#' +readClip <- function() { + OS <- Sys.info()["sysname"] + cliptext <- switch( + OS, + Darwin = { + con <- pipe("pbpaste") + text <- readLines(con) + close(con) + text + }, + Windows = readClipboard(), + Linux = { + if (Sys.which("xclip") == "") { + mess <- c("Clipboard on Linux requires 'xclip'. Try using:", + "sudo apt-get install xclip") + message(paste(mess, collapse = "\n")) + } + con <- pipe("xclip -o -selection clipboard") + text <- readLines(con = con) + close(con) + text + }, + stop("Reading from clipboard not yet supported on your OS")) + cliptext +} + +#' Write to Clipboard on Multiple OSes +#' +#' This function works on Windows, Mac and Linux. It copies a +#' character string or vector of characters to the clipboard and interprets +#' a vector of characters as one character with each element being newline +#' separated. If using Linux, xclip is used as the clipboard. So for the +#' function to work, xclip must be installed. +#' +#' @param object character. Character to be copied to the clipboard +#' +#' @return Returns nothing to R. Returns character string to the clipboard +#' +#' @details If using Linux, xclip will be used as the clipboard. To paste from +#' xclip, either use middle click or the command \code{xclip -o} in the shell. +#' +writeClip <- function(object) { + OS <- Sys.info()["sysname"] + if(!(OS %in% c("Darwin", "Windows", "Linux"))) { + stop("Copying to clipboard not yet supported on your OS") + } + switch( + OS, + Darwin = { + con <- pipe("pbcopy", "w") + writeLines(object, con=con) + close(con) + }, + Windows = writeClipboard(object, format = 1), + Linux = { + if (Sys.which("xclip") == "") { + if (Sys.which("xclip") == "") { + mess <- c("Clipboard on Linux requires 'xclip'. Try using:", + "sudo apt-get install xclip") + message(paste(mess, collapse = "\n")) + } + } + con <- pipe("xclip -selection clipboard -i", open = "w") + writeLines(object, con=con) + close(con) + }) +} diff --git a/R/package.R b/R/package.R new file mode 100644 index 0000000..8e7173d --- /dev/null +++ b/R/package.R @@ -0,0 +1,12 @@ +#' Helper functions for answering R StackOverflow questions +#' +#' This package is focused on providing helper functions to answer StackOverflow +#' questions. It includes functions to transfer code and create random datasets. +#' +#' @docType package +#' @name overflow-package +#' @aliases overflow +#' +#' @author Sebastian Campbell, Ananda Mahto, Julien Barnier, Tyler Rinker + +NULL \ No newline at end of file diff --git a/R/readClip.R b/R/readClip.R deleted file mode 100644 index cdd0005..0000000 --- a/R/readClip.R +++ /dev/null @@ -1,23 +0,0 @@ -#' Read clipboard regardless of OS -#' -#' Different operating systems have different ways of handling the clipboard. -#' Given the frequency with which text is copied to the clipboard to place in -#' an answer on StackOverflow, this utility is provided. -#' -#' @return character string containing text on the clipboard. -#' - -readClip <- function(){ - OS <- Sys.info()["sysname"] - - cliptext <- switch(OS, - Darwin = { - con <- pipe("pbpaste") - text <- readLines(con) - close(con) - text - }, - Windows = readClipboard(), - readLines("clipboard")) - cliptext -} \ No newline at end of file diff --git a/R/soanswer.R b/R/soanswer.R new file mode 100644 index 0000000..60d55eb --- /dev/null +++ b/R/soanswer.R @@ -0,0 +1,45 @@ +#' Turn an R expression into an SO answer +#' +#' Parrot the input expression and append the output with knitr-style comments, +#' all as markdown. \code{soanswer} changes the output for a single expression. +#' @param expr An R expression. +#' @param in_task_callback A logical value. Not intended for direct use. +#' @return Markdown output is printed to the console, written to the clipboard +#' and silently returned as a \code{noquote} character vector. +#' @author Richard Cotton +#' @seealso \code{\link[base]{addTaskCallback}} +#' @examples +#' # Output for various types, explicitly calling soanswer +#' soanswer(sin(2 * pi)) +#' soanswer(sleep) +#' soanswer(message("A message!")) +#' soanswer(warning("A warning!")) +#' soanswer(stop("An error!")) +#' @importFrom utils capture.output +#' @export soanswer +soanswer <- function(expr, in_task_callback = FALSE) +{ + input_lines <- noquote( + paste0( + " ", + if(in_task_callback) + { + deparse(expr) + } else + { + deparse(substitute(expr)) + } + ) + ) + output <- tryCatch( + utils::capture.output(print(if(in_task_callback) eval(expr) else expr)), + message = function(m) substring(m$message, 1, nchar(m$message) - 1), + warning = function(w) c("Warning message:", w$message), + error = function(e) paste("Error:", e$message) + ) + output_lines <- noquote(paste0(" ## ", output)) + lines <- c(input_lines, output_lines) + cat(lines, sep = "\n") + writeClip(lines) + invisible(lines) +} diff --git a/R/SOdput.R b/R/sodput.R similarity index 83% rename from R/SOdput.R rename to R/sodput.R index cc469a0..485ca38 100644 --- a/R/SOdput.R +++ b/R/sodput.R @@ -3,22 +3,22 @@ #' In several cases, you may want to give a sample dataset. \code{dput} is a great tool for doing so. This tool takes #' the \code{dput} output and places it on the clipboard, as well as adding an assignment operator. #' -#' @param object R object to convert to code +#' @param object R object to convert to code. #' @param rows numeric. Vector of row numbers. These rows will be produced in the output. #' By default, all rows are included. -#' @param indents integer. Spaces to be added before each line +#' @param indents integer. Spaces to be added before each line. #' @param mdformat logical. Whether or not to add 4 spaces before every line in order to format as a code block. #' #' @author Tyler Rinker #' #' @examples #' \dontrun{ -#' SOdput(mtcars) -#' SOdput(mtcars, rows=1:6) +#' sodput(mtcars) +#' sodput(mtcars, rows=1:6) #' } #' @export -SOdput <- function(object, rows=TRUE, indents = 4, mdformat=TRUE) { +sodput <- function(object, rows=TRUE, indents = 4, mdformat=TRUE) { name <- as.character(substitute(object)) name <- name[length(name)] diff --git a/R/solast.R b/R/solast.R new file mode 100644 index 0000000..b91bca5 --- /dev/null +++ b/R/solast.R @@ -0,0 +1,115 @@ +# Only purpose of this is so that we can 'mock' the `.Last.value` in testing + +lastval <- function() .Last.value + +#' Retrieve Last Call from History +#' +#' Returns the last call that was entered at the R prompt if it parsed +#' parsed successfully. Because the history file may contain unparseable lines +#' and because it may not start from the beginning of an R session, it is not +#' possible to guarantee that we will be able to correctly retrieve the last +#' command. This function will warn when it can retrieve a command but is not +#' certain the command is complete. +#' +#' @export +#' @author Brodie Gaslam +#' @param max.lookback integer(1L) how many lines of history to attempt to +#' parse back from the end of the history file +#' @return language the last top level command, parsed + +lastcall <- function(max.lookback=100L){ + if( + !is.numeric(max.lookback) || length(max.lookback) != 1L || + is.na(max.lookback) || max.lookback < 0L + ) + stop("`max.lookback` must be integer(1L), not NA, and positive") + + max.lookback <- as.integer(max.lookback) + tmp <- tempfile() + savehistory(tmp) + on.exit(unlink(tmp)) + hist.rev <- rev(readLines(tmp)) + + # Read from end until we reach end of file or `max.lookback` or something + # that successfully parses to two expressions + + warn <- TRUE + stop.line <- 0L + parse.res.success <- NULL + for(i in head(seq_along(hist.rev), max.lookback)) { + parse.res <- try(parse(text=rev(head(hist.rev, i))), silent=TRUE) + if(inherits(parse.res, "try-error")) next + parse.res.success <- parse.res + stop.line <- i + if(length(parse.res) > 2L) { + warn <- FALSE + break + } + } + if(length(parse.res.success) < 2L) + stop( + "Unable to retrieve final expression from last ", max.lookback, + " history lines. If you're sure the last command did not result ", + "in a parse error, try increasing `max.lookback`." + ) + if(warn) warning("We cannot guarantee that the last command was fully parsed") + parse.res.success[[length(parse.res.success) - 1L]] +} +#' Capture Last Top Level Call And Output +#' +#' Captures the output from \code{.Last.value} along with the last expression +#' from the history file and formats them in a manner suitable for posting on +#' Stack Overflow. +#' +#' If you the expression you want captured spans multiple lines, enclose them +#' in a call to \code{\{}. The curly braces will be dropped from the display +#' to make it appear as if you typed all the commands sequentially into the R +#' prompt, though any interim output will not be captured. +#' +#' Please note that the only output that is "captured" by this function is the +#' result of evaluating \code{.Last.value}. If there were warning, errors, or +#' other screen output during the actual expression evaluation those will not +#' show up here. +#' +#' @author Andanda Mahto, Brodie Gaslam +#' @export +#' @seealso \code{\link{lastcall}} for limitations in capturing the last call +#' @param silent logical(1L) set to TRUE to suppress screen display +#' @param clip logical(1L) set to TRUE (default) to attempt to write to system +#' clipboard +#' @param drop.curly.brace if the last call is a call to \code{\{}, drop it and +#' show only the contents (see examples) +#' @param ... arguments to pass on to \code{\link{lastcall}} +#' @return character, invisibly, the call and value together formatted for +#' posting on SO +#' @examples +#' \dontrun{ +#' 1 + 1 +#' solast() +#' { +#' x <- runif(20) +#' x + 3 +#' } +#' solast() +#' } + +solast <- function(silent=FALSE, clip=TRUE, drop.curly.brace=TRUE,...) { + if(!isTRUE(silent) && !identical(silent, FALSE)) + stop("Argument `silent` must be TRUE or FALSE") + if(!isTRUE(clip) && !identical(clip, FALSE)) + stop("Argument `clip` must be TRUE or FALSE") + if(!isTRUE(drop.curly.brace) && !identical(drop.curly.brace, FALSE)) + stop("Argument `drop.curly.brace` must be TRUE or FALSE") + + output <- utils::capture.output(lastval()) + l.c <- lastcall(...) + l.c.d <- if(identical(l.c[[1L]], as.name("{")) && drop.curly.brace) { + unlist(lapply(tail(l.c, -1L), deparse)) + } else deparse(l.c) + x <- noquote(paste0(" ", l.c.d)) + output_lines <- noquote(paste0(" ## ", output)) + lines <- c(x, output_lines) + if(!silent) cat(lines, sep = "\n") + if(clip) writeClip(lines) + invisible(lines) +} diff --git a/R/tmp_install_packages.R b/R/sopkgs.R similarity index 91% rename from R/tmp_install_packages.R rename to R/sopkgs.R index d626472..99408c5 100644 --- a/R/tmp_install_packages.R +++ b/R/sopkgs.R @@ -20,7 +20,7 @@ #' #' @param package character. A package name, or vector of package names. #' @param dependencies logical. Argument passed to \code{install.packages}. Defaults to TRUE. -#' @param ... other arguments passed to \code{install.packages}. +#' @param ... Other arguments passed to \code{install.packages}. #' @export #' @author Julien Barnier #' @seealso \code{\link{install.packages}}, \code{\link{.libPaths}} @@ -28,10 +28,10 @@ #' #' \dontrun{ #' ## Temporarily install the ggplot2 package in the current R session -#' tmp_install_packages("ggplot2") +#' sopkgs("ggplot2") #' } -tmp_install_packages <- function(package, dependencies=TRUE, ...) { +sopkgs <- function(package, dependencies=TRUE, ...) { path <- tempdir() ## Add 'path' to .libPaths, and be sure that it is not ## at the first position, otherwise any package during diff --git a/R/sorandf.R b/R/sorandf.R new file mode 100644 index 0000000..a6b9128 --- /dev/null +++ b/R/sorandf.R @@ -0,0 +1,102 @@ +#' Create random data.frame +#' +#' \code{sorandf} creates a data frame with columns corresponding to different +#' types of random data. It is intended for making reproducible examples easier. +#' +#' @aliases sorandf_add sorandf_reset +#' +#' @param rows integer. number of rows in data.frame. +#' @param cols character. Vector of types of columns. +#' @param names character. Vector of names of columns in data.frame output. +#' @param newf function to add to sorandf functions. Must have just one +#' parameter, n. +#' @param name character. Name to call new function. +#' +#' @details Each column must have a function defining it. It is possible to add +#' new functions using the \code{sorandf_add} function and reset back to the +#' defaults using the \code{sorandf_reset} function. Within this function, +#' there are a number of defaults which can be called by default: +#' +#' \code{id = function(n) paste0("ID.", 1:n)} +#' +#' \code{group = function(n) sample(c("control", "treat"), n, replace = TRUE)} +#' +#' \code{hs.grad = function(n) sample(c("yes", "no"), n, replace = TRUE)} +#' +#' \code{race = function(n) sample(c("black", "white", "asian"), n, replace = +#' TRUE, prob=c(.25, .5, .25))} +#' +#' \code{gender = function(n) sample(c("male", "female"), n, replace = TRUE)} +#' +#' \code{age = function(n) sample(18:40, n, replace = TRUE)} +#' +#' \code{m.status = function(n) sample(c("never", "married", "divorced", +#' "widowed"), n, replace = TRUE, prob=c(.25, .4, .3, .05))} +#' +#' \code{political = function(n) sample(c("democrat", "republican", +#' "independent", "other"), n, replace= TRUE, prob=c(.35, .35, .20, .1))} +#' +#' \code{n.kids = function(n) rpois(n, 1.5)} +#' +#' \code{income = function(n) sample(c(seq(0, 30000, by=1000), seq(0, 150000, +#' by=1000)), n, replace=TRUE)} +#' +#' \code{score = function(n) rnorm(n)} +#' +#' @author Sebastian Campbell, Tyler Rinker +#' +#' @examples +#' \dontrun{ +#' sorandf(15, c("id", "age", "score"), names= c("card", "years", "points")) +#' +#' sorandf_add(function(n){sample(1:10, n)}, "newf") +#' sorandf(10, c("gender", "race", "newf")) +#' sorandf_reset() +#' } +#' +#' @export sorandf sorandf_reset sorandf_add + +sorandf <- function(rows=10L, cols=c("race", "gender", "age"), names=make.names(cols)){ + + setNames(as.data.frame(lapply(cols, function(x) get(x, envir=.so.env)(rows))), names) + +} + +#' @rdname sorandf + +sorandf_add <- function(newf, name){ + + if(name %in% ls(envir=.so.env)){ + warning(paste0("existing function with name: ", name, " overwritten")) + } + assign(name, newf, envir=.so.env) +} + +#' @rdname sorandf + +sorandf_reset <- function(){ + rm(list=ls(envir=.so.env), envir=.so.env) + invisible(mapply(assign, names(base.list), base.list, MoreArgs=list(envir=.so.env))) +} + +base.list <- list(id = function(n) paste0("ID.", 1:n), + group = function(n) sample(c("control", "treat"), n, replace = TRUE), + hs.grad = function(n) sample(c("yes", "no"), n, replace = TRUE), + race = function(n) sample(c("black", "white", "asian"), n, + replace = TRUE, prob=c(.25, .5, .25)), + gender = function(n) sample(c("male", "female"), n, replace = TRUE), + age = function(n) sample(18:40, n, replace = TRUE), + m.status = function(n) sample(c("never", "married", "divorced", "widowed"), + n, replace = TRUE, prob=c(.25, .4, .3, .05)), + political = function(n) sample(c("democrat", "republican", + "independent", "other"), n, replace= TRUE, + prob=c(.35, .35, .20, .1)), + n.kids = function(n) rpois(n, 1.5), + income = function(n) sample(c(seq(0, 30000, by=1000), + seq(0, 150000, by=1000)), n, replace=TRUE), + score = function(n) rnorm(n) + ) + +.so.env <- as.environment(base.list) + + diff --git a/R/readSO.R b/R/soread.R similarity index 58% rename from R/readSO.R rename to R/soread.R index 299134e..c58e076 100644 --- a/R/readSO.R +++ b/R/soread.R @@ -9,16 +9,25 @@ #'TRUE, stringsAsFactors = FALSE)}. This function is basically a convenience #'function for the above. #' -#'The output of \code{\link{readSO}} is automatically assigned to an object in +#'The output of \code{\link{soread}} is automatically assigned to an object in #'your workspace called "\code{mydf}" unless specified using the \code{out} #'argument. #' -#' @param sep character. Determines the field separator character passed to \code{read.table}. -#' @param header logical. Determines whether the first row consists of names of variables. -#' @param stringsAsFactors logical. Whether strings are converted to factors or remain character variables. +#' @param sep character. Determines the field separator character passed +#' to \code{read.table}. +#' @param header logical. Determines whether the first row consists of +#' names of variables. +#' @param stringsAsFactors logical. Whether strings are converted to +#' factors or remain character variables. Defaults to `FALSE` +#' @param skipAfterHeader numeric. Some newer print methods print additional +#' information just below the headers (for example, `tibble`s and `data.table`s). +#' If `skipAfterHeader = TRUE`, the second line will be removed. If +#' `skipAfterHeader` is a numeric value, those lines after the header row +#' will be removed before reading the data. #' @param out character. Desired output object name. Defaults to \code{"mydf"}. #' @return A data.frame as \code{read.table} produces. -#' @note By default, stringsAsFactors is FALSE which is different to the R default. +#' @note By default, `stringsAsFactors` is `FALSE` which is different to the R default +#' in R versions prior to 4.0. #' #' @export #' @author Ananda Mahto @@ -35,13 +44,21 @@ #' #'## Now, just type: #' -#'readSO() +#'soread() #'} #' -readSO <- function(sep = "", header = TRUE, stringsAsFactors = FALSE, out = "mydf") { - temp <- gsub("^#|^##", "", gsub("^\\s+", "", suppressWarnings(readClip()))) +soread <- function(sep = "", header = TRUE, stringsAsFactors = FALSE, skipAfterHeader = NULL, out = "mydf") { + temp <- sub("^[# ]+", "", suppressWarnings(readClip())) + if (!is.null(skipAfterHeader)) { + if (is.logical(skipAfterHeader) & isTRUE(skipAfterHeader)) { + temp <- temp[-2] + } else { + temp <- temp[-c(1 + skipAfterHeader)] + } + } temp <- read.table(text = temp, header = header, stringsAsFactors = stringsAsFactors, sep = sep) assign(out, temp, envir = .GlobalEnv) message("data.frame ", dQuote(out), " created in your workspace") temp } +NULL \ No newline at end of file diff --git a/R/sotrunc.R b/R/sotrunc.R new file mode 100644 index 0000000..f1687dd --- /dev/null +++ b/R/sotrunc.R @@ -0,0 +1,164 @@ +#' Truncate the Output of Dataframes, Matrices and Lists +#' +#' A dispaly printing function that trunates \code{data.frame}/\code{matrix} by +#' adding ellipsis \ldots to take the place of non-displayed columns and rows. +#' +#' @param x An R object (usually a \code{data.frame}, \code{matrix}, or a +#' \code{list} that contains >= 1 \code{data.frame}/\code{matrix}. +#' @param ncol The number of columns (including 3 columns displayed as ellipsis) +#' to display. +#' @param nrow The number of rows (including 3 rows displayed as ellipsis) to +#' display. +#' @param \ldots Other arguments passed to \code{sotrunc}. +#' @note This function is intended for truncated display. Please do not use to +#' gernarate your \href{http://sscce.org/}{SSCCE} +#' (Short, Self Contained, Correct (Compilable), Example). +#' @return Prints a truncated display of the input. +#' @keywords truncate +#' @export +#' @rdname sotrunc +#' @examples +#' sotrunc(mtcars) +#' sotrunc(mtcars, nrow = 6) +#' sotrunc(mtcars, ncol = 6) +#' sotrunc(CO2) +#' sotrunc(lm(mpg~hp+am, data=mtcars)) +#' sotrunc(1:10) +#' sotrunc(mtcars[1:5, 1:5]) +sotrunc <- function(x, ncol = 10, nrow=15, ...){ + + if (ncol < 4 | nrow < 4) stop("`ncol` & `nrow` arguments must be > 3") + + x + ncol + nrow + + UseMethod("sotrunc") + +} + +#' \code{sotrunc.matrix} - matrix method for \code{sotrunc} +#' @rdname sotrunc +#' @export +#' @method sotrunc matrix +sotrunc.matrix <- function(x, ncol = 10, nrow=15, ...){ + + sotrunc_helper(x=x, ncol = ncol, nrow=nrow) + +} + +#' \code{sotrunc.data.frame} - data.frame method for \code{sotrunc} +#' @rdname sotrunc +#' @export +#' @method sotrunc data.frame +sotrunc.data.frame <- function(x, ncol = 10, nrow=15, ...){ + + sotrunc_helper(x=x, ncol = ncol, nrow=nrow) + +} + +#' \code{sotrunc.list} - list method for \code{sotrunc} +#' @rdname sotrunc +#' @export +#' @method sotrunc list +sotrunc.list <- function(x, ncol = 10, nrow=15, ...){ + + sotrunc_list_helper(x=x, ncol = ncol, nrow=nrow) + +} + +#' \code{sotrunc.default} - Default method for \code{sotrunc} +#' @rdname sotrunc +#' @export +#' @method sotrunc default +sotrunc.default <- function(x, ncol = 10, nrow=15, ...){ + + if (is.list(x)) { + sotrunc_list_helper(x=x, ncol = ncol, nrow=nrow) + } else { + if (!any(sapply(sotrunc_checks, function(f) f(x)))) { + return(x) + } + sotrunc_helper(x=x, ncol = ncol, nrow=nrow) + } +} + + +sotrunc_checks <- gsub("sotrunc", "is", methods(sotrunc)) +sotrunc_checks <- sapply(sotrunc_checks[sotrunc_checks != "is.default"], match.fun) + + +sotrunc_col <- function(x, ncol = 10) { + + if (!(ncol(x) <= ncol)) { + + firstc <- 1:(ncol - 4) + lastc <- ncol(x) + + core <- x[, firstc, drop=FALSE] + core <- cbind.data.frame(core, matrix(rep(".", nrow(core) * 3), ncol=3)) + lenc <- ncol(core) + colnames(core)[(lenc-2):lenc] <- "." + core <- cbind.data.frame(core, x[, lastc, drop=FALSE]) + + } else { + core <- x + } + + m <- capture.output(core) + space <- max(nchar(m)) - 1 + n <- data.frame(m[-1], stringsAsFactors = FALSE) + colnames(n) <- m[1] + n +} + + +sotrunc_row <- function(x, nrow = 15) { + + if (nrow(x) <= nrow) return(x) + + if (ncol(x) > 1 || !is.character(x[, 1]) || sum(diff(nchar(x[, 1]))) != 0){ + + m <- capture.output(x) + space <- max(nchar(m)) - 1 + x <- data.frame(m[-1], stringsAsFactors = FALSE) + colnames(x) <- m[1] + } + + firstr <- 1:(nrow - 3) + lastr <- nrow(x) + + m <- x[c(firstr, lastr), ] + + space <- max(nchar(m)) - 1 + m <- c(head(m, -1), paste0(rep(".", 3), paste(rep(" ", space), collapse ="")), tail(m, 1)) + + o <- data.frame(m[-1], stringsAsFactors = FALSE) + nms <- capture.output(x)[1] + tchar <- nchar(o[1,1]) + nmschar <- nchar(nms) + colnames(o) <- substring(nms, nmschar-(tchar - 1)) + print(o, quote=FALSE, row.names=FALSE) +} + +sotrunc_helper <- function(x, ncol = 10, nrow = 15){ + sotrunc_row(sotrunc_col(x, ncol = ncol), nrow = nrow) +} + + +sotrunc_list_helper <- function(x, ncol = 10, nrow=15){ + + lapply(x, function(y) { + + if (!any(sapply(sotrunc_checks, function(f) f(y)))) { + return(y) + } + + sotrunc(y, ncol = ncol, nrow=nrow) + }) +} + + + + + diff --git a/R/writeClip.R b/R/writeClip.R deleted file mode 100644 index 5a75d1c..0000000 --- a/R/writeClip.R +++ /dev/null @@ -1,31 +0,0 @@ -#' Write to clipboard on multiple OSes -#' -#' This function works on Windows, Mac and Linux. It copies a -#' character string or vector of characters to the clipboard and interprets -#' a vector of characters as one character with each element being newline -#' separated. If using Linux, xclip is used as the clipboard. So for the -#' function to work, xclip must be installed. -#' -#' @param object character. Character to be copied to the clipboard -#' -#' @return Returns nothing to R. Returns character string to the clipboard -#' -#' @details If using Linux, xclip will be used as the clipboard. To paste from -#' xclip, either use middle click or the command \code{xclip -o} in the shell. -#' - -writeClip <- function(object){ - OS <- Sys.info()["sysname"] - - if(!(OS %in% c("Darwin", "Windows", "Linux"))) stop("Copying to clipboard not yet supported on your OS") - - switch(OS, - "Darwin"={con <- pipe("pbcopy", "w") - writeLines(object, con=con) - close(con)}, - "Windows"=writeClipboard(object, format = 1), - "Linux"={if(Sys.which("xclip") == "") stop("Clipboard on Linux requires 'xclip'. Try using:\nsudo apt-get install xclip") - con <- pipe("xclip -i", "w") - writeLines(object, con=con) - close(con)}) -} \ No newline at end of file diff --git a/README.md b/README.md index 7ce74d6..1d1052d 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,108 @@ -oveRflow -======== +# overflow An R package to assist people answering R questions on Stack Overflow. -Authors: Sebastian Campbell, Ananda Mahto, Julien Barnier +Authors: Sebastian Campbell, Ananda Mahto, Julien Barnier, Tyler Rinker, Richard Cotton, Brodie Gaslam -Maintainer: Sebastian Campbell +Maintainer: Ananda Mahto -Contributor: Tyler Rinker +## Installation and Usage -Installation ------------- - -The easiest way to install this package is to use `install_github` from the `devtools` package: +The easiest way to install this package is to use `install_github`: ```R -library(devtools) -install_github("oveRflow", "sebastian-c") +source("http://news.mrdwab.com/install_github.R") +install_github("mrdwab/overflow-mrdwab") +``` + +Once installed, simply use the following to access the functions: + +``` +library(overflow) +``` + +## Functions + +### Main Functions + +Function|Description +-------|----------- +`soread`|Reads data directly from the clipboard and creates an object named "mydf" in your workspace. +`soanswer`|Writes a call and its output to the clipboard, already formatted for pasting into an answer at Stack Overflow. +`solast`|Captures the output from `.Last.value` along with the last expression from the history file and formats them in a manner suitable for posting on Stack Overflow. +`sodput`|A modified version of `dput` that copies your data to your clipboard, to be pasted into a question or an answer at Stack Overflow. +`sopkgs`|Temporarily installs a package in the current R session. + +### Additional Functions + +Function|Description +-------|--------- +`sotrunc`|Truncate the output of `data.frame`s, matrices, and lists. +`sorandf`|Function to create a random `data.frame`. It's probably better to just head over to [Tyler's "Wakefield" package](https://github.com/trinker/wakefield) rather than use this. + +## Examples + +Examples can be found in the "Examples" section of the relevant helpfile, but essentially, you get the following: + +### `soread` + +``` +## Copy the following text (select and ctrl-c) + +# A B +# 1 2 +# 3 4 +# 5 6 + +## Now, just type the following to create a data.frame in your workspace + +soread() + +## Copying tibbles (select from the line after `# A tibble: ...` and ctrl-c) + +# A tibble: 3 x 2 + A B + +1 1 5 +2 2 3 +3 3 11 + +soread(skipAfterHeader = TRUE, out = "mydf2") + +``` + +### `soanswer` + +``` +> soanswer(sin(2 * pi)) + sin(2 * pi) + ## [1] -2.449294e-16 ``` + +The output should automatically be copied to your clipboard to be pasted into an answer. + +### `sodput` + +``` +> sodput(mtcars, rows=1:6) + + mtcars <- structure(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1), cyl = c(6, + 6, 4, 6, 8, 6), disp = c(160, 160, 108, 258, 360, 225), hp = c(110, + 110, 93, 110, 175, 105), drat = c(3.9, 3.9, 3.85, 3.08, 3.15, + 2.76), wt = c(2.62, 2.875, 2.32, 3.215, 3.44, 3.46), qsec = c(16.46, + 17.02, 18.61, 19.44, 17.02, 20.22), vs = c(0, 0, 1, 1, 0, 1), + am = c(1, 1, 1, 0, 0, 0), gear = c(4, 4, 4, 3, 3, 3), carb = c(4, + 4, 1, 1, 2, 1)), .Names = c("mpg", "cyl", "disp", "hp", "drat", + "wt", "qsec", "vs", "am", "gear", "carb"), row.names = c("Mazda RX4", + "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", + "Valiant"), class = "data.frame") +``` + +The output should automatically be copied to your clipboard to be pasted into a question or an answer. + +-------------------- + +## Known Limitations + +- The features to read and write to the clipboard on Linux may be buggy. Be sure you have `xclip` installed. +- When you select data to be used with `soread`, you must ensure that you fully select the last line; failing to do so would lead to your dataset being truncated by one row. diff --git a/_pkgdown.yml b/_pkgdown.yml new file mode 100644 index 0000000..e69de29 diff --git a/docs/404.html b/docs/404.html new file mode 100644 index 0000000..9d727a6 --- /dev/null +++ b/docs/404.html @@ -0,0 +1,148 @@ + + + + + + + + +Page not found (404) • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+
+ + +Content not found. Please use links in the navbar. + +
+ + + +
+ + + +
+ + +
+

Site built with pkgdown 1.5.1.9000.

+
+ +
+
+ + + + + + + + diff --git a/docs/authors.html b/docs/authors.html new file mode 100644 index 0000000..e8c1ab9 --- /dev/null +++ b/docs/authors.html @@ -0,0 +1,167 @@ + + + + + + + + +Authors • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + +
+ +
+
+ + +
    +
  • +

    Sebastian Campbell. Author. +

    +
  • +
  • +

    Ananda Mahto. Author, maintainer. +

    +
  • +
  • +

    Julien Barnier. Author. +

    +
  • +
  • +

    Tyler Rinker. Author. +

    +
  • +
  • +

    Richard Cotton. Author. +

    +
  • +
  • +

    Brodie Gaslam. Author. +

    +
  • +
+ +
+ +
+ + + +
+ + +
+

Site built with pkgdown 1.5.1.9000.

+
+ +
+
+ + + + + + + + diff --git a/docs/bootstrap-toc.css b/docs/bootstrap-toc.css new file mode 100644 index 0000000..5a85941 --- /dev/null +++ b/docs/bootstrap-toc.css @@ -0,0 +1,60 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ + +/* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ + +/* All levels of nav */ +nav[data-toggle='toc'] .nav > li > a { + display: block; + padding: 4px 20px; + font-size: 13px; + font-weight: 500; + color: #767676; +} +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 19px; + color: #563d7c; + text-decoration: none; + background-color: transparent; + border-left: 1px solid #563d7c; +} +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 18px; + font-weight: bold; + color: #563d7c; + background-color: transparent; + border-left: 2px solid #563d7c; +} + +/* Nav: second level (shown on .active) */ +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} +nav[data-toggle='toc'] .nav .nav > li > a { + padding-top: 1px; + padding-bottom: 1px; + padding-left: 30px; + font-size: 12px; + font-weight: normal; +} +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 29px; +} +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 28px; + font-weight: 500; +} + +/* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ +nav[data-toggle='toc'] .nav > .active > ul { + display: block; +} diff --git a/docs/bootstrap-toc.js b/docs/bootstrap-toc.js new file mode 100644 index 0000000..1cdd573 --- /dev/null +++ b/docs/bootstrap-toc.js @@ -0,0 +1,159 @@ +/*! + * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) + * Copyright 2015 Aidan Feldman + * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ +(function() { + 'use strict'; + + window.Toc = { + helpers: { + // return all matching elements in the set, or their descendants + findOrFilter: function($el, selector) { + // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ + // http://stackoverflow.com/a/12731439/358804 + var $descendants = $el.find(selector); + return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); + }, + + generateUniqueIdBase: function(el) { + var text = $(el).text(); + var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); + return anchor || el.tagName.toLowerCase(); + }, + + generateUniqueId: function(el) { + var anchorBase = this.generateUniqueIdBase(el); + for (var i = 0; ; i++) { + var anchor = anchorBase; + if (i > 0) { + // add suffix + anchor += '-' + i; + } + // check if ID already exists + if (!document.getElementById(anchor)) { + return anchor; + } + } + }, + + generateAnchor: function(el) { + if (el.id) { + return el.id; + } else { + var anchor = this.generateUniqueId(el); + el.id = anchor; + return anchor; + } + }, + + createNavList: function() { + return $(''); + }, + + createChildNavList: function($parent) { + var $childList = this.createNavList(); + $parent.append($childList); + return $childList; + }, + + generateNavEl: function(anchor, text) { + var $a = $(''); + $a.attr('href', '#' + anchor); + $a.text(text); + var $li = $('
  • '); + $li.append($a); + return $li; + }, + + generateNavItem: function(headingEl) { + var anchor = this.generateAnchor(headingEl); + var $heading = $(headingEl); + var text = $heading.data('toc-text') || $heading.text(); + return this.generateNavEl(anchor, text); + }, + + // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). + getTopLevel: function($scope) { + for (var i = 1; i <= 6; i++) { + var $headings = this.findOrFilter($scope, 'h' + i); + if ($headings.length > 1) { + return i; + } + } + + return 1; + }, + + // returns the elements for the top level, and the next below it + getHeadings: function($scope, topLevel) { + var topSelector = 'h' + topLevel; + + var secondaryLevel = topLevel + 1; + var secondarySelector = 'h' + secondaryLevel; + + return this.findOrFilter($scope, topSelector + ',' + secondarySelector); + }, + + getNavLevel: function(el) { + return parseInt(el.tagName.charAt(1), 10); + }, + + populateNav: function($topContext, topLevel, $headings) { + var $context = $topContext; + var $prevNav; + + var helpers = this; + $headings.each(function(i, el) { + var $newNav = helpers.generateNavItem(el); + var navLevel = helpers.getNavLevel(el); + + // determine the proper $context + if (navLevel === topLevel) { + // use top level + $context = $topContext; + } else if ($prevNav && $context === $topContext) { + // create a new level of the tree and switch to it + $context = helpers.createChildNavList($prevNav); + } // else use the current $context + + $context.append($newNav); + + $prevNav = $newNav; + }); + }, + + parseOps: function(arg) { + var opts; + if (arg.jquery) { + opts = { + $nav: arg + }; + } else { + opts = arg; + } + opts.$scope = opts.$scope || $(document.body); + return opts; + } + }, + + // accepts a jQuery object, or an options object + init: function(opts) { + opts = this.helpers.parseOps(opts); + + // ensure that the data attribute is in place for styling + opts.$nav.attr('data-toggle', 'toc'); + + var $topContext = this.helpers.createChildNavList(opts.$nav); + var topLevel = this.helpers.getTopLevel(opts.$scope); + var $headings = this.helpers.getHeadings(opts.$scope, topLevel); + this.helpers.populateNav($topContext, topLevel, $headings); + } + }; + + $(function() { + $('nav[data-toggle="toc"]').each(function(i, el) { + var $nav = $(el); + Toc.init($nav); + }); + }); +})(); diff --git a/docs/docsearch.css b/docs/docsearch.css new file mode 100644 index 0000000..e5f1fe1 --- /dev/null +++ b/docs/docsearch.css @@ -0,0 +1,148 @@ +/* Docsearch -------------------------------------------------------------- */ +/* + Source: https://github.com/algolia/docsearch/ + License: MIT +*/ + +.algolia-autocomplete { + display: block; + -webkit-box-flex: 1; + -ms-flex: 1; + flex: 1 +} + +.algolia-autocomplete .ds-dropdown-menu { + width: 100%; + min-width: none; + max-width: none; + padding: .75rem 0; + background-color: #fff; + background-clip: padding-box; + border: 1px solid rgba(0, 0, 0, .1); + box-shadow: 0 .5rem 1rem rgba(0, 0, 0, .175); +} + +@media (min-width:768px) { + .algolia-autocomplete .ds-dropdown-menu { + width: 175% + } +} + +.algolia-autocomplete .ds-dropdown-menu::before { + display: none +} + +.algolia-autocomplete .ds-dropdown-menu [class^=ds-dataset-] { + padding: 0; + background-color: rgb(255,255,255); + border: 0; + max-height: 80vh; +} + +.algolia-autocomplete .ds-dropdown-menu .ds-suggestions { + margin-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion { + padding: 0; + overflow: visible +} + +.algolia-autocomplete .algolia-docsearch-suggestion--category-header { + padding: .125rem 1rem; + margin-top: 0; + font-size: 1.3em; + font-weight: 500; + color: #00008B; + border-bottom: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--wrapper { + float: none; + padding-top: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--subcategory-column { + float: none; + width: auto; + padding: 0; + text-align: left +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content { + float: none; + width: auto; + padding: 0 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--content::before { + display: none +} + +.algolia-autocomplete .ds-suggestion:not(:first-child) .algolia-docsearch-suggestion--category-header { + padding-top: .75rem; + margin-top: .75rem; + border-top: 1px solid rgba(0, 0, 0, .1) +} + +.algolia-autocomplete .ds-suggestion .algolia-docsearch-suggestion--subcategory-column { + display: block; + padding: .1rem 1rem; + margin-bottom: 0.1; + font-size: 1.0em; + font-weight: 400 + /* display: none */ +} + +.algolia-autocomplete .algolia-docsearch-suggestion--title { + display: block; + padding: .25rem 1rem; + margin-bottom: 0; + font-size: 0.9em; + font-weight: 400 +} + +.algolia-autocomplete .algolia-docsearch-suggestion--text { + padding: 0 1rem .5rem; + margin-top: -.25rem; + font-size: 0.8em; + font-weight: 400; + line-height: 1.25 +} + +.algolia-autocomplete .algolia-docsearch-footer { + width: 110px; + height: 20px; + z-index: 3; + margin-top: 10.66667px; + float: right; + font-size: 0; + line-height: 0; +} + +.algolia-autocomplete .algolia-docsearch-footer--logo { + background-image: url("data:image/svg+xml;utf8,"); + background-repeat: no-repeat; + background-position: 50%; + background-size: 100%; + overflow: hidden; + text-indent: -9000px; + width: 100%; + height: 100%; + display: block; + transform: translate(-8px); +} + +.algolia-autocomplete .algolia-docsearch-suggestion--highlight { + color: #FF8C00; + background: rgba(232, 189, 54, 0.1) +} + + +.algolia-autocomplete .algolia-docsearch-suggestion--text .algolia-docsearch-suggestion--highlight { + box-shadow: inset 0 -2px 0 0 rgba(105, 105, 105, .5) +} + +.algolia-autocomplete .ds-suggestion.ds-cursor .algolia-docsearch-suggestion--content { + background-color: rgba(192, 192, 192, .15) +} diff --git a/docs/docsearch.js b/docs/docsearch.js new file mode 100644 index 0000000..b35504c --- /dev/null +++ b/docs/docsearch.js @@ -0,0 +1,85 @@ +$(function() { + + // register a handler to move the focus to the search bar + // upon pressing shift + "/" (i.e. "?") + $(document).on('keydown', function(e) { + if (e.shiftKey && e.keyCode == 191) { + e.preventDefault(); + $("#search-input").focus(); + } + }); + + $(document).ready(function() { + // do keyword highlighting + /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ + var mark = function() { + + var referrer = document.URL ; + var paramKey = "q" ; + + if (referrer.indexOf("?") !== -1) { + var qs = referrer.substr(referrer.indexOf('?') + 1); + var qs_noanchor = qs.split('#')[0]; + var qsa = qs_noanchor.split('&'); + var keyword = ""; + + for (var i = 0; i < qsa.length; i++) { + var currentParam = qsa[i].split('='); + + if (currentParam.length !== 2) { + continue; + } + + if (currentParam[0] == paramKey) { + keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); + } + } + + if (keyword !== "") { + $(".contents").unmark({ + done: function() { + $(".contents").mark(keyword); + } + }); + } + } + }; + + mark(); + }); +}); + +/* Search term highlighting ------------------------------*/ + +function matchedWords(hit) { + var words = []; + + var hierarchy = hit._highlightResult.hierarchy; + // loop to fetch from lvl0, lvl1, etc. + for (var idx in hierarchy) { + words = words.concat(hierarchy[idx].matchedWords); + } + + var content = hit._highlightResult.content; + if (content) { + words = words.concat(content.matchedWords); + } + + // return unique words + var words_uniq = [...new Set(words)]; + return words_uniq; +} + +function updateHitURL(hit) { + + var words = matchedWords(hit); + var url = ""; + + if (hit.anchor) { + url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; + } else { + url = hit.url + '?q=' + escape(words.join(" ")); + } + + return url; +} diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..780688d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,274 @@ + + + + + + + +Utility functions for answering R question on StackOverflow • overflow + + + + + + + + + + +
    +
    + + + + +
    +
    +
    + +

    An R package to assist people answering R questions on Stack Overflow.

    +

    Authors: Sebastian Campbell, Ananda Mahto, Julien Barnier, Tyler Rinker, Richard Cotton, Brodie Gaslam

    +

    Maintainer: Ananda Mahto

    +
    +

    +Installation and Usage

    +

    The easiest way to install this package is to use install_github:

    +
    +source("http://news.mrdwab.com/install_github.R")
    +install_github("mrdwab/overflow-mrdwab")
    +
    +

    Once installed, simply use the following to access the functions:

    +
    library(overflow)
    +
    +
    +

    +Functions

    +
    +

    +Main Functions

    + ++++ + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FunctionDescription
    soreadReads data directly from the clipboard and creates an object named “mydf” in your workspace.
    soanswerWrites a call and its output to the clipboard, already formatted for pasting into an answer at Stack Overflow.
    solastCaptures the output from .Last.value along with the last expression from the history file and formats them in a manner suitable for posting on Stack Overflow.
    sodputA modified version of dput that copies your data to your clipboard, to be pasted into a question or an answer at Stack Overflow.
    sopkgsTemporarily installs a package in the current R session.
    +
    +
    +

    +Additional Functions

    + ++++ + + + + + + + + + + + + + + +
    FunctionDescription
    sotruncTruncate the output of data.frames, matrices, and lists.
    sorandfFunction to create a random data.frame. It’s probably better to just head over to Tyler’s “Wakefield” package rather than use this.
    +
    +
    +
    +

    +Examples

    +

    Examples can be found in the “Examples” section of the relevant helpfile, but essentially, you get the following:

    +
    +

    +soread +

    +
    ## Copy the following text (select and ctrl-c)
    +
    +# A B
    +# 1 2
    +# 3 4
    +# 5 6
    +
    +## Now, just type the following to create a data.frame in your workspace
    +
    +soread()
    +
    +## Copying tibbles (select from the line after `# A tibble: ...` and ctrl-c)
    +
    +# A tibble: 3 x 2
    +      A     B
    +  <dbl> <dbl>
    +1     1     5
    +2     2     3
    +3     3    11
    +
    +soread(skipAfterHeader = TRUE, out = "mydf2")
    +
    +
    +
    +

    +soanswer +

    +
    > soanswer(sin(2 * pi))
    +    sin(2 * pi)
    +    ## [1] -2.449294e-16
    +

    The output should automatically be copied to your clipboard to be pasted into an answer.

    +
    +
    +

    +sodput +

    +
    > sodput(mtcars, rows=1:6)
    +                                                                                  
    +     mtcars <- structure(list(mpg = c(21, 21, 22.8, 21.4, 18.7, 18.1), cyl = c(6, 
    +         6, 4, 6, 8, 6), disp = c(160, 160, 108, 258, 360, 225), hp = c(110,      
    +         110, 93, 110, 175, 105), drat = c(3.9, 3.9, 3.85, 3.08, 3.15,            
    +         2.76), wt = c(2.62, 2.875, 2.32, 3.215, 3.44, 3.46), qsec = c(16.46,     
    +         17.02, 18.61, 19.44, 17.02, 20.22), vs = c(0, 0, 1, 1, 0, 1),            
    +             am = c(1, 1, 1, 0, 0, 0), gear = c(4, 4, 4, 3, 3, 3), carb = c(4,    
    +             4, 1, 1, 2, 1)), .Names = c("mpg", "cyl", "disp", "hp", "drat",      
    +         "wt", "qsec", "vs", "am", "gear", "carb"), row.names = c("Mazda RX4",    
    +         "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout",    
    +         "Valiant"), class = "data.frame")  
    +

    The output should automatically be copied to your clipboard to be pasted into a question or an answer.

    +
    +
    +
    +
    +

    +Known Limitations

    +
      +
    • The features to read and write to the clipboard on Linux may be buggy. Be sure you have xclip installed.
    • +
    • When you select data to be used with soread, you must ensure that you fully select the last line; failing to do so would lead to your dataset being truncated by one row.
    • +
    +
    +
    +
    + + +
    + + +
    + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + diff --git a/docs/link.svg b/docs/link.svg new file mode 100644 index 0000000..88ad827 --- /dev/null +++ b/docs/link.svg @@ -0,0 +1,12 @@ + + + + + + diff --git a/docs/news/index.html b/docs/news/index.html new file mode 100644 index 0000000..76976c0 --- /dev/null +++ b/docs/news/index.html @@ -0,0 +1,188 @@ + + + + + + + + +Changelog • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    +overflow 0.2-4

    +
      +
    • Modified soread to allow skipping lines after header, for example when using with outpt from a tibble.
    • +
    +
    +
    +

    +overflow 0.2-3

    +
      +
    • +solast added to capture the output from .Last.value along with the last expression from the history.
    • +
    +
    +
    +

    +overflow 0.2-1

    +
      +
    • Added sorandf for creating random datasets.
    • +
    +
    +
    +

    +overflow 0.2-0

    +
      +
    • Renamed package from ‘oveRflow’ to ‘overflow’
    • +
    • Renamed function SOread, SOdput and tmp_install_packages tosoreadandsodputandsopkgs` for easier use.
    • +
    • New function: SOdput - Sends dput to clipboard with assignment operator.
    • +
    • readSO now strips out ## comments and leading whitespace.
    • +
    • Bugfix - tmp_install_packages no longer overwrites libraries which are not the base and user libraries.
    • +
    • New function: tmp_install_packages - installs packages to a temporary library.
    • +
    • Bugfix - readSO now works on Mac.
    • +
    +
    +
    +

    +overflow 0.1-0

    +
      +
    • New function: readSO - reads in data from StackOverflow.
    • +
    +
    +
    + + + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/pkgdown.css b/docs/pkgdown.css new file mode 100644 index 0000000..1273238 --- /dev/null +++ b/docs/pkgdown.css @@ -0,0 +1,367 @@ +/* Sticky footer */ + +/** + * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ + * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css + * + * .Site -> body > .container + * .Site-content -> body > .container .row + * .footer -> footer + * + * Key idea seems to be to ensure that .container and __all its parents__ + * have height set to 100% + * + */ + +html, body { + height: 100%; +} + +body { + position: relative; +} + +body > .container { + display: flex; + height: 100%; + flex-direction: column; +} + +body > .container .row { + flex: 1 0 auto; +} + +footer { + margin-top: 45px; + padding: 35px 0 36px; + border-top: 1px solid #e5e5e5; + color: #666; + display: flex; + flex-shrink: 0; +} +footer p { + margin-bottom: 0; +} +footer div { + flex: 1; +} +footer .pkgdown { + text-align: right; +} +footer p { + margin-bottom: 0; +} + +img.icon { + float: right; +} + +img { + max-width: 100%; +} + +/* Fix bug in bootstrap (only seen in firefox) */ +summary { + display: list-item; +} + +/* Typographic tweaking ---------------------------------*/ + +.contents .page-header { + margin-top: calc(-60px + 1em); +} + +dd { + margin-left: 3em; +} + +/* Section anchors ---------------------------------*/ + +a.anchor { + margin-left: -30px; + display:inline-block; + width: 30px; + height: 30px; + visibility: hidden; + + background-image: url(./link.svg); + background-repeat: no-repeat; + background-size: 20px 20px; + background-position: center center; +} + +.hasAnchor:hover a.anchor { + visibility: visible; +} + +@media (max-width: 767px) { + .hasAnchor:hover a.anchor { + visibility: hidden; + } +} + + +/* Fixes for fixed navbar --------------------------*/ + +.contents h1, .contents h2, .contents h3, .contents h4 { + padding-top: 60px; + margin-top: -40px; +} + +/* Navbar submenu --------------------------*/ + +.dropdown-submenu { + position: relative; +} + +.dropdown-submenu>.dropdown-menu { + top: 0; + left: 100%; + margin-top: -6px; + margin-left: -1px; + border-radius: 0 6px 6px 6px; +} + +.dropdown-submenu:hover>.dropdown-menu { + display: block; +} + +.dropdown-submenu>a:after { + display: block; + content: " "; + float: right; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; + border-width: 5px 0 5px 5px; + border-left-color: #cccccc; + margin-top: 5px; + margin-right: -10px; +} + +.dropdown-submenu:hover>a:after { + border-left-color: #ffffff; +} + +.dropdown-submenu.pull-left { + float: none; +} + +.dropdown-submenu.pull-left>.dropdown-menu { + left: -100%; + margin-left: 10px; + border-radius: 6px 0 6px 6px; +} + +/* Sidebar --------------------------*/ + +#pkgdown-sidebar { + margin-top: 30px; + position: -webkit-sticky; + position: sticky; + top: 70px; +} + +#pkgdown-sidebar h2 { + font-size: 1.5em; + margin-top: 1em; +} + +#pkgdown-sidebar h2:first-child { + margin-top: 0; +} + +#pkgdown-sidebar .list-unstyled li { + margin-bottom: 0.5em; +} + +/* bootstrap-toc tweaks ------------------------------------------------------*/ + +/* All levels of nav */ + +nav[data-toggle='toc'] .nav > li > a { + padding: 4px 20px 4px 6px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; +} + +nav[data-toggle='toc'] .nav > li > a:hover, +nav[data-toggle='toc'] .nav > li > a:focus { + padding-left: 5px; + color: inherit; + border-left: 1px solid #878787; +} + +nav[data-toggle='toc'] .nav > .active > a, +nav[data-toggle='toc'] .nav > .active:hover > a, +nav[data-toggle='toc'] .nav > .active:focus > a { + padding-left: 5px; + font-size: 1.5rem; + font-weight: 400; + color: inherit; + border-left: 2px solid #878787; +} + +/* Nav: second level (shown on .active) */ + +nav[data-toggle='toc'] .nav .nav { + display: none; /* Hide by default, but at >768px, show it */ + padding-bottom: 10px; +} + +nav[data-toggle='toc'] .nav .nav > li > a { + padding-left: 16px; + font-size: 1.35rem; +} + +nav[data-toggle='toc'] .nav .nav > li > a:hover, +nav[data-toggle='toc'] .nav .nav > li > a:focus { + padding-left: 15px; +} + +nav[data-toggle='toc'] .nav .nav > .active > a, +nav[data-toggle='toc'] .nav .nav > .active:hover > a, +nav[data-toggle='toc'] .nav .nav > .active:focus > a { + padding-left: 15px; + font-weight: 500; + font-size: 1.35rem; +} + +/* orcid ------------------------------------------------------------------- */ + +.orcid { + font-size: 16px; + color: #A6CE39; + /* margins are required by official ORCID trademark and display guidelines */ + margin-left:4px; + margin-right:4px; + vertical-align: middle; +} + +/* Reference index & topics ----------------------------------------------- */ + +.ref-index th {font-weight: normal;} + +.ref-index td {vertical-align: top; min-width: 100px} +.ref-index .icon {width: 40px;} +.ref-index .alias {width: 40%;} +.ref-index-icons .alias {width: calc(40% - 40px);} +.ref-index .title {width: 60%;} + +.ref-arguments th {text-align: right; padding-right: 10px;} +.ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} +.ref-arguments .name {width: 20%;} +.ref-arguments .desc {width: 80%;} + +/* Nice scrolling for wide elements --------------------------------------- */ + +table { + display: block; + overflow: auto; +} + +/* Syntax highlighting ---------------------------------------------------- */ + +pre { + word-wrap: normal; + word-break: normal; + border: 1px solid #eee; +} + +pre, code { + background-color: #f8f8f8; + color: #333; +} + +pre code { + overflow: auto; + word-wrap: normal; + white-space: pre; +} + +pre .img { + margin: 5px 0; +} + +pre .img img { + background-color: #fff; + display: block; + height: auto; +} + +code a, pre a { + color: #375f84; +} + +a.sourceLine:hover { + text-decoration: none; +} + +.fl {color: #1514b5;} +.fu {color: #000000;} /* function */ +.ch,.st {color: #036a07;} /* string */ +.kw {color: #264D66;} /* keyword */ +.co {color: #888888;} /* comment */ + +.message { color: black; font-weight: bolder;} +.error { color: orange; font-weight: bolder;} +.warning { color: #6A0366; font-weight: bolder;} + +/* Clipboard --------------------------*/ + +.hasCopyButton { + position: relative; +} + +.btn-copy-ex { + position: absolute; + right: 0; + top: 0; + visibility: hidden; +} + +.hasCopyButton:hover button.btn-copy-ex { + visibility: visible; +} + +/* headroom.js ------------------------ */ + +.headroom { + will-change: transform; + transition: transform 200ms linear; +} +.headroom--pinned { + transform: translateY(0%); +} +.headroom--unpinned { + transform: translateY(-100%); +} + +/* mark.js ----------------------------*/ + +mark { + background-color: rgba(255, 255, 51, 0.5); + border-bottom: 2px solid rgba(255, 153, 51, 0.3); + padding: 1px; +} + +/* vertical spacing after htmlwidgets */ +.html-widget { + margin-bottom: 10px; +} + +/* fontawesome ------------------------ */ + +.fab { + font-family: "Font Awesome 5 Brands" !important; +} + +/* don't display links in code chunks when printing */ +/* source: https://stackoverflow.com/a/10781533 */ +@media print { + code a:link:after, code a:visited:after { + content: ""; + } +} diff --git a/docs/pkgdown.js b/docs/pkgdown.js new file mode 100644 index 0000000..7e7048f --- /dev/null +++ b/docs/pkgdown.js @@ -0,0 +1,108 @@ +/* http://gregfranko.com/blog/jquery-best-practices/ */ +(function($) { + $(function() { + + $('.navbar-fixed-top').headroom(); + + $('body').css('padding-top', $('.navbar').height() + 10); + $(window).resize(function(){ + $('body').css('padding-top', $('.navbar').height() + 10); + }); + + $('[data-toggle="tooltip"]').tooltip(); + + var cur_path = paths(location.pathname); + var links = $("#navbar ul li a"); + var max_length = -1; + var pos = -1; + for (var i = 0; i < links.length; i++) { + if (links[i].getAttribute("href") === "#") + continue; + // Ignore external links + if (links[i].host !== location.host) + continue; + + var nav_path = paths(links[i].pathname); + + var length = prefix_length(nav_path, cur_path); + if (length > max_length) { + max_length = length; + pos = i; + } + } + + // Add class to parent
  • , and enclosing
  • if in dropdown + if (pos >= 0) { + var menu_anchor = $(links[pos]); + menu_anchor.parent().addClass("active"); + menu_anchor.closest("li.dropdown").addClass("active"); + } + }); + + function paths(pathname) { + var pieces = pathname.split("/"); + pieces.shift(); // always starts with / + + var end = pieces[pieces.length - 1]; + if (end === "index.html" || end === "") + pieces.pop(); + return(pieces); + } + + // Returns -1 if not found + function prefix_length(needle, haystack) { + if (needle.length > haystack.length) + return(-1); + + // Special case for length-0 haystack, since for loop won't run + if (haystack.length === 0) { + return(needle.length === 0 ? 0 : -1); + } + + for (var i = 0; i < haystack.length; i++) { + if (needle[i] != haystack[i]) + return(i); + } + + return(haystack.length); + } + + /* Clipboard --------------------------*/ + + function changeTooltipMessage(element, msg) { + var tooltipOriginalTitle=element.getAttribute('data-original-title'); + element.setAttribute('data-original-title', msg); + $(element).tooltip('show'); + element.setAttribute('data-original-title', tooltipOriginalTitle); + } + + if(ClipboardJS.isSupported()) { + $(document).ready(function() { + var copyButton = ""; + + $(".examples, div.sourceCode").addClass("hasCopyButton"); + + // Insert copy buttons: + $(copyButton).prependTo(".hasCopyButton"); + + // Initialize tooltips: + $('.btn-copy-ex').tooltip({container: 'body'}); + + // Initialize clipboard: + var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { + text: function(trigger) { + return trigger.parentNode.textContent; + } + }); + + clipboardBtnCopies.on('success', function(e) { + changeTooltipMessage(e.trigger, 'Copied!'); + e.clearSelection(); + }); + + clipboardBtnCopies.on('error', function() { + changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); + }); + }); + } +})(window.jQuery || window.$) diff --git a/docs/pkgdown.yml b/docs/pkgdown.yml new file mode 100644 index 0000000..c9d948c --- /dev/null +++ b/docs/pkgdown.yml @@ -0,0 +1,6 @@ +pandoc: '2.5' +pkgdown: 1.5.1.9000 +pkgdown_sha: caf7cc74e008e8d0d6e53eeda93cd3cad3545bf2 +articles: [] +last_built: 2020-06-19T23:46Z + diff --git a/docs/reference/index.html b/docs/reference/index.html new file mode 100644 index 0000000..f4a3f31 --- /dev/null +++ b/docs/reference/index.html @@ -0,0 +1,233 @@ + + + + + + + + +Function reference • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +

    All functions

    +

    +
    +

    lastcall()

    +

    Retrieve Last Call from History

    +

    overflow-package

    +

    Helper functions for answering R StackOverflow questions

    +

    readClip()

    +

    Read Clipboard Regardless of OS

    +

    soanswer()

    +

    Turn an R expression into an SO answer

    +

    sodput()

    +

    Create complete code to create an object and copy to clipboard

    +

    solast()

    +

    Capture Last Top Level Call And Output

    +

    sopkgs()

    +

    Temporarily install a package in the current R session

    +

    sorandf() sorandf_add() sorandf_reset()

    +

    Create random data.frame

    +

    soread()

    +

    Read in StackOverflow pasted table-formatted data

    +

    sotrunc()

    +

    Truncate the Output of Dataframes, Matrices and Lists

    +

    writeClip()

    +

    Write to Clipboard on Multiple OSes

    +
    + + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/lastcall.html b/docs/reference/lastcall.html new file mode 100644 index 0000000..89b9d4e --- /dev/null +++ b/docs/reference/lastcall.html @@ -0,0 +1,179 @@ + + + + + + + + +Retrieve Last Call from History — lastcall • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Returns the last call that was entered at the R prompt if it parsed +parsed successfully. Because the history file may contain unparseable lines +and because it may not start from the beginning of an R session, it is not +possible to guarantee that we will be able to correctly retrieve the last +command. This function will warn when it can retrieve a command but is not +certain the command is complete.

    +
    + +
    lastcall(max.lookback = 100L)
    + +

    Arguments

    + + + + + + +
    max.lookback

    integer(1L) how many lines of history to attempt to +parse back from the end of the history file

    + +

    Value

    + +

    language the last top level command, parsed

    +

    Author

    + +

    Brodie Gaslam

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/overflow-package.html b/docs/reference/overflow-package.html new file mode 100644 index 0000000..b639d85 --- /dev/null +++ b/docs/reference/overflow-package.html @@ -0,0 +1,158 @@ + + + + + + + + +Helper functions for answering R StackOverflow questions — overflow-package • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This package is focused on providing helper functions to answer StackOverflow +questions. It includes functions to transfer code and create random datasets.

    +
    + + + +

    Author

    + +

    Sebastian Campbell, Ananda Mahto, Julien Barnier, Tyler Rinker

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/readClip.html b/docs/reference/readClip.html new file mode 100644 index 0000000..5158c48 --- /dev/null +++ b/docs/reference/readClip.html @@ -0,0 +1,161 @@ + + + + + + + + +Read Clipboard Regardless of OS — readClip • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Different operating systems have different ways of handling the clipboard. +Given the frequency with which text is copied to the clipboard to place in +an answer on StackOverflow, this utility is provided.

    +
    + +
    readClip()
    + + +

    Value

    + +

    character string containing text on the clipboard.

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/soanswer.html b/docs/reference/soanswer.html new file mode 100644 index 0000000..d567d1c --- /dev/null +++ b/docs/reference/soanswer.html @@ -0,0 +1,207 @@ + + + + + + + + +Turn an R expression into an SO answer — soanswer • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Parrot the input expression and append the output with knitr-style comments, +all as markdown. soanswer changes the output for a single expression.

    +
    + +
    soanswer(expr, in_task_callback = FALSE)
    + +

    Arguments

    + + + + + + + + + + +
    expr

    An R expression.

    in_task_callback

    A logical value. Not intended for direct use.

    + +

    Value

    + +

    Markdown output is printed to the console, written to the clipboard +and silently returned as a noquote character vector.

    +

    See also

    + + +

    Author

    + +

    Richard Cotton

    + +

    Examples

    +
    # Output for various types, explicitly calling soanswer +soanswer(sin(2 * pi))
    #> sin(2 * pi) +#> ## [1] -2.449294e-16
    soanswer(sleep)
    #> sleep +#> ## extra group ID +#> ## 1 0.7 1 1 +#> ## 2 -1.6 1 2 +#> ## 3 -0.2 1 3 +#> ## 4 -1.2 1 4 +#> ## 5 -0.1 1 5 +#> ## 6 3.4 1 6 +#> ## 7 3.7 1 7 +#> ## 8 0.8 1 8 +#> ## 9 0.0 1 9 +#> ## 10 2.0 1 10 +#> ## 11 1.9 2 1 +#> ## 12 0.8 2 2 +#> ## 13 1.1 2 3 +#> ## 14 0.1 2 4 +#> ## 15 -0.1 2 5 +#> ## 16 4.4 2 6 +#> ## 17 5.5 2 7 +#> ## 18 1.6 2 8 +#> ## 19 4.6 2 9 +#> ## 20 3.4 2 10
    soanswer(message("A message!"))
    #> message("A message!") +#> ## A message!
    soanswer(warning("A warning!"))
    #> warning("A warning!") +#> ## Warning message: +#> ## A warning!
    soanswer(stop("An error!"))
    #> stop("An error!") +#> ## Error: An error!
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/sodput.html b/docs/reference/sodput.html new file mode 100644 index 0000000..06e847d --- /dev/null +++ b/docs/reference/sodput.html @@ -0,0 +1,185 @@ + + + + + + + + +Create complete code to create an object and copy to clipboard — sodput • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    In several cases, you may want to give a sample dataset. dput is a great tool for doing so. This tool takes +the dput output and places it on the clipboard, as well as adding an assignment operator.

    +
    + +
    sodput(object, rows = TRUE, indents = 4, mdformat = TRUE)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + +
    object

    R object to convert to code.

    rows

    numeric. Vector of row numbers. These rows will be produced in the output. +By default, all rows are included.

    indents

    integer. Spaces to be added before each line.

    mdformat

    logical. Whether or not to add 4 spaces before every line in order to format as a code block.

    + +

    Author

    + +

    Tyler Rinker

    + +

    Examples

    +
    if (FALSE) { +sodput(mtcars) +sodput(mtcars, rows=1:6) +}
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/solast.html b/docs/reference/solast.html new file mode 100644 index 0000000..0999f4c --- /dev/null +++ b/docs/reference/solast.html @@ -0,0 +1,210 @@ + + + + + + + + +Capture Last Top Level Call And Output — solast • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    Captures the output from .Last.value along with the last expression +from the history file and formats them in a manner suitable for posting on +Stack Overflow.

    +
    + +
    solast(silent = FALSE, clip = TRUE, drop.curly.brace = TRUE, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + +
    silent

    logical(1L) set to TRUE to suppress screen display

    clip

    logical(1L) set to TRUE (default) to attempt to write to system +clipboard

    drop.curly.brace

    if the last call is a call to {, drop it and +show only the contents (see examples)

    ...

    arguments to pass on to lastcall

    + +

    Value

    + +

    character, invisibly, the call and value together formatted for + posting on SO

    +

    Details

    + +

    If you the expression you want captured spans multiple lines, enclose them +in a call to {. The curly braces will be dropped from the display +to make it appear as if you typed all the commands sequentially into the R +prompt, though any interim output will not be captured.

    +

    Please note that the only output that is "captured" by this function is the +result of evaluating .Last.value. If there were warning, errors, or +other screen output during the actual expression evaluation those will not +show up here.

    +

    See also

    + +

    lastcall for limitations in capturing the last call

    +

    Author

    + +

    Andanda Mahto, Brodie Gaslam

    + +

    Examples

    +
    if (FALSE) { +1 + 1 +solast() +{ + x <- runif(20) + x + 3 +} +solast() +}
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/sopkgs.html b/docs/reference/sopkgs.html new file mode 100644 index 0000000..1bcfa4d --- /dev/null +++ b/docs/reference/sopkgs.html @@ -0,0 +1,200 @@ + + + + + + + + +Temporarily install a package in the current R session — sopkgs • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This function can be useful when a package is necessary to try to answer a question +on StackOverflow and you know that you won't need it anymore afterward. It will install +one or several packages only for the current R session.

    +
    + +
    sopkgs(package, dependencies = TRUE, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + +
    package

    character. A package name, or vector of package names.

    dependencies

    logical. Argument passed to install.packages. Defaults to TRUE.

    ...

    Other arguments passed to install.packages.

    + +

    Details

    + +

    The files are downloaded and installed in a temporary directory, and this +directory is temporarily added to the library tree within which packages are +looked for: (.libPaths). If you start another R session, the package +won't be accessible as it won't be in the library tree anymore, and as the +files are installed in a temporary directory they should be deleted upon next +reboot (this depends on your operating system).

    +

    Note

    + +

    You can find alternative functions in the original question and answers on +StackOverflow :

    + +

    http://stackoverflow.com/questions/14896941/install-an-r-package-temporarily-only-for-the-current-session

    +

    See also

    + + +

    Author

    + +

    Julien Barnier <julien@nozav.org>

    + +

    Examples

    +
    +if (FALSE) { +## Temporarily install the ggplot2 package in the current R session +sopkgs("ggplot2") +}
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/sorandf.html b/docs/reference/sorandf.html new file mode 100644 index 0000000..38a487a --- /dev/null +++ b/docs/reference/sorandf.html @@ -0,0 +1,222 @@ + + + + + + + + +Create random data.frame — sorandf • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    sorandf creates a data frame with columns corresponding to different +types of random data. It is intended for making reproducible examples easier.

    +
    + +
    sorandf(
    +  rows = 10L,
    +  cols = c("race", "gender", "age"),
    +  names = make.names(cols)
    +)
    +
    +sorandf_add(newf, name)
    +
    +sorandf_reset()
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + +
    rows

    integer. number of rows in data.frame.

    cols

    character. Vector of types of columns.

    names

    character. Vector of names of columns in data.frame output.

    newf

    function to add to sorandf functions. Must have just one +parameter, n.

    name

    character. Name to call new function.

    + +

    Details

    + +

    Each column must have a function defining it. It is possible to add + new functions using the sorandf_add function and reset back to the + defaults using the sorandf_reset function. Within this function, + there are a number of defaults which can be called by default:

    +

    id = function(n) paste0("ID.", 1:n)

    +

    group = function(n) sample(c("control", "treat"), n, replace = TRUE)

    +

    hs.grad = function(n) sample(c("yes", "no"), n, replace = TRUE)

    +

    race = function(n) sample(c("black", "white", "asian"), n, replace = + TRUE, prob=c(.25, .5, .25))

    +

    gender = function(n) sample(c("male", "female"), n, replace = TRUE)

    +

    age = function(n) sample(18:40, n, replace = TRUE)

    +

    m.status = function(n) sample(c("never", "married", "divorced", + "widowed"), n, replace = TRUE, prob=c(.25, .4, .3, .05))

    +

    political = function(n) sample(c("democrat", "republican", + "independent", "other"), n, replace= TRUE, prob=c(.35, .35, .20, .1))

    +

    n.kids = function(n) rpois(n, 1.5)

    +

    income = function(n) sample(c(seq(0, 30000, by=1000), seq(0, 150000, + by=1000)), n, replace=TRUE)

    +

    score = function(n) rnorm(n)

    +

    Author

    + +

    Sebastian Campbell, Tyler Rinker

    + +

    Examples

    +
    if (FALSE) { +sorandf(15, c("id", "age", "score"), names= c("card", "years", "points")) + +sorandf_add(function(n){sample(1:10, n)}, "newf") +sorandf(10, c("gender", "race", "newf")) +sorandf_reset() +} +
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/soread.html b/docs/reference/soread.html new file mode 100644 index 0000000..d17efa5 --- /dev/null +++ b/docs/reference/soread.html @@ -0,0 +1,230 @@ + + + + + + + + +Read in StackOverflow pasted table-formatted data — soread • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    A wrapper for read.table. Reads a table from text or from the clipboard and creates a data.frame from it.

    +
    + +
    soread(
    +  sep = "",
    +  header = TRUE,
    +  stringsAsFactors = FALSE,
    +  skipAfterHeader = NULL,
    +  out = "mydf"
    +)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + + + + + +
    sep

    character. Determines the field separator character passed +to read.table.

    header

    logical. Determines whether the first row consists of +names of variables.

    stringsAsFactors

    logical. Whether strings are converted to +factors or remain character variables. Defaults to `FALSE`

    skipAfterHeader

    numeric. Some newer print methods print additional +information just below the headers (for example, `tibble`s and `data.table`s). +If `skipAfterHeader = TRUE`, the second line will be removed. If +`skipAfterHeader` is a numeric value, those lines after the header row +will be removed before reading the data.

    out

    character. Desired output object name. Defaults to "mydf".

    + +

    Value

    + +

    A data.frame as read.table produces.

    +

    Details

    + +

    For many questions at Stack Overflow, the question asker does not properly +share their question (for example, using dput or by sharing +some commands to make up the data). Most of the time, you can just copy and +paste the text into R using read.table(text = "clipboard", header = +TRUE, stringsAsFactors = FALSE). This function is basically a convenience +function for the above.

    +

    The output of soread is automatically assigned to an object in +your workspace called "mydf" unless specified using the out +argument.

    +

    Note

    + +

    By default, `stringsAsFactors` is `FALSE` which is different to the R default +in R versions prior to 4.0.

    +

    See also

    + + +

    Author

    + +

    Ananda Mahto

    + +

    Examples

    +
    +if (FALSE) { +## Copy the following text (select and ctrl-c) + +# A B +# 1 2 +# 3 4 +# 5 6 + +## Now, just type: + +soread() +} +
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/sotrunc.html b/docs/reference/sotrunc.html new file mode 100644 index 0000000..05cb7e3 --- /dev/null +++ b/docs/reference/sotrunc.html @@ -0,0 +1,438 @@ + + + + + + + + +Truncate the Output of Dataframes, Matrices and Lists — sotrunc • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    A dispaly printing function that trunates data.frame/matrix by +adding ellipsis ... to take the place of non-displayed columns and rows.

    +
    + +
    sotrunc(x, ncol = 10, nrow = 15, ...)
    +
    +# S3 method for matrix
    +sotrunc(x, ncol = 10, nrow = 15, ...)
    +
    +# S3 method for data.frame
    +sotrunc(x, ncol = 10, nrow = 15, ...)
    +
    +# S3 method for list
    +sotrunc(x, ncol = 10, nrow = 15, ...)
    +
    +# S3 method for default
    +sotrunc(x, ncol = 10, nrow = 15, ...)
    + +

    Arguments

    + + + + + + + + + + + + + + + + + + +
    x

    An R object (usually a data.frame, matrix, or a +list that contains >= 1 data.frame/matrix.

    ncol

    The number of columns (including 3 columns displayed as ellipsis) +to display.

    nrow

    The number of rows (including 3 rows displayed as ellipsis) to +display.

    ...

    Other arguments passed to sotrunc.

    + +

    Value

    + +

    Prints a truncated display of the input.

    +

    Note

    + +

    This function is intended for truncated display. Please do not use to +gernarate your SSCCE +(Short, Self Contained, Correct (Compilable), Example).

    + +

    Examples

    +
    sotrunc(mtcars)
    #> mpg cyl disp hp drat wt . . . carb +#> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 . . . 4 +#> Datsun 710 22.8 4 108.0 93 3.85 2.320 . . . 1 +#> Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 . . . 1 +#> Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 . . . 2 +#> Valiant 18.1 6 225.0 105 2.76 3.460 . . . 1 +#> Duster 360 14.3 8 360.0 245 3.21 3.570 . . . 4 +#> Merc 240D 24.4 4 146.7 62 3.69 3.190 . . . 2 +#> Merc 230 22.8 4 140.8 95 3.92 3.150 . . . 2 +#> Merc 280 19.2 6 167.6 123 3.92 3.440 . . . 4 +#> Merc 280C 17.8 6 167.6 123 3.92 3.440 . . . 4 +#> Merc 450SE 16.4 8 275.8 180 3.07 4.070 . . . 3 +#> . +#> . +#> . +#> Volvo 142E 21.4 4 121.0 109 4.11 2.780 . . . 2
    sotrunc(mtcars, nrow = 6)
    #> mpg cyl disp hp drat wt . . . carb +#> Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 . . . 4 +#> Datsun 710 22.8 4 108.0 93 3.85 2.320 . . . 1 +#> . +#> . +#> . +#> Volvo 142E 21.4 4 121.0 109 4.11 2.780 . . . 2
    sotrunc(mtcars, ncol = 6)
    #> mpg cyl . . . carb +#> Mazda RX4 Wag 21.0 6 . . . 4 +#> Datsun 710 22.8 4 . . . 1 +#> Hornet 4 Drive 21.4 6 . . . 1 +#> Hornet Sportabout 18.7 8 . . . 2 +#> Valiant 18.1 6 . . . 1 +#> Duster 360 14.3 8 . . . 4 +#> Merc 240D 24.4 4 . . . 2 +#> Merc 230 22.8 4 . . . 2 +#> Merc 280 19.2 6 . . . 4 +#> Merc 280C 17.8 6 . . . 4 +#> Merc 450SE 16.4 8 . . . 3 +#> . +#> . +#> . +#> Volvo 142E 21.4 4 . . . 2
    sotrunc(CO2)
    #> Plant Type Treatment conc uptake +#> 2 Qn1 Quebec nonchilled 175 30.4 +#> 3 Qn1 Quebec nonchilled 250 34.8 +#> 4 Qn1 Quebec nonchilled 350 37.2 +#> 5 Qn1 Quebec nonchilled 500 35.3 +#> 6 Qn1 Quebec nonchilled 675 39.2 +#> 7 Qn1 Quebec nonchilled 1000 39.7 +#> 8 Qn2 Quebec nonchilled 95 13.6 +#> 9 Qn2 Quebec nonchilled 175 27.3 +#> 10 Qn2 Quebec nonchilled 250 37.1 +#> 11 Qn2 Quebec nonchilled 350 41.8 +#> 12 Qn2 Quebec nonchilled 500 40.6 +#> . +#> . +#> . +#> 84 Mc3 Mississippi chilled 1000 19.9
    sotrunc(lm(mpg~hp+am, data=mtcars))
    #> $coefficients +#> (Intercept) hp am +#> 26.5849137 -0.0588878 5.2770853 +#> +#> $residuals +#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive +#> -4.3843407 -4.3843407 -3.5854333 1.2927446 +#> Hornet Sportabout Valiant Duster 360 Merc 240D +#> 2.4204518 -2.3016944 2.1425981 1.4661301 +#> Merc 230 Merc 280 Merc 280C Merc 450SE +#> 1.8094276 -0.1417139 -1.5417139 0.4148909 +#> Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental +#> 1.3148909 -0.7851091 -4.1129141 -3.5240360 +#> Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla +#> 1.6592810 4.4245960 1.6001667 5.8657082 +#> Toyota Corona Dodge Challenger AMC Javelin Camaro Z28 +#> 0.6272032 -2.2517432 -2.5517432 1.1425981 +#> Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa +#> 2.9204518 -0.6754040 -0.5032090 5.1923227 +#> Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E +#> -0.5156190 -1.8566335 2.8654151 -4.0432285 +#> +#> $effects +#> (Intercept) hp am +#> -113.6497374 -26.0455922 -14.2209362 1.7568573 2.4493021 -1.8041000 +#> +#> 1.7027042 2.2516673 2.3739854 0.2353463 -1.1646537 0.4102594 +#> +#> 1.3102594 -0.7897406 -4.2849541 -3.7630396 1.3198323 5.9973147 +#> +#> 3.2666343 7.4451232 1.1783684 -2.0554843 -2.3554843 0.7027042 +#> +#> 2.9493021 0.8973147 0.9021012 6.4503132 -0.2687766 -1.0138163 +#> +#> 2.6368170 -2.7584526 +#> +#> $rank +#> [1] 3 +#> +#> $fitted.values +#> Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive +#> 25.38434 25.38434 26.38543 20.10726 +#> Hornet Sportabout Valiant Duster 360 Merc 240D +#> 16.27955 20.40169 12.15740 22.93387 +#> Merc 230 Merc 280 Merc 280C Merc 450SE +#> 20.99057 19.34171 19.34171 15.98511 +#> Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental +#> 15.98511 15.98511 14.51291 13.92404 +#> Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla +#> 13.04072 27.97540 28.79983 28.03429 +#> Toyota Corona Dodge Challenger AMC Javelin Camaro Z28 +#> 20.87280 17.75174 17.75174 12.15740 +#> Pontiac Firebird Fiat X1-9 Porsche 914-2 Lotus Europa +#> 16.27955 27.97540 26.50321 25.20768 +#> Ford Pantera L Ferrari Dino Maserati Bora Volvo 142E +#> 16.31562 21.55663 12.13458 25.44323 +#> +#> $assign +#> [1] 0 1 2 +#> +#> $qr +#> $qr +#> (Intercept) hp am +#> Mazda RX4 -5.6568542 -829.78980772 -2.29809704 +#> Mazda RX4 Wag 0.1767767 381.74189579 -0.67568560 +#> Datsun 710 0.1767767 0.12620114 -2.69484674 +#> Hornet 4 Drive 0.1767767 0.08166844 -0.21691576 +#> Hornet Sportabout 0.1767767 -0.08860368 -0.14797338 +#> Valiant 0.1767767 0.09476629 -0.22221902 +#> Duster 360 0.1767767 -0.27197365 -0.07372773 +#> Merc 240D 0.1767767 0.20740784 -0.26782706 +#> Merc 230 0.1767767 0.12096200 -0.23282554 +#> Merc 280 0.1767767 0.04761401 -0.20312728 +#> Merc 280C 0.1767767 0.04761401 -0.20312728 +#> Merc 450SE 0.1767767 -0.10170154 -0.14267012 +#> Merc 450SL 0.1767767 -0.10170154 -0.14267012 +#> Merc 450SLC 0.1767767 -0.10170154 -0.14267012 +#> Cadillac Fleetwood 0.1767767 -0.16719081 -0.11615381 +#> Lincoln Continental 0.1767767 -0.19338652 -0.10554729 +#> Chrysler Imperial 0.1767767 -0.23268009 -0.08963751 +#> Fiat 128 0.1767767 0.19692956 0.10749416 +#> Honda Civic 0.1767767 0.23360355 0.09264504 +#> Toyota Corolla 0.1767767 0.19954913 0.10643351 +#> Toyota Corona 0.1767767 0.11572286 -0.23070424 +#> Dodge Challenger 0.1767767 -0.02311440 -0.17448968 +#> AMC Javelin 0.1767767 -0.02311440 -0.17448968 +#> Camaro Z28 0.1767767 -0.27197365 -0.07372773 +#> Pontiac Firebird 0.1767767 -0.08860368 -0.14797338 +#> Fiat X1-9 0.1767767 0.19692956 0.10749416 +#> Porsche 914-2 0.1767767 0.13144028 0.13401047 +#> Lotus Europa 0.1767767 0.07380972 0.15734481 +#> Ford Pantera L 0.1767767 -0.32174550 0.31750327 +#> Ferrari Dino 0.1767767 -0.08860368 0.22310524 +#> Maserati Bora 0.1767767 -0.50773504 0.39280957 +#> Volvo 142E 0.1767767 0.08428801 0.15310220 +#> attr(,"assign") +#> [1] 0 1 2 +#> +#> $qraux +#> [1] 1.176777 1.081668 1.136132 +#> +#> $pivot +#> [1] 1 2 3 +#> +#> $tol +#> [1] 1e-07 +#> +#> $rank +#> [1] 3 +#> +#> attr(,"class") +#> [1] "qr" +#> +#> $df.residual +#> [1] 29 +#> +#> $xlevels +#> named list() +#> +#> $call +#> lm(formula = mpg ~ hp + am, data = mtcars) +#> +#> $terms +#> mpg ~ hp + am +#> attr(,"variables") +#> list(mpg, hp, am) +#> attr(,"factors") +#> hp am +#> mpg 0 0 +#> hp 1 0 +#> am 0 1 +#> attr(,"term.labels") +#> [1] "hp" "am" +#> attr(,"order") +#> [1] 1 1 +#> attr(,"intercept") +#> [1] 1 +#> attr(,"response") +#> [1] 1 +#> attr(,".Environment") +#> <environment: 0x5579bfac37d8> +#> attr(,"predvars") +#> list(mpg, hp, am) +#> attr(,"dataClasses") +#> mpg hp am +#> "numeric" "numeric" "numeric" +#> +#> $model +#> mpg hp am +#> Mazda RX4 21.0 110 1 +#> Mazda RX4 Wag 21.0 110 1 +#> Datsun 710 22.8 93 1 +#> Hornet 4 Drive 21.4 110 0 +#> Hornet Sportabout 18.7 175 0 +#> Valiant 18.1 105 0 +#> Duster 360 14.3 245 0 +#> Merc 240D 24.4 62 0 +#> Merc 230 22.8 95 0 +#> Merc 280 19.2 123 0 +#> Merc 280C 17.8 123 0 +#> Merc 450SE 16.4 180 0 +#> Merc 450SL 17.3 180 0 +#> Merc 450SLC 15.2 180 0 +#> Cadillac Fleetwood 10.4 205 0 +#> Lincoln Continental 10.4 215 0 +#> Chrysler Imperial 14.7 230 0 +#> Fiat 128 32.4 66 1 +#> Honda Civic 30.4 52 1 +#> Toyota Corolla 33.9 65 1 +#> Toyota Corona 21.5 97 0 +#> Dodge Challenger 15.5 150 0 +#> AMC Javelin 15.2 150 0 +#> Camaro Z28 13.3 245 0 +#> Pontiac Firebird 19.2 175 0 +#> Fiat X1-9 27.3 66 1 +#> Porsche 914-2 26.0 91 1 +#> Lotus Europa 30.4 113 1 +#> Ford Pantera L 15.8 264 1 +#> Ferrari Dino 19.7 175 1 +#> Maserati Bora 15.0 335 1 +#> Volvo 142E 21.4 109 1 +#>
    sotrunc(1:10)
    #> [1] 1 2 3 4 5 6 7 8 9 10
    sotrunc(mtcars[1:5, 1:5])
    #> mpg cyl disp hp drat +#> 1 Mazda RX4 21.0 6 160 110 3.90 +#> 2 Mazda RX4 Wag 21.0 6 160 110 3.90 +#> 3 Datsun 710 22.8 4 108 93 3.85 +#> 4 Hornet 4 Drive 21.4 6 258 110 3.08 +#> 5 Hornet Sportabout 18.7 8 360 175 3.15
    +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/docs/reference/writeClip.html b/docs/reference/writeClip.html new file mode 100644 index 0000000..7d9bb5f --- /dev/null +++ b/docs/reference/writeClip.html @@ -0,0 +1,177 @@ + + + + + + + + +Write to Clipboard on Multiple OSes — writeClip • overflow + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    +
    + + + + +
    + +
    +
    + + +
    +

    This function works on Windows, Mac and Linux. It copies a +character string or vector of characters to the clipboard and interprets +a vector of characters as one character with each element being newline +separated. If using Linux, xclip is used as the clipboard. So for the +function to work, xclip must be installed.

    +
    + +
    writeClip(object)
    + +

    Arguments

    + + + + + + +
    object

    character. Character to be copied to the clipboard

    + +

    Value

    + +

    Returns nothing to R. Returns character string to the clipboard

    +

    Details

    + +

    If using Linux, xclip will be used as the clipboard. To paste from +xclip, either use middle click or the command xclip -o in the shell.

    + +
    + +
    + + +
    + + +
    +

    Site built with pkgdown 1.5.1.9000.

    +
    + +
    +
    + + + + + + + + diff --git a/man/SOdput.Rd b/man/SOdput.Rd deleted file mode 100644 index 26ab26f..0000000 --- a/man/SOdput.Rd +++ /dev/null @@ -1,35 +0,0 @@ -\name{SOdput} -\alias{SOdput} -\title{Create complete code to create an object and copy to clipboard} -\usage{ - SOdput(object, rows = TRUE, indents = 4, mdformat = TRUE) -} -\arguments{ - \item{object}{R object to convert to code} - - \item{rows}{numeric. Vector of row numbers. These rows - will be produced in the output. By default, all rows are - included.} - - \item{indents}{integer. Spaces to be added before each - line} - - \item{mdformat}{logical. Whether or not to add 4 spaces - before every line in order to format as a code block.} -} -\description{ - In several cases, you may want to give a sample dataset. - \code{dput} is a great tool for doing so. This tool takes - the \code{dput} output and places it on the clipboard, as - well as adding an assignment operator. -} -\examples{ -\dontrun{ -SOdput(mtcars) -SOdput(mtcars, rows=1:6) -} -} -\author{ - Tyler Rinker -} - diff --git a/man/lastcall.Rd b/man/lastcall.Rd new file mode 100644 index 0000000..3335476 --- /dev/null +++ b/man/lastcall.Rd @@ -0,0 +1,26 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/solast.R +\name{lastcall} +\alias{lastcall} +\title{Retrieve Last Call from History} +\usage{ +lastcall(max.lookback = 100L) +} +\arguments{ +\item{max.lookback}{integer(1L) how many lines of history to attempt to +parse back from the end of the history file} +} +\value{ +language the last top level command, parsed +} +\description{ +Returns the last call that was entered at the R prompt if it parsed +parsed successfully. Because the history file may contain unparseable lines +and because it may not start from the beginning of an R session, it is not +possible to guarantee that we will be able to correctly retrieve the last +command. This function will warn when it can retrieve a command but is not +certain the command is complete. +} +\author{ +Brodie Gaslam +} diff --git a/man/overflow-package.Rd b/man/overflow-package.Rd new file mode 100644 index 0000000..6e03f2a --- /dev/null +++ b/man/overflow-package.Rd @@ -0,0 +1,14 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/package.R +\docType{package} +\name{overflow-package} +\alias{overflow-package} +\alias{overflow} +\title{Helper functions for answering R StackOverflow questions} +\description{ +This package is focused on providing helper functions to answer StackOverflow +questions. It includes functions to transfer code and create random datasets. +} +\author{ +Sebastian Campbell, Ananda Mahto, Julien Barnier, Tyler Rinker +} diff --git a/man/readClip.Rd b/man/readClip.Rd index 9ab9bd7..54a1886 100644 --- a/man/readClip.Rd +++ b/man/readClip.Rd @@ -1,16 +1,16 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/clipboard.R \name{readClip} \alias{readClip} -\title{Read clipboard regardless of OS} +\title{Read Clipboard Regardless of OS} \usage{ - readClip() +readClip() } \value{ - character string containing text on the clipboard. +character string containing text on the clipboard. } \description{ - Different operating systems have different ways of - handling the clipboard. Given the frequency with which - text is copied to the clipboard to place in an answer on - StackOverflow, this utility is provided. +Different operating systems have different ways of handling the clipboard. +Given the frequency with which text is copied to the clipboard to place in +an answer on StackOverflow, this utility is provided. } - diff --git a/man/readSO.Rd b/man/readSO.Rd deleted file mode 100644 index 6eace08..0000000 --- a/man/readSO.Rd +++ /dev/null @@ -1,67 +0,0 @@ -\name{readSO} -\alias{readSO} -\title{Read in StackOverflow pasted table-formatted data} -\usage{ - readSO(sep = "", header = TRUE, stringsAsFactors = FALSE, - out = "mydf") -} -\arguments{ - \item{sep}{character. Determines the field separator - character passed to \code{read.table}.} - - \item{header}{logical. Determines whether the first row - consists of names of variables.} - - \item{stringsAsFactors}{logical. Whether strings are - converted to factors or remain character variables.} - - \item{out}{character. Desired output object name. - Defaults to \code{"mydf"}.} -} -\value{ - A data.frame as \code{read.table} produces. -} -\description{ - A wrapper for \link{read.table}. Reads a table from text - or from the clipboard and creates a data.frame from it. -} -\details{ - For many questions at Stack Overflow, the question asker - does not properly share their question (for example, - using \code{\link{dput}} or by sharing some commands to - make up the data). Most of the time, you can just copy - and paste the text into R using \code{read.table(text = - "clipboard", header = TRUE, stringsAsFactors = FALSE)}. - This function is basically a convenience function for the - above. - - The output of \code{\link{readSO}} is automatically - assigned to an object in your workspace called - "\code{mydf}" unless specified using the \code{out} - argument. -} -\note{ - By default, stringsAsFactors is FALSE which is different - to the R default. -} -\examples{ -\dontrun{ -## Copy the following text (select and ctrl-c) - -# A B -# 1 2 -# 3 4 -# 5 6 - -## Now, just type: - -readSO() -} -} -\author{ - Ananda Mahto -} -\seealso{ - \code{\link{dput}}, \code{\link{read.table}} -} - diff --git a/man/soanswer.Rd b/man/soanswer.Rd new file mode 100644 index 0000000..f9c9c49 --- /dev/null +++ b/man/soanswer.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/soanswer.R +\name{soanswer} +\alias{soanswer} +\title{Turn an R expression into an SO answer} +\usage{ +soanswer(expr, in_task_callback = FALSE) +} +\arguments{ +\item{expr}{An R expression.} + +\item{in_task_callback}{A logical value. Not intended for direct use.} +} +\value{ +Markdown output is printed to the console, written to the clipboard +and silently returned as a \code{noquote} character vector. +} +\description{ +Parrot the input expression and append the output with knitr-style comments, +all as markdown. \code{soanswer} changes the output for a single expression. +} +\examples{ +# Output for various types, explicitly calling soanswer +soanswer(sin(2 * pi)) +soanswer(sleep) +soanswer(message("A message!")) +soanswer(warning("A warning!")) +soanswer(stop("An error!")) +} +\seealso{ +\code{\link[base]{addTaskCallback}} +} +\author{ +Richard Cotton +} diff --git a/man/sodput.Rd b/man/sodput.Rd new file mode 100644 index 0000000..6a5c032 --- /dev/null +++ b/man/sodput.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sodput.R +\name{sodput} +\alias{sodput} +\title{Create complete code to create an object and copy to clipboard} +\usage{ +sodput(object, rows = TRUE, indents = 4, mdformat = TRUE) +} +\arguments{ +\item{object}{R object to convert to code.} + +\item{rows}{numeric. Vector of row numbers. These rows will be produced in the output. +By default, all rows are included.} + +\item{indents}{integer. Spaces to be added before each line.} + +\item{mdformat}{logical. Whether or not to add 4 spaces before every line in order to format as a code block.} +} +\description{ +In several cases, you may want to give a sample dataset. \code{dput} is a great tool for doing so. This tool takes +the \code{dput} output and places it on the clipboard, as well as adding an assignment operator. +} +\examples{ +\dontrun{ +sodput(mtcars) +sodput(mtcars, rows=1:6) +} +} +\author{ +Tyler Rinker +} diff --git a/man/solast.Rd b/man/solast.Rd new file mode 100644 index 0000000..49c5bf5 --- /dev/null +++ b/man/solast.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/solast.R +\name{solast} +\alias{solast} +\title{Capture Last Top Level Call And Output} +\usage{ +solast(silent = FALSE, clip = TRUE, drop.curly.brace = TRUE, ...) +} +\arguments{ +\item{silent}{logical(1L) set to TRUE to suppress screen display} + +\item{clip}{logical(1L) set to TRUE (default) to attempt to write to system +clipboard} + +\item{drop.curly.brace}{if the last call is a call to \code{\{}, drop it and +show only the contents (see examples)} + +\item{...}{arguments to pass on to \code{\link{lastcall}}} +} +\value{ +character, invisibly, the call and value together formatted for + posting on SO +} +\description{ +Captures the output from \code{.Last.value} along with the last expression +from the history file and formats them in a manner suitable for posting on +Stack Overflow. +} +\details{ +If you the expression you want captured spans multiple lines, enclose them +in a call to \code{\{}. The curly braces will be dropped from the display +to make it appear as if you typed all the commands sequentially into the R +prompt, though any interim output will not be captured. + +Please note that the only output that is "captured" by this function is the +result of evaluating \code{.Last.value}. If there were warning, errors, or +other screen output during the actual expression evaluation those will not +show up here. +} +\examples{ +\dontrun{ +1 + 1 +solast() +{ + x <- runif(20) + x + 3 +} +solast() +} +} +\seealso{ +\code{\link{lastcall}} for limitations in capturing the last call +} +\author{ +Andanda Mahto, Brodie Gaslam +} diff --git a/man/sopkgs.Rd b/man/sopkgs.Rd new file mode 100644 index 0000000..13207ea --- /dev/null +++ b/man/sopkgs.Rd @@ -0,0 +1,48 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sopkgs.R +\name{sopkgs} +\alias{sopkgs} +\title{Temporarily install a package in the current R session} +\usage{ +sopkgs(package, dependencies = TRUE, ...) +} +\arguments{ +\item{package}{character. A package name, or vector of package names.} + +\item{dependencies}{logical. Argument passed to \code{install.packages}. Defaults to TRUE.} + +\item{...}{Other arguments passed to \code{install.packages}.} +} +\description{ +This function can be useful when a package is necessary to try to answer a question +on StackOverflow and you know that you won't need it anymore afterward. It will install +one or several packages only for the current R session. +} +\details{ +The files are downloaded and installed in a temporary directory, and this +directory is temporarily added to the library tree within which packages are +looked for: (\code{.libPaths}). If you start another R session, the package +won't be accessible as it won't be in the library tree anymore, and as the +files are installed in a temporary directory they should be deleted upon next +reboot (this depends on your operating system). +} +\note{ +You can find alternative functions in the original question and answers on +StackOverflow : + + +\url{http://stackoverflow.com/questions/14896941/install-an-r-package-temporarily-only-for-the-current-session} +} +\examples{ + +\dontrun{ +## Temporarily install the ggplot2 package in the current R session +sopkgs("ggplot2") +} +} +\seealso{ +\code{\link{install.packages}}, \code{\link{.libPaths}} +} +\author{ +Julien Barnier +} diff --git a/man/sorandf.Rd b/man/sorandf.Rd new file mode 100644 index 0000000..681520d --- /dev/null +++ b/man/sorandf.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sorandf.R +\name{sorandf} +\alias{sorandf} +\alias{sorandf_add} +\alias{sorandf_reset} +\title{Create random data.frame} +\usage{ +sorandf( + rows = 10L, + cols = c("race", "gender", "age"), + names = make.names(cols) +) + +sorandf_add(newf, name) + +sorandf_reset() +} +\arguments{ +\item{rows}{integer. number of rows in data.frame.} + +\item{cols}{character. Vector of types of columns.} + +\item{names}{character. Vector of names of columns in data.frame output.} + +\item{newf}{function to add to sorandf functions. Must have just one +parameter, n.} + +\item{name}{character. Name to call new function.} +} +\description{ +\code{sorandf} creates a data frame with columns corresponding to different +types of random data. It is intended for making reproducible examples easier. +} +\details{ +Each column must have a function defining it. It is possible to add + new functions using the \code{sorandf_add} function and reset back to the + defaults using the \code{sorandf_reset} function. Within this function, + there are a number of defaults which can be called by default: + + \code{id = function(n) paste0("ID.", 1:n)} + + \code{group = function(n) sample(c("control", "treat"), n, replace = TRUE)} + + \code{hs.grad = function(n) sample(c("yes", "no"), n, replace = TRUE)} + + \code{race = function(n) sample(c("black", "white", "asian"), n, replace = + TRUE, prob=c(.25, .5, .25))} + + \code{gender = function(n) sample(c("male", "female"), n, replace = TRUE)} + + \code{age = function(n) sample(18:40, n, replace = TRUE)} + + \code{m.status = function(n) sample(c("never", "married", "divorced", + "widowed"), n, replace = TRUE, prob=c(.25, .4, .3, .05))} + + \code{political = function(n) sample(c("democrat", "republican", + "independent", "other"), n, replace= TRUE, prob=c(.35, .35, .20, .1))} + + \code{n.kids = function(n) rpois(n, 1.5)} + + \code{income = function(n) sample(c(seq(0, 30000, by=1000), seq(0, 150000, + by=1000)), n, replace=TRUE)} + + \code{score = function(n) rnorm(n)} +} +\examples{ +\dontrun{ +sorandf(15, c("id", "age", "score"), names= c("card", "years", "points")) + +sorandf_add(function(n){sample(1:10, n)}, "newf") +sorandf(10, c("gender", "race", "newf")) +sorandf_reset() +} + +} +\author{ +Sebastian Campbell, Tyler Rinker +} diff --git a/man/soread.Rd b/man/soread.Rd new file mode 100644 index 0000000..f793bfa --- /dev/null +++ b/man/soread.Rd @@ -0,0 +1,76 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/soread.R +\name{soread} +\alias{soread} +\title{Read in StackOverflow pasted table-formatted data} +\usage{ +soread( + sep = "", + header = TRUE, + stringsAsFactors = FALSE, + skipAfterHeader = NULL, + out = "mydf" +) +} +\arguments{ +\item{sep}{character. Determines the field separator character passed +to \code{read.table}.} + +\item{header}{logical. Determines whether the first row consists of +names of variables.} + +\item{stringsAsFactors}{logical. Whether strings are converted to +factors or remain character variables. Defaults to `FALSE`} + +\item{skipAfterHeader}{numeric. Some newer print methods print additional +information just below the headers (for example, `tibble`s and `data.table`s). +If `skipAfterHeader = TRUE`, the second line will be removed. If +`skipAfterHeader` is a numeric value, those lines after the header row +will be removed before reading the data.} + +\item{out}{character. Desired output object name. Defaults to \code{"mydf"}.} +} +\value{ +A data.frame as \code{read.table} produces. +} +\description{ +A wrapper for \link{read.table}. Reads a table from text or from the clipboard and creates a data.frame from it. +} +\details{ +For many questions at Stack Overflow, the question asker does not properly +share their question (for example, using \code{\link{dput}} or by sharing +some commands to make up the data). Most of the time, you can just copy and +paste the text into R using \code{read.table(text = "clipboard", header = +TRUE, stringsAsFactors = FALSE)}. This function is basically a convenience +function for the above. + +The output of \code{\link{soread}} is automatically assigned to an object in +your workspace called "\code{mydf}" unless specified using the \code{out} +argument. +} +\note{ +By default, `stringsAsFactors` is `FALSE` which is different to the R default +in R versions prior to 4.0. +} +\examples{ + +\dontrun{ +## Copy the following text (select and ctrl-c) + +# A B +# 1 2 +# 3 4 +# 5 6 + +## Now, just type: + +soread() +} + +} +\seealso{ +\code{\link{dput}}, \code{\link{read.table}} +} +\author{ +Ananda Mahto +} diff --git a/man/sotrunc.Rd b/man/sotrunc.Rd new file mode 100644 index 0000000..5a6746a --- /dev/null +++ b/man/sotrunc.Rd @@ -0,0 +1,54 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/sotrunc.R +\name{sotrunc} +\alias{sotrunc} +\alias{sotrunc.matrix} +\alias{sotrunc.data.frame} +\alias{sotrunc.list} +\alias{sotrunc.default} +\title{Truncate the Output of Dataframes, Matrices and Lists} +\usage{ +sotrunc(x, ncol = 10, nrow = 15, ...) + +\method{sotrunc}{matrix}(x, ncol = 10, nrow = 15, ...) + +\method{sotrunc}{data.frame}(x, ncol = 10, nrow = 15, ...) + +\method{sotrunc}{list}(x, ncol = 10, nrow = 15, ...) + +\method{sotrunc}{default}(x, ncol = 10, nrow = 15, ...) +} +\arguments{ +\item{x}{An R object (usually a \code{data.frame}, \code{matrix}, or a +\code{list} that contains >= 1 \code{data.frame}/\code{matrix}.} + +\item{ncol}{The number of columns (including 3 columns displayed as ellipsis) +to display.} + +\item{nrow}{The number of rows (including 3 rows displayed as ellipsis) to +display.} + +\item{\ldots}{Other arguments passed to \code{sotrunc}.} +} +\value{ +Prints a truncated display of the input. +} +\description{ +A dispaly printing function that trunates \code{data.frame}/\code{matrix} by +adding ellipsis \ldots to take the place of non-displayed columns and rows. +} +\note{ +This function is intended for truncated display. Please do not use to +gernarate your \href{http://sscce.org/}{SSCCE} +(Short, Self Contained, Correct (Compilable), Example). +} +\examples{ +sotrunc(mtcars) +sotrunc(mtcars, nrow = 6) +sotrunc(mtcars, ncol = 6) +sotrunc(CO2) +sotrunc(lm(mpg~hp+am, data=mtcars)) +sotrunc(1:10) +sotrunc(mtcars[1:5, 1:5]) +} +\keyword{truncate} diff --git a/man/tmp_install_packages.Rd b/man/tmp_install_packages.Rd deleted file mode 100644 index c4b434b..0000000 --- a/man/tmp_install_packages.Rd +++ /dev/null @@ -1,51 +0,0 @@ -\name{tmp_install_packages} -\alias{tmp_install_packages} -\title{Temporarily install a package in the current R session} -\usage{ - tmp_install_packages(package, dependencies = TRUE, ...) -} -\arguments{ - \item{package}{character. A package name, or vector of - package names.} - - \item{dependencies}{logical. Argument passed to - \code{install.packages}. Defaults to TRUE.} - - \item{...}{other arguments passed to - \code{install.packages}.} -} -\description{ - This function can be useful when a package is necessary - to try to answer a question on StackOverflow and you know - that you won't need it anymore afterward. It will install - one or several packages only for the current R session. -} -\details{ - The files are downloaded and installed in a temporary - directory, and this directory is temporarily added to the - library tree within which packages are looked for: - (\code{.libPaths}). If you start another R session, the - package won't be accessible as it won't be in the library - tree anymore, and as the files are installed in a - temporary directory they should be deleted upon next - reboot (this depends on your operating system). -} -\note{ - You can find alternative functions in the original - question and answers on StackOverflow : - - \url{http://stackoverflow.com/questions/14896941/install-an-r-package-temporarily-only-for-the-current-session} -} -\examples{ -\dontrun{ -## Temporarily install the ggplot2 package in the current R session -tmp_install_packages("ggplot2") -} -} -\author{ - Julien Barnier -} -\seealso{ - \code{\link{install.packages}}, \code{\link{.libPaths}} -} - diff --git a/man/writeClip.Rd b/man/writeClip.Rd index fc87bf1..236adcc 100644 --- a/man/writeClip.Rd +++ b/man/writeClip.Rd @@ -1,28 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/clipboard.R \name{writeClip} \alias{writeClip} -\title{Write to clipboard on multiple OSes} +\title{Write to Clipboard on Multiple OSes} \usage{ - writeClip(object) +writeClip(object) } \arguments{ - \item{object}{character. Character to be copied to the - clipboard} +\item{object}{character. Character to be copied to the clipboard} } \value{ - Returns nothing to R. Returns character string to the - clipboard +Returns nothing to R. Returns character string to the clipboard } \description{ - This function works on Windows, Mac and Linux. It copies - a character string or vector of characters to the - clipboard and interprets a vector of characters as one - character with each element being newline separated. If - using Linux, xclip is used as the clipboard. So for the - function to work, xclip must be installed. +This function works on Windows, Mac and Linux. It copies a +character string or vector of characters to the clipboard and interprets +a vector of characters as one character with each element being newline +separated. If using Linux, xclip is used as the clipboard. So for the +function to work, xclip must be installed. } \details{ - If using Linux, xclip will be used as the clipboard. To - paste from xclip, either use middle click or the command - \code{xclip -o} in the shell. +If using Linux, xclip will be used as the clipboard. To paste from +xclip, either use middle click or the command \code{xclip -o} in the shell. } - diff --git a/overflow-mrdwab.Rproj b/overflow-mrdwab.Rproj new file mode 100644 index 0000000..1788e68 --- /dev/null +++ b/overflow-mrdwab.Rproj @@ -0,0 +1,18 @@ +Version: 1.0 + +RestoreWorkspace: Default +SaveWorkspace: Default +AlwaysSaveHistory: Default + +EnableCodeIndexing: Yes +UseSpacesForTab: Yes +NumSpacesForTab: 2 +Encoding: UTF-8 + +RnwWeave: Sweave +LaTeX: pdfLaTeX + +BuildType: Package +PackageUseDevtools: Yes +PackageInstallArgs: --no-multiarch --with-keep.source +PackageRoxygenize: rd,collate,namespace,vignette diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..10f39e3 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,2 @@ +library(testthat) +test_dir("testthat") diff --git a/tests/testthat/test-last.R b/tests/testthat/test-last.R new file mode 100644 index 0000000..9824efa --- /dev/null +++ b/tests/testthat/test-last.R @@ -0,0 +1,69 @@ +library("overflow") +context("solast") +test_that("lastcall", { + hist.dat <- list( + "1 + 1\nlastcall()\n", + "1 + 1\n2 + 2\nlastcall()\n", + "1\n{\nx <- 3\nx + 1:3}\nlastcall()\n", + "1 + 1\n}\nlastcall()\n", + "1\n}\n1 + 1\nlastcall()\n", + paste0(c("{", 1:90, "x <- 5\nx\n}\nx / 2\nlastcall()\n"), collapse="\n") + ) + sl <- function(x) tail(x, 2L)[[1L]] # second to last value + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[1L]]), + expect_warning(res <- lastcall(), "We cannot guarantee"), + expect_equal(res, sl(parse(text=hist.dat[[1L]]))) + ) + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[2L]]), + expect_equal(lastcall(), sl(parse(text=hist.dat[[2L]]))) + ) + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[3L]]), + expect_equal(lastcall(), sl(parse(text=hist.dat[[3L]]))) + ) + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[4L]]), + expect_error(lastcall(), "Unable to retrieve") + ) + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[5L]]), + expect_warning(lastcall(), "We cannot guarantee") + ) + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[6L]]), + expect_equal(lastcall(), sl(parse(text=hist.dat[[6L]]))) + ) + # Here we hit `max.lookback` before we can fully parse prior expression + with_mock( + savehistory=function(file) writeLines(con=file, hist.dat[[6L]]), + expect_warning(res <- lastcall(max.lookback=6L), "We cannot guarantee"), + expect_equal(res, sl(parse(text=hist.dat[[6L]]))) + ) + expect_error(lastcall("hello"), "integer") +}) +test_that("solast", { + expect_error(solast(silent="hello"), "TRUE or FALSE") + expect_error(solast(clip="hello"), "TRUE or FALSE") + expect_error(solast(drop.curly.brace="hello"), "TRUE or FALSE") + hist <- "1\n{\nx <- 1\nx\n}\nsolast()\n" + + res.sub <- c("x <- 1", "x") + res.res <- "## [1] 1" + res.1 <- noquote(paste0(" ", c(res.sub, res.res))) + res.2 <- noquote(paste0(" ", c("{", paste0(" ", res.sub), "}", res.res))) + + with_mock( + savehistory=function(file) writeLines(con=file, hist), + .env=getNamespace("overflow"), + lastval=function() 1, + print(solast()), + print(res.1), + expect_equal(solast(), res.1), + expect_equal(noquote(capture.output(solast())), res.1), + expect_equal(capture.output(solast(silent=TRUE)), character(0L)), + expect_equal(solast(drop.curly.brace=FALSE), res.2), + expect_error(solast(max.lookback=1L), "Unable to retrieve") + ) +})