diff --git a/DESCRIPTION b/DESCRIPTION index f9f75f1..75a3f84 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -30,6 +30,8 @@ Description: Query and print information about the current R License: GPL-2 URL: https://github.com/r-lib/sessioninfo#readme BugReports: https://github.com/r-lib/sessioninfo/issues +Depends: + R (>= 2.10) Imports: cli, tools, diff --git a/NAMESPACE b/NAMESPACE index 971546d..225a4be 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -5,10 +5,12 @@ S3method(as.character,packages_info) S3method(as.character,platform_info) S3method(as.character,python_info) S3method(as.character,session_info) +S3method(c,platform_info) S3method(format,external_info) S3method(format,packages_info) S3method(format,platform_info) S3method(format,python_info) +S3method(format,session_info) S3method(print,external_info) S3method(print,packages_info) S3method(print,platform_info) diff --git a/R/hash.R b/R/hash.R new file mode 100644 index 0000000..ec81383 --- /dev/null +++ b/R/hash.R @@ -0,0 +1,43 @@ + +# TODO: this can use cli, once a new version with cli::hash_emoji() is +# release to CRAN + +add_hash <- function(si, size = 3) { + stopifnot(size >= 1, size <= 4) + + orig <- si + # drop the date for hashing + if ("platform" %in% names(si) && "date" %in% names(si$platform)) { + si$platform$date <- NULL + } + + old <- options( + cli.unicode = FALSE, + cli.num_colors = 1, + sessioninfo.emoji = FALSE + ) + on.exit(options(old), add = TRUE) + tmp <- tempfile() + writeLines(format(si), tmp) + on.exit(unlink(tmp), add = TRUE) + + md5 <- tools::md5sum(tmp)[[1]] + md513 <- substr(md5, 1, 13) + mdint <- as.integer(as.hexmode(strsplit(md513, "")[[1]])) + hash <- sum(mdint * 16^(0:12)) + + base <- nrow(emojis) + ehash <- hash %% (base ** size) + digits <- integer() + while (ehash > 0) { + digits <- c(digits, ehash %% base) + ehash <- ehash %/% base + } + digits <- c(digits, rep(0, 10))[1:size] + + nms <- emojis$name[digits + 1] + emo <- emojis$emoji[digits + 1] + + orig$hash <- list(emoji = emo, emo_text = nms) + orig +} diff --git a/R/platform-info.R b/R/platform-info.R index b59e6ff..dcc32e5 100644 --- a/R/platform-info.R +++ b/R/platform-info.R @@ -24,7 +24,7 @@ #' platform_info() platform_info <- function() { - structure(drop_null(list( + as_platform_info(drop_null(list( version = R.version.string, os = os_name(), system = version$system, @@ -36,7 +36,7 @@ platform_info <- function() { date = format(Sys.Date()), rstudio_version = get_rstudio_version(), pandoc_version = get_pandoc_version() - )), class = c("platform_info", "list")) + ))) } get_rstudio_version <- function() { @@ -98,3 +98,15 @@ print.platform_info <- function(x, ...) { as.character.platform_info <- function(x, ...) { format(x, ...) } + +#' @export + +c.platform_info <- function(...) { + as_platform_info(NextMethod()) +} + +as_platform_info <- function(x) { + stopifnot(is.list(x)) + class(x) <- c("platform_info", "list") + x +} diff --git a/R/printing.R b/R/printing.R index b7aae88..456431d 100644 --- a/R/printing.R +++ b/R/printing.R @@ -1,11 +1,11 @@ #' @importFrom cli symbol -rule <- function (..., pad = NULL) { - if (is.null(pad)) pad <- symbol$line +rule <- function (..., pad = NULL, double = FALSE) { + if (is.null(pad)) pad <- if (double) symbol$double_line else symbol$line title <- if (length(list(...))) paste0(" ", ..., " ") else "" - width <- max(cli::console_width() - nchar(title) - 3, 0) + width <- max(cli::console_width() - cli::ansi_nchar(title, "width") - 3, 0) paste(pad, title, paste(rep(pad, width), collapse = ""), sep = "") } diff --git a/R/session-info.R b/R/session-info.R index e8df85f..9310a42 100644 --- a/R/session-info.R +++ b/R/session-info.R @@ -90,6 +90,8 @@ session_info <- function( class = c("session_info", "list") ) + si <- add_hash(si) + if (is_string(to_file)) { writeLines(as.character(si), to_file) invisible(si) @@ -100,24 +102,67 @@ session_info <- function( #' @export -as.character.session_info <- function(x, ...) { - c(if ("platform" %in% names(x)) { - c(rule("Session info"), as.character(x$platform), "") +format.session_info <- function(x, ...) { + + has_platform <- !is.null(x$platform) + + c(if (!"platform" %in% names(x)) { + c(rule(paste("Session info", emo_hash(x)), double = TRUE), text_hash(x)) + }, + if ("platform" %in% names(x)) { + c(rule(paste("Session info", emo_hash(x))), + text_hash(x), + format(x$platform), + "" + ) }, if ("packages" %in% names(x)) { - c(rule("Packages"), as.character(x$packages), "") + c(rule("Packages"), format(x$packages), "") }, if ("external" %in% names(x)) { - c(rule("External software"), as.character(x$external), "") + c(rule("External software"), format(x$external), "") }, if ("python" %in% names(x)) { - c(rule("Python configuration"), as.character(x$python), "") + c(rule("Python configuration"), format(x$python), "") } ) } #' @export +as.character.session_info <- function(x, ...) { + format(x, ...) +} + +has_emoji <- function () { + if (isTRUE(opt <- getOption("sessioninfo.emoji"))) { + TRUE + } else if (identical(opt, FALSE)) { + FALSE + } else if (!cli::is_utf8_output()) { + FALSE + } else { + Sys.info()[["sysname"]] == "Darwin" + } +} + +emo_hash <- function(x) { + if (is.null(x$hash)) return("") + if (has_emoji()) { + paste0(" ", paste(x$hash$emoji, " ", collapse = "")) + } else { + "" + } +} + +text_hash <- function(x) { + if (!is.null(x$hash) && !has_emoji()) { + c(paste0(" hash: ", paste(x$hash$emo_text, collapse = ", ")), "") + } +} + +#' @export + print.session_info <- function(x, ...) { - cat(as.character(x), sep = "\n") + cat(format(x), sep = "\n") } diff --git a/R/sysdata.rda b/R/sysdata.rda new file mode 100644 index 0000000..1a857d4 Binary files /dev/null and b/R/sysdata.rda differ diff --git a/tools/bad-emoji.R b/tools/bad-emoji.R new file mode 100644 index 0000000..deb2dbe --- /dev/null +++ b/tools/bad-emoji.R @@ -0,0 +1,203 @@ +# emoji 0.2.0 +bad <- c( + 11, + 24, + 33, + 34, + 37, + 43:45, + 50, + 67, + 71, + 76, + 86, + 101, + 144:147, + 155, + 157, + 170, + 209:232, + 239:250, + 264:269, + 325:330, + 379:384, + 403:422, + 454:455, + 474:479, + 487:488, + 496, + 545:568, + 605:610, + 617:622, + 629:634, + 641:670, + 695:718, + 725:748, + 755:778, + 785:808, + 815:838, + 845:898, + 905:928, + 935:958, + 965:1000, + 1025:1030, + 1043:1048, + 1061:1072, + seq(1074, 1096, by = 2), + 1097:1102, + 1115:1120, + 1133:1138, + 1151:1156, + 1169:1174, + 1187:1192, + 1205:1210, + 1223:1228, + 1241:1246, + 1259:1270, + seq(1272, 1294, by = 2), + 1295:1300, + 1313:1318, + 1337, + 1360, + 1368:1395, + 1402:1431, + 1438:1467, + 1486:1509, + 1528:1551, + 1558:1581, + 1588:1599, + 1606:1623, + 1642:1647, + 1654:1677, + 1684:1707, + 1714:1737, + 1744:1767, + 1774:1797, + 1804:1827, + 1834:1857, + 1859:1862, + 1864:1868, + 1875:1898, + 1905:1928, + 1935:2072, + 2079:2102, + 2123:2126, + 2133:2156, + 2163:2186, + 2209:2236, + 2243:2521, + 2528:2551, + 2558:2581, + 2588:2611, + 2624:2649, + 2652:2656, + 2658:2662, + 2664:2668, + 2670:2674, + 2678:2682, + 2684:2688, + 2690:2684, + 2696:2700, + 2704:2708, + 2710:2714, + 2716:2720, + 2722:2726, + 2729:2773, + 2775:2825, + 2827:2877, + 2879:2929, + 2931:2975, + 2977:3027, + 3029:3079, + 3081:3131, + 3162, + 3176, + 3179, + 3180, + 3187, + 3197, + 3214, + 3225, + 3229, + 3230, + 3233:3235, + 3253:3255, + 3270, + 3277, + 3283, + 3286, + 3293, + 3294, + 3299, + 3309, + 3322, + 3323, + 3338, + 3341, + 3350, + 3354, + 3355, + 3358, + 3363, + 3367, + 3380, + 3382, + 3387, + 3391, + 3415, + 3433, + 3444, + 3446:3449, + 3456, + 3489, + 3490, + 3516, + 3535, + 3565, + 3574:3576, + 3580, + 3589, + 3596, + 3613, + 3678, + 3778, + 3784, + 3785, + 3788, + 3790, + 3798:3800, + 3819:3821, + 3827, + 3837:3840, + 3849, + 3856, + 3863, + 3892, + 3897, + 3899, + 3908, + 3944, + 3965, + 4041, + 4053, + 4057, + 4059, + 4067, + 4071, + 4074, + 4087:4089, + 4092, + 4093, + 4098, + 4100, + 4103, + 4104, + 4110, + 4112, + 4113, + 4120, + 4124, + 4125, + 4399, + 4436:4441 +)