list_to_md.r 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. #' Output a nested list in RMarkdown list format
  2. #'
  3. #' @param x The list
  4. #' @param type Text to specify type of lists (unorderd, ordered, headers)
  5. #' @param pre Text to prefix to each line (e.g., if you want all lines indented 4 spaces to start, use " ")
  6. #' @param quote Text to quote values with (e.g., use "`" to make sure values are not parsed as markdown
  7. #'
  8. #' @return A character string
  9. #' @export
  10. #'
  11. #' @examples
  12. #' x <- list(
  13. #' a = list(a1 = "Named", a2 = "List"),
  14. #' b = list("Unnamed", "List"),
  15. #' c = c(c1 = "Named", c2 = "Vector"),
  16. #' d = c("Unnamed", "Vector"),
  17. #' e = list(e1 = list("A", "B", "C"),
  18. #' e2 = list(a = "A", b = "B"),
  19. #' e3 = c("A", "B", "C"),
  20. #' e4 = 100),
  21. #' f = "single item vector",
  22. #' g = list()
  23. #' )
  24. #' nested_list(x)
  25. #' nested_list(x, pre = " ")
  26. #' nested_list(x, type = "headers", pre= "#", quote = "'")
  27. nested_list <- function(x, pre = "", quote = "", type = "unordered") {
  28. txt <- c()
  29. if (type == "unordered") parameters= c("* "," ",": ")
  30. if (type == "ordered") parameters= c("1. "," ",": ")
  31. if (type == "headers") parameters= c("# ","#","\n")
  32. # use default if parameters not given correctly
  33. if (!exists("parameters")) parameters= c("* "," ",": ")
  34. if (is.function(x)) {
  35. fnc <- x %>%
  36. jsonlite::toJSON() %>%
  37. jsonlite::fromJSON()
  38. txt <- c("```r", fnc, "```") %>%
  39. paste0(pre, .)
  40. } else if (!is.null(x) & !is.atomic(x) & !is.vector(x) & !is.list(x)) {
  41. # not a displayable type
  42. txt <- class(x)[1] %>% paste0("{", ., "}")
  43. } else if (is.null(x) | length(x) == 0) {
  44. txt <- "{empty}"
  45. } else if (length(x) == 1 &
  46. is.null(names(x)) &
  47. !is.list(x)) { # single-item unnamed vector
  48. txt <- paste0(quote, x, quote)
  49. } else { # x is a list, named vector, or vector length > 1
  50. # handle named, unnamed, or partially named
  51. list_names <- names(x)
  52. if (is.null(list_names)) {
  53. bullet <- paste0(1:length(x), ". ")
  54. if (type == "headers") bullet <- paste0(parameters[1], 1:length(x), "_no_title", parameters[3])
  55. } else {
  56. blanks <- grep("^$", list_names)
  57. list_names[blanks] <- paste0("{", blanks, "}")
  58. bullet <- paste0(parameters[1], list_names, parameters[3])
  59. }
  60. pre2 <- paste0(pre, parameters[2])
  61. txt <- lapply(seq_along(x), function(i) {
  62. item <- x[[i]]
  63. sub <- nested_list(item, pre2, quote,type)
  64. # add line break unless item is unnamed and length = 1
  65. lbreak <- ifelse(length(item) > 1 | (length(names(item)) > 0), "\n", "")
  66. if (grepl("\n", sub)) lbreak <- "\n"
  67. paste0(pre, bullet[i], lbreak, sub)
  68. })
  69. }
  70. collapsing = ifelse (type == "headers","\n\n","\n")
  71. list_txt <- paste(txt, collapse = collapsing)
  72. class(list_txt) <- c("nested_list", "character")
  73. list_txt
  74. }
  75. #' Print Nested List
  76. #'
  77. #' @param x The nested_list string
  78. #' @param ... Additional parameters for print
  79. #'
  80. #' @export
  81. #'
  82. print.nested_list <- function(x, ...) {
  83. cat(x)
  84. }