diff --git a/NAMESPACE b/NAMESPACE index ddc80a8..b385307 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -3,6 +3,7 @@ export(alamak) export(makePixPal) importFrom(cli,console_width) +importFrom(crayon,combine_styles) importFrom(crayon,make_style) importFrom(crayon,red) importFrom(grDevices,rgb) diff --git a/R/alamak.R b/R/alamak.R index 30178a6..afe4b29 100644 --- a/R/alamak.R +++ b/R/alamak.R @@ -4,11 +4,13 @@ #' Generates a pixel pal from a PNG file #' #' @param filepath a character indicating a path to a .PNG file. +#' @param compress logical, should the Pixel Pal be compressed to take up fewer +#' spaces in the terminal? Default is TRUE. #' #' @return a character string converted to color ASCII through \code{crayon} #' #' @importFrom png readPNG -#' @importFrom crayon make_style +#' @importFrom crayon make_style combine_styles #' @importFrom grDevices rgb #' #' @examples @@ -34,7 +36,7 @@ #' #' @export -makePixPal <- function(filepath) { +makePixPal <- function(filepath, compress = TRUE) { pix = readPNG(filepath, native = FALSE) @@ -42,13 +44,17 @@ makePixPal <- function(filepath) { pix = matrix(pixcols, nrow = dim(pix)[1], byrow = TRUE) - crayonstrings <- matrix( - unlist(sapply(pixcols, function(x) { - make_style(x, bg = TRUE)(" ")})), - nrow = nrow(pix)) + if(compress) { + crayonstrings <- compressPixPal(pix) + } else { + crayonstrings <- matrix( + unlist(sapply(pixcols, function(x) { + make_style(x, bg = TRUE)(" ")})), + nrow = nrow(pix)) - crayonstrings[t(pix) == "#00000000"] = " " - crayonstrings[,ncol(crayonstrings)] <- paste(crayonstrings[,ncol(crayonstrings)], "\n", sep = "") + crayonstrings[t(pix) == "#00000000"] = " " + crayonstrings[,ncol(crayonstrings)] <- paste(crayonstrings[,ncol(crayonstrings)], "\n", sep = "") + } return(crayonstrings) } @@ -70,8 +76,15 @@ makePixPal <- function(filepath) { #' #' @examples #' +#' # Error message #' alamak(a + 4) #' +#' # Warning message +#' alamak(as.numeric("alamak")) +#' +#' # Change Pixel Pal +#' alamak(as.numeric("alamak"), "Lenny") +#' #' @importFrom crayon red #' @importFrom cli console_width #' @@ -79,6 +92,7 @@ makePixPal <- function(filepath) { alamak <- function(f, pixpal = "Jerry"){ + # Input checks if(all(class(pixpal) == "character" & pixpal %in% c("Jerry", "Lenny", "Buster", "Oniji", "E10N"))) { pixpal = pixpals[[pixpal]] } else if(class(pixpal) != "list") { @@ -92,36 +106,37 @@ alamak <- function(f, pixpal = "Jerry"){ stop("Not a valid Pixel Pal! Needs \"Error\" and \"Warning\" elements. See ?makePixPal for an example") } - warns = list() - errs = list() + #Error catching + warnings = list() + errors = list() out <- tryCatch(withCallingHandlers( expr = f, - warning = function(w) { - warns <<- c(warns, list(w)) - invokeRestart("muffleWarning") - }), - + warnings <<- c(warnings, list(w)) + invokeRestart("muffleWarning")}), error = function(e) { - errs <<- c(errs, list(e)) - } + errors <<- c(errors, list(e))} ) - if(length(errs) > 0 | length(warns) > 0) { - if(length(errs) > 0){ + if(length(errors) > 0 | length(warnings) > 0) { + + if(length(errors) > 0){ errtype = "Error" - errmess = paste0(errtype, ": ", unlist(lapply(errs, function(x) { + errmess = paste0(errtype, ": ", unlist(lapply(errors, function(x) { mess = gsub(x = as.character(x$message), pattern = "\\033\\[[0-9][0-9+]m", replacement = "", perl = TRUE) return(mess) }))) - } else if(length(warns) > 0) { + } else if(length(warnings) > 0) { errtype = "Warning" - errmess = paste0(errtype, ": ", unlist(lapply(warns, function(x) { + errmess = paste0(errtype, ": ", unlist(lapply(warnings, function(x) { mess = gsub(x = as.character(x$message), pattern = "\\033\\[[3[0-9+]m", replacement = "", perl = TRUE) return(mess) }))) } + + # Message wrangling + pal = pixpal$crayon consolew = min(2*console_width() - 2 - ncol(pal), 100) @@ -143,11 +158,8 @@ alamak <- function(f, pixpal = "Jerry"){ max_text_col = column_sizes[max_col_size] - #print(max_text_col) - #print(message_to_add[1]) - - finalmess = c(" ", rep("_", max_text_col), "____\n|", - rep(" ", max_text_col), " |\n") + finalmess = c("\u250c", rep("\u2500", max_text_col + 3), "\u2510\n\u2502", + rep(" ", max_text_col), " \u2502\n") for(i in message_to_add) { if(grepl("\\033\\[31", i, perl = TRUE)) { @@ -156,11 +168,12 @@ alamak <- function(f, pixpal = "Jerry"){ padding = nchar(i) } finalmess = c(finalmess, - "| ", i, - rep(" ", max_text_col - padding), " |\n") + "\u2502 ", i, + rep(" ", max_text_col - padding), " \u2502\n") } - finalmess = c(finalmess, "|_", rep("_", max_text_col), "___|\n") + finalmess = c(finalmess, "\u2502", rep(" ", max_text_col + 3), "\u2502\n", + "\u2514", rep("\u2500", max_text_col + 3), "\u2518\n") finalmess_print = unlist(strsplit(paste0(finalmess, collapse = ""), split = "\n")) @@ -168,7 +181,7 @@ alamak <- function(f, pixpal = "Jerry"){ if(difference > 0) { pal = rbind(pal, do.call(rbind, - lapply(seq_len(difference), function(x) c(rep(" ", ncol(pal)-1), " \n")) + lapply(seq_len(difference), function(x) c(rep(" ", ncol(pal)-1), "\n")) ) ) } @@ -181,12 +194,71 @@ alamak <- function(f, pixpal = "Jerry"){ crayonmap_with_message[right_lines[i]] = gsub(x = crayonmap[right_lines[i]], pattern = "\n", replacement = paste0(" ", finalmess_print[i], "\n")) - } - cat(crayonmap_with_message, sep = "") + } + + # Printing + cat("\n", crayonmap_with_message, "\n", sep = "") } - if(length(errs) == 0) return(out) + if(length(errors) == 0) return(out) + +} + +#' Compress a pixel pal +#' +#' Compresses a pixel pal using Unicode Blocks +#' +#' @param pix a character indicating a path to a .PNG file. +#' +#' @return returns a compressed Pixel Pal character matrix that occupies half the +#' space in the terminal +#' +#' @details Internal use only. Note: the Apple Terminal does not deal well with +#' Unicode blocks. When the package is loaded, if Apple Terminal is detected, +#' compression is disabled. +#' +#' @references kindly suggested in https://github.com/gdagstn/alamak/issues/2 +#' by Trevor L. Davis +#' +#' @importFrom crayon make_style combine_styles + +compressPixPal <- function(pix){ + + pix = t(pix) + + complist = list() + + for(i in seq(1,nrow(pix), by = 2)) { + + two_rows = t(pix[i:(i + 1),]) + + compressed = apply(two_rows, 1, function(x) { + + if(x[1] == "#00000000" & x[2] != "#00000000") { + background1 = FALSE + x[1] = x[2] + pixel_char = "\u2584" + } else if(x[1] != "#00000000" & x[2] == "#00000000") { + x[2] = x[1] + background1 = FALSE + pixel_char = "\u2580" + } else if(x[1] == "#00000000" & x[2] == "#00000000"){ + background1 = FALSE + pixel_char = " " + } else if(x[1] != "#00000000" & x[2] != "#00000000"){ + background1 = TRUE + pixel_char = "\u2584" + } + + combine_styles(make_style(x[1], bg = background1), + make_style(x[2], bg = FALSE))(pixel_char) + }) + + complist[[i]] = c(compressed, "\n") + + } + return(do.call(rbind, complist[!is.null(complist)])) } diff --git a/R/pixpals.R b/R/pixpals.R index d69f61f..cf57a85 100644 --- a/R/pixpals.R +++ b/R/pixpals.R @@ -1,6 +1,12 @@ +#' Code to create initial Pixel Pals +#' Sourced on loading + pixpals = list() -pixpals$Buster = list("crayon" = makePixPal("inst/extdata/buster.png"), +term = Sys.getenv("TERM_PROGRAM") +if(term == "Apple_Terminal") compression = FALSE else compression = TRUE + +pixpals$Buster = list("crayon" = makePixPal("inst/extdata/buster.png", compress = compression), "messages" = list( @@ -23,7 +29,7 @@ pixpals$Buster = list("crayon" = makePixPal("inst/extdata/buster.png"), ) ) -pixpals$Jerry = list("crayon" = makePixPal("inst/extdata/jerry.png"), +pixpals$Jerry = list("crayon" = makePixPal("inst/extdata/jerry.png", compress = compression), "messages" = list( @@ -52,7 +58,7 @@ pixpals$Jerry = list("crayon" = makePixPal("inst/extdata/jerry.png"), ) ) -pixpals$Oniji = list("crayon" = makePixPal("inst/extdata/oniji.png"), +pixpals$Oniji = list("crayon" = makePixPal("inst/extdata/oniji.png", compress = compression), "messages" = list( "Error" = c("A single function / Mysterious operations / It has failed again.", @@ -73,7 +79,7 @@ pixpals$Oniji = list("crayon" = makePixPal("inst/extdata/oniji.png"), ) -pixpals$Lenny = list("crayon" = makePixPal("inst/extdata/lenny.png"), +pixpals$Lenny = list("crayon" = makePixPal("inst/extdata/lenny.png", compress = compression), "messages" = list( "Error" = c("You got this!", @@ -100,7 +106,7 @@ pixpals$Lenny = list("crayon" = makePixPal("inst/extdata/lenny.png"), ) ) -pixpals$E10N = list("crayon" = makePixPal("inst/extdata/e10n.png"), +pixpals$E10N = list("crayon" = makePixPal("inst/extdata/e10n.png", compress = compression), "messages" = list( diff --git a/R/sysdata.rda b/R/sysdata.rda index fbcffec..5dd3edd 100644 Binary files a/R/sysdata.rda and b/R/sysdata.rda differ diff --git a/man/alamak.Rd b/man/alamak.Rd index 27ef7b0..29d68c8 100644 --- a/man/alamak.Rd +++ b/man/alamak.Rd @@ -10,9 +10,10 @@ alamak(f, pixpal = "Jerry") \item{f}{a function} \item{pixpal}{a Pixel Pal, one of "Lenny" (supportive velociraptor), "Buster" -(cool lemon), "Jerry" (a parrot that hates you) and "Oniji" (Edo period -Japanese kabuki actor who speaks in haiku only). Alternatively, a Pixel -Pal made following the instructions at \code{?makePixPal}.} +(cool lemon), "Jerry" (a parrot that hates you), "Oniji" (Edo period +Japanese kabuki actor who speaks in haiku only), and "E10N" (a robot from +the future). Alternatively, a Pixel Pal can be created manually following +the instructions at \code{?makePixPal}.} } \value{ the output of \code{f} if there are no errors, otherwise @@ -25,6 +26,13 @@ Catches an error or warning and lets a pixel pal tell you all about it } \examples{ +# Error message alamak(a + 4) +# Warning message +alamak(as.numeric("alamak")) + +# Change Pixel Pal +alamak(as.numeric("alamak"), "Lenny") + } diff --git a/man/compressPixPal.Rd b/man/compressPixPal.Rd new file mode 100644 index 0000000..31cee37 --- /dev/null +++ b/man/compressPixPal.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/alamak.R +\name{compressPixPal} +\alias{compressPixPal} +\title{Compress a pixel pal} +\usage{ +compressPixPal(pix) +} +\arguments{ +\item{pix}{a character indicating a path to a .PNG file.} +} +\value{ +returns a compressed Pixel Pal character matrix that occupies half the + space in the terminal +} +\description{ +Compresses a pixel pal using Unicode Blocks +} +\details{ +Internal use only. Note: the Apple Terminal does not deal well with + Unicode blocks. When the package is loaded, if Apple Terminal is detected, + compression is disabled. +} +\references{ +kindly suggested in https://github.com/gdagstn/alamak/issues/2 + by Trevor L. Davis +} diff --git a/man/makePixPal.Rd b/man/makePixPal.Rd index 6e04345..e84ebbc 100644 --- a/man/makePixPal.Rd +++ b/man/makePixPal.Rd @@ -4,10 +4,13 @@ \alias{makePixPal} \title{Make a pixel pal} \usage{ -makePixPal(filepath) +makePixPal(filepath, compress = TRUE) } \arguments{ \item{filepath}{a character indicating a path to a .PNG file.} + +\item{compress}{logical, should the Pixel Pal be compressed to take up fewer +spaces in the terminal? Default is TRUE.} } \value{ a character string converted to color ASCII through \code{crayon} diff --git a/man/pixpals.Rd b/man/pixpals.Rd new file mode 100644 index 0000000..50b4579 --- /dev/null +++ b/man/pixpals.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/pixpals.R +\docType{data} +\name{pixpals} +\alias{pixpals} +\title{Code to create initial Pixel Pals +Sourced on loading} +\format{ +An object of class \code{list} of length 5. +} +\usage{ +pixpals +} +\description{ +Code to create initial Pixel Pals +Sourced on loading +} +\keyword{datasets}