cliapp/0000755000176200001440000000000013405461705011527 5ustar liggesuserscliapp/inst/0000755000176200001440000000000013346717143012510 5ustar liggesuserscliapp/inst/scripts/0000755000176200001440000000000013375766246014211 5ustar liggesuserscliapp/inst/scripts/up.R0000755000176200001440000000277113375766246014772 0ustar liggesusers#! /usr/bin/env Rscript ## To get the async package: ## source("https://install-github.me/r-lib/async") setup_app <- function() { theme <- list("url" = list(color = "blue")) app <- cliapp::start_app(theme = theme, output = "stdout") } load_packages <- function() { tryCatch({ library(cliapp) library(async) library(docopt) }, error = function(e) { cli_alert_danger("The {pkg async} and {pkg docopt} packages are needed!") q(save = "no", status = 1) }) } up <- function(urls, timeout = 5) { load_packages() setup_app() chk_url <- async(function(url, ...) { http_head(url, ...)$ then(function(res) { if (res$status_code < 300) { cli_alert_success("{url {url}} ({res$times[['total']]}s)") } else { cli_alert_danger("{url {url}} (HTTP {res$status_code})") } })$ catch(error = function(err) { e <- if (grepl("timed out", err$message)) "timed out" else "error" cli_alert_danger("{url {url}} ({e})") }) }) invisible(synchronise( async_map(urls, chk_url, options = list(timeout = timeout)) )) } parse_arguments <- function() { "Usage: up.R [-t timeout] [URLS ...] up.R -h | --help Options: -t timeout Timeout for giving up on a site, in seconds [default: 5]. -h --help Print this help message Check if web sites are up. " -> doc docopt(doc) } if (is.null(sys.calls())) { load_packages() opts <- parse_arguments() up(opts$URLS, timeout = as.numeric(opts$t)) } cliapp/inst/scripts/news.R0000755000176200001440000000564513375764752015325 0ustar liggesusers#! /usr/bin/env Rscript setup_app <- function() { theme <- list( "url" = list(color = "blue"), ".pkg" = list(color = "orange"), "it" = list("margin-bottom" = 1)) start_app(theme = theme, output = "stdout") } load_packages <- function() { tryCatch({ library(cliapp) library(httr) library(jsonlite) library(prettyunits) library(glue) library(parsedate) library(docopt) }, error = function(e) { cli_alert_danger( "The {pkg glue}, {pkg httr}, {pkg jsonlite}, {pkg prettyunits},", " {pkg parsedate} and {pkg docopt} packages are needed!") q(save = "no", status = 1) }) } news <- function(n = 10, day = FALSE, week = FALSE, since = NULL, reverse = FALSE) { load_packages() setup_app() result <- if (day) news_day() else if (week) news_week() else if (!is.null(since)) news_since(since) else news_n(as.numeric(n)) if (reverse) result <- rev(result) format_results(result) invisible() } news_day <- function() { date <- format_iso_8601(Sys.time() - as.difftime(1, units="days")) ep <- glue("/-/pkgreleases?descending=true&endkey=%22{date}%22") do_query(ep) } news_week <- function() { date <- format_iso_8601(Sys.time() - as.difftime(7, units="days")) ep <- glue("/-/pkgreleases?descending=true&endkey=%22{date}%22") do_query(ep) } news_since <- function(since) { date <- format_iso_8601(parse_date(since)) ep <- glue("/-/pkgreleases?descending=true&endkey=%22{date}%22") do_query(ep) } news_n <- function(n) { ep <- glue("/-/pkgreleases?limit={n}&descending=true") do_query(ep) } do_query <- function(ep) { base <- "https://crandb.r-pkg.org" url <- glue("{base}{ep}") response <- GET(url) stop_for_status(response) fromJSON(content(response, as = "text"), simplifyVector = FALSE) } format_results <- function(results) { cli_div(theme = list(ul = list("list-style-type" = ""))) cli_ol() lapply(results, format_result) } parse_arguments <- function() { "Usage: news.R [-r | --reverse] [-n num ] news.R [-r | --reverse] --day | --week | --since date news.R [-h | --help] Options: -n num Show the last 'n' releases [default: 10]. --day Show releases in the last 24 hours --week Show relaases in the last 7 * 24 hours --since date Show releases since 'date' -r --reverse Reverse the order, show older on top -h --help Print this help message New package releases on CRAN " -> doc docopt(doc) } format_result <- function(result) { pkg <- result$package ago <- vague_dt(Sys.time() - parse_iso_8601(result$date)) cli_it() cli_text("{pkg {pkg$Package}} {pkg$Version} -- {ago} by {emph {pkg$Maintainer}}") cli_text("{pkg$Title}") cli_text("{url https://r-pkg.org/pkg/{pkg$Package}}") } if (is.null(sys.calls())) { load_packages() opts <- parse_arguments() news(opts$n, opts$day, opts$week, opts$since, opts$reverse) } cliapp/inst/scripts/search.R0000755000176200001440000000402413375766166015605 0ustar liggesusers#! /usr/bin/env Rscript setup_app <- function() { theme <- list( "url" = list(color = "blue"), ".pkg" = list(color = "orange")) start_app(theme = theme, output = "stdout") } load_packages <- function() { tryCatch({ library(cliapp) library(pkgsearch) library(docopt) library(prettyunits) error = function(e) { cli_alert_danger( "The {pkg pkgsearch}, {pkg prettyunits} and {pkg docopt} packages are needed!") q(save = "no", status = 1) } }) } search <- function(terms, from = 1, size = 5) { load_packages() setup_app() term <- paste(encodeString(quote = '"', terms), collapse = " ") result <- do_query(term, from = from, size = size) format_result(result, from = from, size = size) invisible() } `%||%` <- function(l, r) if (is.null(l)) r else l do_query <- function(query, from, size) { cli_alert_info("Searching...") pkg_search(query, from = from, size = size) } format_result <- function(obj, from, size) { meta <- attr(obj, "metadata") if (!meta$total) { cli_alert_danger("No results :(") return() } cli_alert_success("Found {meta$total} packages in {pretty_ms(meta$took)}") cli_text() cli_div(theme = list(ul = list("list-style-type" = ""))) cli_ol() lapply(seq_len(nrow(obj)), function(i) format_hit(obj[i,])) } format_hit <- function(hit) { ago <- vague_dt(Sys.time() - hit$date) cli_it() cli_text("{pkg {hit$package}} {hit$version} -- {emph {hit$title}}") cli_par() cli_text(hit$description) cli_text("{emph {ago} by {hit$maintainer_name}}") } parse_arguments <- function() { "Usage: cransearch.R [-h | --help] [ -f from ] [ -n size ] ... Options: -h --help Print this help message -f first First hit to include -n size Number of hits to include Seach for CRAN packages on r-pkg.org " -> doc docopt(doc) } if (is.null(sys.calls())) { load_packages() opts <- parse_arguments() search(opts$term, from = as.numeric(opts$f %||% 1), size = as.numeric(opts$n %||% 5)) } cliapp/inst/scripts/outdated.R0000755000176200001440000000400113375765173016141 0ustar liggesusers#! /usr/bin/env Rscript ## To get the pkgcache package: ## source("https://install-github.me/r-lib/pkgcache") setup_app <- function() { theme <- list( "url" = list(color = "blue"), ".pkg" = list(color = "orange")) start_app(theme = theme, output = "stdout") } load_packages <- function() { tryCatch(suppressPackageStartupMessages({ library(cliapp) library(cli) library(pkgcache) library(docopt) }), error = function(e) { cli_alert_danger("The {pkg pkgcache} and {pkg docopt} packages are needed!") q(save = "no", status = 1) }) } outdated <- function(lib = NULL, notcran = FALSE) { load_packages() setup_app() if (is.null(lib)) lib <- .libPaths()[1] inst <- utils::installed.packages(lib = lib) cli_alert_info("Getting repository metadata") repo <- meta_cache_list(rownames(inst)) if (!notcran) inst <- inst[inst[, "Package"] %in% repo$package, ] for (i in seq_len(nrow(inst))) { pkg <- inst[i, "Package"] iver <- inst[i, "Version"] if (! pkg %in% repo$package) { cli_alert_info("{pkg {pkg}}: \tnot a CRAN/BioC package") next } rpkg <- repo[repo$package == pkg, ] newer <- rpkg[package_version(rpkg$version) > iver, ] if (!nrow(newer)) next nver <- package_version(newer$version) mnver <- max(nver) newest <- newer[mnver == nver, ] bin <- if (any(newest$platform != "source")) "bin" else "" src <- if (any(newest$platform == "source")) "src" else "" cli_alert_danger( "{pkg {pkg}} \t{iver} {symbol$arrow_right} {mnver} {emph ({bin} {src})}") } } parse_arguments <- function() { "Usage: outdated.R [-l lib] [-x] outdated.R -h | --help Options: -x Print not CRAN/BioC packages as well -l lib Library directory, default is first directory in the lib path -h --help Print this help message Check for outdated packages in a package library. " -> doc docopt(doc) } if (is.null(sys.calls())) { load_packages() opts <- parse_arguments() outdated(opts$l, opts$x) } cliapp/tests/0000755000176200001440000000000013375603045012672 5ustar liggesuserscliapp/tests/testthat.R0000644000176200001440000000130113346165237014654 0ustar liggesuserslibrary(testthat) library(cliapp) ## Run the tests in fancy mode and non-fancy mode as well ## Also, run them in latin1 encoding as well, this is for Unix, ## because Windows encoding names are different. withr::with_options( list(cli.unicode = FALSE), test_check("cliapp") ) withr::with_options( list(cli.unicode = TRUE), test_check("cliapp") ) has_locale <- function(l) { has <- TRUE tryCatch( withr::with_locale(c(LC_CTYPE = l), "foobar"), warning = function(w) has <<- FALSE, error = function(e) has <<- FALSE ) has } if (l10n_info()$`UTF-8` && has_locale("en_US.ISO8859-1")) { withr::with_locale( c(LC_CTYPE = "en_US.ISO8859-1"), test_check("cliapp") ) } cliapp/tests/testthat/0000755000176200001440000000000013405461705014531 5ustar liggesuserscliapp/tests/testthat/test-themes.R0000644000176200001440000000354313375751775017142 0ustar liggesusers context("cli themes") setup(start_app()) teardown(stop_app()) test_that("add/remove/list themes", { id <- default_app()$add_theme(list(".green" = list(color = "green"))) on.exit(default_app()$remove_theme(id), add = TRUE) expect_true(id %in% names(default_app()$list_themes())) withr::with_options(list(crayon.enabled = TRUE, crayon.colors = 256), { capt0(cli_par(class = "green")) out <- capt0(cli_text(lorem_ipsum())) capt0(cli_end()) expect_true(grepl(start(crayon::make_style("green")), out, fixed = TRUE)) }) default_app()$remove_theme(id) expect_false(id %in% names(default_app()$list_themes())) }) test_that("default theme is valid", { expect_error({ id <- default_app()$add_theme(builtin_theme()) default_app()$remove_theme(id) }, NA) }) test_that("explicit formatter is used, and combined", { id <- default_app()$add_theme(list( "span.emph" = list(fmt = function(x) paste0("(((", x, ")))")), "span.emph::before" = list(content = "<<"), "span.emph::after" = list(content = ">>") )) on.exit(default_app()$remove_theme(id), add = TRUE) out <- capt0(cli_text("this is {emph it}, really")) expect_match(crayon::strip_style(out), "(((<>)))", fixed = TRUE) }) test_that("simple theme", { def <- simple_theme() expect_true(is.list(def)) expect_false(is.null(names(def))) expect_true(all(names(def) != "")) expect_true(all(vlapply(def, is.list))) }) test_that("user's override", { custom <- list(".alert::before" = list(content = "custom:")) override <- list(".alert::before" = list(content = "override:")) start_app(theme = custom) out <- capt0(cli_alert("Alert!")) expect_match(out, "custom:") stop_app() withr::with_options(list(cli.user_theme = override), { start_app(theme = custom) out <- capt0(cli_alert("Alert!")) expect_match(out, "override:") stop_app() }) }) cliapp/tests/testthat/test-headers.R0000644000176200001440000000140413375603045017244 0ustar liggesusers context("cli headers") setup(start_app()) teardown(stop_app()) test_that("headers", { cli_div(class = "testcli", theme = test_style()) withr::with_options(list(crayon.enabled = TRUE, crayon.colors = 256), { out <- capt0(cli_h1("HEADER")) expect_true(crayon::has_style(out)) expect_equal(crayon::strip_style(out), "\nHEADER\n\n") out <- capt0(cli_h2("Header")) expect_true(crayon::has_style(out)) expect_equal(crayon::strip_style(out), "Header\n\n") out <- capt0(cli_h3("Header")) expect_true(crayon::has_style(out)) expect_equal(crayon::strip_style(out), "Header\n") x <- "foobar" xx <- 100 out <- capt0(cli_h2("{xx}. header: {x}")) expect_equal(crayon::strip_style(out), "\n100. header: foobar\n\n") }) }) cliapp/tests/testthat/test-text.R0000644000176200001440000000134613375603045016622 0ustar liggesusers context("cli text") setup(start_app()) teardown(stop_app()) test_that("text is wrapped", { cli_div(class = "testcli", theme = test_style()) withr::with_options(c(cli.width = 60), { capt0(cli_h1("Header"), strip_style = TRUE) out <- capt0(cli_text(lorem_ipsum()), strip_style = TRUE) out <- strsplit(out, "\n")[[1]] len <- nchar(strsplit(out, "\n", fixed = TRUE)[[1]]) expect_true(all(len <= 60)) }) }) test_that("verbatim text is not wrapped", { cli_div(class = "testcli", theme = test_style()) withr::with_options(c(cli.width = 60), { capt0(cli_h1("Header")) txt <- strrep("1234567890 ", 20) out <- capt0(cli_verbatim(txt), strip_style = TRUE) expect_equal(out, paste0(txt, "\n")) }) }) cliapp/tests/testthat/test-custom-handler.R0000644000176200001440000000070313375603045020557 0ustar liggesusers context("custom-handler") test_that("custom handler works", { conds <- list() withr::with_options( list(cli.default_handler = function(msg) conds <<- c(conds, list(msg))), { cli_h1("title"); cli_h2("subtitle"); cli_text("text") } ) expect_equal(length(conds), 3) lapply(conds, expect_s3_class, "cliapp_message") expect_equal(conds[[1]]$type, "h1") expect_equal(conds[[2]]$type, "h2") expect_equal(conds[[3]]$type, "text") }) cliapp/tests/testthat/test-alerts.R0000644000176200001440000000163313375603045017127 0ustar liggesusers context("cli alerts") setup(start_app()) teardown(stop_app()) test_that("generic", { cli_div(theme = list(".alert::before" = list(content = "GENERIC! "))) out <- capt0(cli_alert("wow")) expect_match(out, "GENERIC") }) test_that("success", { cli_div(theme = list(".alert-success::before" = list(content = "SUCCESS! "))) out <- capt0(cli_alert_success("wow")) expect_match(out, "SUCCESS") }) test_that("danger", { cli_div(theme = list(".alert-danger::before" = list(content = "DANGER! "))) out <- capt0(cli_alert_danger("wow")) expect_match(out, "DANGER") }) test_that("warning", { cli_div(theme = list(".alert-warning::before" = list(content = "WARNING! "))) out <- capt0(cli_alert_warning("wow")) expect_match(out, "WARNING") }) test_that("info", { cli_div(theme = list(".alert-info::before" = list(content = "INFO! "))) out <- capt0(cli_alert_info("wow")) expect_match(out, "INFO") }) cliapp/tests/testthat/test-progress-bars.R0000644000176200001440000000257413376001646020433 0ustar liggesusers context("cli progress bars") setup(start_app()) teardown(stop_app()) test_that("progress bars", { x <- 100 withr::with_options( list(cli.width = 40, crayon.enabled = FALSE, crayon.colors = 1), { out <- capt0({ cli_text("so far so good: {x}") bar <- cli_progress_bar(total = 5, force = TRUE, show_after = 0) bar$tick() bar$tick() cli_text("still very good: {x}!") bar$tick() cli_text(strrep("1234567890 ", 6)) bar$tick() bar$tick() cli_text("aaaaand we are done") }) }) out <- strsplit(out, "\n", fixed = TRUE)[[1]] exp <- c( "so far so good: 100", paste0("\r[======>--------------------------] 20%", "\r[============>--------------------] 40%", "\r ", "\rstill very good: 100!"), paste0("[============>--------------------] 40%", "\r[===================>-------------] 60%", "\r ", "\r1234567890 1234567890 1234567890"), "1234567890 1234567890 1234567890", paste0("[===================>-------------] 60%", "\r[=========================>-------] 80%", "\r[=================================] 100%", "\r ", "\raaaaand we are done") ) expect_equal(out, exp) }) cliapp/tests/testthat/test-lists.R0000644000176200001440000001236513375603045016777 0ustar liggesusers context("cli lists") setup(start_app()) teardown(stop_app()) test_that("ul", { cli_div(theme = list(ul = list("list-style-type" = "*"))) lid <- cli_ul() out <- capt0({ cli_it("foo") cli_it(c("bar", "foobar")) }, strip_style = TRUE) expect_equal(out, "* foo\n* bar\n* foobar\n") cli_end(lid) }) test_that("ol", { cli_div(theme = list(ol = list())) lid <- cli_ol() out <- capt0({ cli_it("foo") cli_it(c("bar", "foobar")) }, strip_style = TRUE) expect_equal(out, "1. foo\n2. bar\n3. foobar\n") cli_end(lid) }) test_that("ul ul", { cli_div(theme = list( ul = list("list-style-type" = "*"), "ul ul" = list("list-style-type" = "-"), it = list("margin-left" = 2) )) lid <- cli_ul() out <- capt0({ cli_it("1") lid2 <- cli_ul() cli_it("1 1") cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "* 1\n - 1 1\n - 1 2\n - 1 3\n* 2\n") cli_end(lid) }) test_that("ul ol", { cli_div(theme = list( ul = list("list-style-type" = "*"), it = list("margin-left" = 2) )) lid <- cli_ul() out <- capt0({ cli_it("1") lid2 <- cli_ol() cli_it("1 1") cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "* 1\n 1. 1 1\n 2. 1 2\n 3. 1 3\n* 2\n") cli_end(lid) }) test_that("ol ol", { cli_div(theme = list( it = list("margin-left" = 2) )) lid <- cli_ol() out <- capt0({ cli_it("1") lid2 <- cli_ol() cli_it("1 1") cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "1. 1\n 1. 1 1\n 2. 1 2\n 3. 1 3\n2. 2\n") cli_end(lid) }) test_that("ol ul", { cli_div(theme = list( ul = list("list-style-type" = "*"), it = list("margin-left" = 2) )) lid <- cli_ol() out <- capt0({ cli_it("1") lid2 <- cli_ul() cli_it("1 1") cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "1. 1\n * 1 1\n * 1 2\n * 1 3\n2. 2\n") cli_end(lid) }) test_that("starting with an item", { cli_div(theme = list(ul = list("list-style-type" = "*"))) out <- capt0({ cli_it("foo") cli_it(c("bar", "foobar")) }, strip_style = TRUE) expect_equal(out, "* foo\n* bar\n* foobar\n") }) test_that("ol, with first item", { cli_div(theme = list(ol = list())) out <- capt0({ lid <- cli_ol("foo", .close = FALSE) cli_it(c("bar", "foobar")) }, strip_style = TRUE) expect_equal(out, "1. foo\n2. bar\n3. foobar\n") cli_end(lid) }) test_that("ul, with first item", { cli_div(theme = list(ul = list("list-style-type" = "*"))) out <- capt0({ lid <- cli_ul("foo", .close = FALSE) cli_it(c("bar", "foobar")) }, strip_style = TRUE) expect_equal(out, "* foo\n* bar\n* foobar\n") cli_end(lid) }) test_that("dl", { cli_div(theme = list(ul = list())) lid <- cli_dl() out <- capt0({ cli_it(c(this = "foo")) cli_it(c(that = "bar", other = "foobar")) }, strip_style = TRUE) expect_equal(out, "this: foo\nthat: bar\nother: foobar\n") cli_end(lid) }) test_that("dl dl", { cli_div(theme = list( it = list("margin-left" = 2) )) lid <- cli_dl() out <- capt0({ cli_it(c(a = "1")) lid2 <- cli_dl() cli_it(c("a-a" = "1 1")) cli_it(c("a-b" = "1 2", "a-c" = "1 3")) cli_end(lid2) cli_it(c(b = "2")) }, strip_style = TRUE) expect_equal(out, "a: 1\n a-a: 1 1\n a-b: 1 2\n a-c: 1 3\nb: 2\n") cli_end(lid) }) test_that("dl ol", { cli_div(theme = list( it = list("margin-left" = 2) )) lid <- cli_dl() out <- capt0({ cli_it(c(a = "1")) lid2 <- cli_ol() cli_it(c("1 1")) cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it(c(b = "2")) }, strip_style = TRUE) expect_equal(out, "a: 1\n 1. 1 1\n 2. 1 2\n 3. 1 3\nb: 2\n") cli_end(lid) }) test_that("dl ul", { cli_div(theme = list( ul = list("list-style-type" = "*"), it = list("margin-left" = 2) )) lid <- cli_dl() out <- capt0({ cli_it(c(a = "1")) lid2 <- cli_ul() cli_it(c("1 1")) cli_it(c("1 2", "1 3")) cli_end(lid2) cli_it(c(b = "2")) }, strip_style = TRUE) expect_equal(out, "a: 1\n * 1 1\n * 1 2\n * 1 3\nb: 2\n") cli_end(lid) }) test_that("ol dl", { cli_div(theme = list( it = list("margin-left" = 2) )) lid <- cli_ol() out <- capt0({ cli_it("1") lid2 <- cli_dl() cli_it(c("a-a" = "1 1")) cli_it(c("a-b" = "1 2", "a-c" = "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "1. 1\n a-a: 1 1\n a-b: 1 2\n a-c: 1 3\n2. 2\n") cli_end(lid) }) test_that("ul dl", { cli_div(theme = list( ul = list("list-style-type" = "*"), it = list("margin-left" = 2) )) lid <- cli_ul() out <- capt0({ cli_it("1") lid2 <- cli_dl() cli_it(c("a-a" = "1 1")) cli_it(c("a-b" = "1 2", "a-c" = "1 3")) cli_end(lid2) cli_it("2") }, strip_style = TRUE) expect_equal(out, "* 1\n a-a: 1 1\n a-b: 1 2\n a-c: 1 3\n* 2\n") cli_end(lid) }) test_that("dl, with first item", { cli_div(theme = list(ul = list())) out <- capt0({ lid <- cli_dl(c(this = "foo"), .close = FALSE) cli_it(c(that = "bar", other = "foobar")) }, strip_style = TRUE) expect_equal(out, "this: foo\nthat: bar\nother: foobar\n") cli_end(lid) }) cliapp/tests/testthat/test-substitution.R0000644000176200001440000000030513375603045020404 0ustar liggesusers context("substitution") setup(start_app()) teardown(stop_app()) test_that("glue errors", { expect_error(cli_h1("foo { asdfasdfasdf } bar")) expect_error(cli_text("foo {cmd {dsfsdf()}}")) }) cliapp/tests/testthat/test-inline.R0000644000176200001440000000200013375603045017100 0ustar liggesusers context("cli inline") setup(start_app()) teardown(stop_app()) test_that("inline classes", { classes <- c( "emph", "strong", "code", "pkg", "fun", "arg", "key", "file", "path", "email", "url", "var", "envvar") do <- function(class) { special_style <- structure( list( list(color = "cyan"), list(content = "<<<"), list(content =">>>")), names = c( paste0("span.", class), paste0("span.", class, "::before"), paste0("span.", class, "::after") ) ) cli_div(theme = special_style) withr::with_options(list(crayon.enabled = TRUE, crayon.colors = 256), { txt <- glue::glue("This is { it} really", .open = "<", .close = ">") out <- capt0(cli_text(txt)) expect_true(crayon::has_style(out)) expect_match(crayon::strip_style(out), "<<>>", info = class) expect_match(out, start(crayon::make_style("cyan")), fixed = TRUE, info = class) }) } lapply(classes, do) }) cliapp/tests/testthat/helper.R0000644000176200001440000000157713375603045016146 0ustar liggesusers test_style <- function() { list( ".testcli" = list( h1 = list( "font-weight" = "bold", "font-style" = "italic", "margin-top" = 1, "margin-bottom" = 1), h2 = list( "font-weight" = "bold", "margin-top" = 1, "margin-bottom" = 1), h3 = list( "text-decoration" = "underline", "margin-top" = 1) ) ) } capture_messages <- function(expr) { msgs <- character() i <- 0 suppressMessages(withCallingHandlers( expr, message = function(e) msgs[[i <<- i + 1]] <<- conditionMessage(e))) paste0(msgs, collapse = "") } capt <- function(expr, print_it = TRUE) { pr <- if (print_it) print else identity paste(capture.output(pr(expr)), collapse = "\n") } capt0 <- function(expr, strip_style = FALSE) { out <- capture_messages(expr) if (strip_style) crayon::strip_style(out) else out } cliapp/tests/testthat/test-containers.R0000644000176200001440000000544713375603045020011 0ustar liggesusers context("cli containers") setup(start_app()) teardown(stop_app()) test_that("auto closing", { cli_div(theme = list(".xx .emph::before" = list(content = "itsu:"))) id <- "" out <- "" f <- function() { capt0(id <<- cli_par(class = "xx")) out <<- capt0(cli_text("foo {emph blah} bar")) } capt0(f()) expect_match(out, "itsu:", fixed = TRUE) out <- capt0(cli_text("foo {emph blah} bar")) expect_false(grepl("itsu:", out, fixed = TRUE)) }) test_that("opt out of auto closing", { cli_div(theme = list(".xx .emph::before" = list(content = "itsu:"))) id <- NULL f <- function() { capt0(id <<- cli_par(class = "xx", .auto_close = FALSE)) out <- capt0(cli_text("foo {emph blah} bar")) expect_match(out, "itsu:", fixed = TRUE) } capt0(f()) ## Still active out <- capt0(cli_text("foo {emph blah} bar")) expect_match(out, "itsu:", fixed = TRUE) ## close explicitly expect_false(is.null(id)) capt0(cli_end(id)) out <- capt0(cli_text("foo {emph blah} bar")) expect_false(grepl("itsu:", out, fixed = TRUE)) }) test_that("auto closing with special env", { cli_div(theme = list(".xx .emph::before" = list(content = "itsu:"))) id <- NULL f <- function() { g() ## Still active out <- capt0(cli_text("foo {emph blah} bar")) expect_match(out, "itsu:", fixed = TRUE) } g <- function() { capt0(id <<- cli_par(class = "xx", .auto_close = TRUE, .envir = parent.frame())) out <- capt0(cli_text("foo {emph blah} bar")) expect_match(out, "itsu:", fixed = TRUE) } capt0(f()) ## Not active any more out <- capt0(cli_text("foo {emph blah} bar")) expect_false(grepl("itsu:", out, fixed = TRUE)) }) test_that("div with special style", { f <- function() { cli_div(theme = list(".xx .emph::before" = list(content = "itsu:"))) capt0(cli_par(class = "xx")) out <- capt0(cli_text("foo {emph blah} bar")) expect_match(out, "itsu:", fixed = TRUE) } capt0(f()) ## Not active any more out <- capt0(cli_text("foo {emph blah} bar")) expect_false(grepl("itsu:", out, fixed = TRUE)) }) test_that("margin is squashed", { cli_div(theme = list(par = list("margin-top" = 3, "margin-bottom" = 3))) out <- capt0({ cli_par(); cli_par(); cli_par() }, strip_style = TRUE) expect_equal(out, "\n\n\n") out <- capt0({ cli_end(); cli_end(); cli_end() }) expect_equal(out, "") out <- capt0({ cli_par(); cli_par(); cli_par() }) expect_equal(out, "") capt0(cli_text(lorem_ipsum())) out <- capt0({ cli_end(); cli_end(); cli_end() }, strip_style = TRUE) expect_equal(out, "\n\n\n") }) test_that("before and after work properly", { cli_div(theme = list( "div.alert-success::before" = list(content ="!!!") )) out <- capt0(cli_alert_success("{pkg foobar} is good")) expect_match(out, "!!!", fixed = TRUE) }) cliapp/tests/testthat/test-subprocess.R0000644000176200001440000000636413376577417020051 0ustar liggesusers context("subprocess") test_that("events are properly generated", { ## This needs callr >= 3.0.0.90001, which is not yet on CRAN if (packageVersion("callr") < "3.0.0.9001") skip("Need newer callr") do <- function() { cliapp::cli_div() cliapp::cli_h1("title") cliapp::cli_text("text") } rs <- callr::r_session$new() on.exit(rs$kill(), add = TRUE) msgs <- list() handler <- function(msg) { msgs <<- c(msgs, list(msg)) if (!is.null(findRestart("muffleMessage"))) { invokeRestart("muffleMessage") } } withCallingHandlers( rs$run(do), cliapp_message = handler) expect_equal(length(msgs), 4) lapply(msgs, expect_s3_class, "cliapp_message") expect_equal(msgs[[1]]$type, "div") expect_equal(msgs[[2]]$type, "h1") expect_equal(msgs[[3]]$type, "text") expect_equal(msgs[[4]]$type, "end") rs$close() }) test_that("subprocess with default handler", { ## This needs callr >= 3.0.0.90001, which is not yet on CRAN if (packageVersion("callr") < "3.0.0.9001") skip("Need newer callr") do <- function() { cliapp::cli_div() cliapp::cli_h1("title") cliapp::cli_text("text") } rs <- callr::r_session$new() on.exit(rs$kill(), add = TRUE) msgs <- list() withr::with_options(list( cli.default_handler = function(msg) { msgs <<- c(msgs, list(msg)) if (!is.null(findRestart("muffleMessage"))) { invokeRestart("muffleMessage") } }), rs$run(do) ) expect_equal(length(msgs), 4) lapply(msgs, expect_s3_class, "cliapp_message") expect_equal(msgs[[1]]$type, "div") expect_equal(msgs[[2]]$type, "h1") expect_equal(msgs[[3]]$type, "text") expect_equal(msgs[[4]]$type, "end") rs$close() }) test_that("output in child process", { ## This needs callr >= 3.0.0.90001, which is not yet on CRAN if (packageVersion("callr") < "3.0.0.9001") skip("Need newer callr") do <- function() { options(crayon.enabled = TRUE) options(crayon.colors = 256) crayon::num_colors(forget = TRUE) withCallingHandlers( cliapp_message = function(msg) { withCallingHandlers( cliapp:::cli_server_default(msg), message = function(mmsg) { class(mmsg) <- c("callr_message", "message", "condition") signalCondition(mmsg) invokeRestart("muffleMessage") } ) invokeRestart("muffleMessage") }, { cliapp::start_app(theme = cliapp::simple_theme()) cliapp::cli_h1("Title") cliapp::cli_text("This is generated in the {emph subprocess}.") "foobar" } ) } rs <- callr::r_session$new() on.exit(rs$kill(), add = TRUE) msgs <- list() result <- withCallingHandlers( callr_message = function(msg) { msgs <<- c(msgs, list(msg)) if (!is.null(findRestart("muffleMessage"))) { invokeRestart("muffleMessage") } }, rs$run_with_output(do) ) expect_equal(result$stdout, "") expect_equal(result$stderr, "") expect_identical(result$result, "foobar") expect_null(result$error) lapply(msgs, expect_s3_class, "callr_message") str <- paste(vcapply(msgs, "[[", "message"), collapse = "") expect_true(crayon::has_style(str)) expect_match(str, "Title") expect_match(str, "This is generated") rs$close() }) cliapp/NAMESPACE0000644000176200001440000000240213377471374012757 0ustar liggesusers# Generated by roxygen2: do not edit by hand export(builtin_theme) export(cli_alert) export(cli_alert_danger) export(cli_alert_info) export(cli_alert_success) export(cli_alert_warning) export(cli_div) export(cli_dl) export(cli_end) export(cli_h1) export(cli_h2) export(cli_h3) export(cli_it) export(cli_ol) export(cli_par) export(cli_progress_bar) export(cli_text) export(cli_ul) export(cli_verbatim) export(console_width) export(default_app) export(simple_theme) export(start_app) export(stop_app) importFrom(R6,R6Class) importFrom(cli,symbol) importFrom(crayon,bold) importFrom(crayon,col_substr) importFrom(crayon,combine_styles) importFrom(crayon,italic) importFrom(crayon,make_style) importFrom(crayon,underline) importFrom(fansi,strwrap_ctl) importFrom(glue,glue) importFrom(glue,glue_collapse) importFrom(progress,progress_bar) importFrom(selectr,css_to_xpath) importFrom(stats,na.omit) importFrom(utils,globalVariables) importFrom(utils,head) importFrom(utils,modifyList) importFrom(utils,tail) importFrom(withr,defer) importFrom(xml2,read_html) importFrom(xml2,xml_add_child) importFrom(xml2,xml_attr) importFrom(xml2,xml_find_all) importFrom(xml2,xml_find_first) importFrom(xml2,xml_name) importFrom(xml2,xml_parent) importFrom(xml2,xml_path) importFrom(xml2,xml_remove) cliapp/NEWS.md0000644000176200001440000000004013401716341012612 0ustar liggesusers # 0.1.0 First public release. cliapp/R/0000755000176200001440000000000013376002042011720 5ustar liggesuserscliapp/R/server.R0000644000176200001440000000045413375603045013365 0ustar liggesusers cli_server_default <- function(msg) { cli_server_default_safe(msg) } cli_server_default_safe <- function(msg) { type <- as.character(msg$type)[1] app <- default_app() %||% start_app() do.call(app[[type]], msg$args) } cli_server_callr_handler <- function(msg) { cli_server_default(msg) } cliapp/R/cli.R0000644000176200001440000001701113375751761012634 0ustar liggesusers #' @importFrom R6 R6Class cliapp <- R6Class( "cliapp", public = list( initialize = function(theme = getOption("cli.theme"), user_theme = getOption("cli.user_theme"), output = c("message", "stdout")) clii_init(self, private, theme, user_theme, match.arg(output)), ## Themes list_themes = function() clii_list_themes(self, private), add_theme = function(theme) clii_add_theme(self, private, theme), remove_theme = function(id) clii_remove_theme(self, private, id), ## Close container(s) end = function(id) clii_end(self, private, id), ## Generic container div = function(id, class = NULL, theme = NULL) clii_div(self, private, id, class, theme), ## Paragraphs par = function(id, class = NULL) clii_par(self, private, id, class), ## Text, wrapped text = function(...) clii_text(self, private, ...), ## Text, not wrapped verbatim = function(...) clii_verbatim(self, private, ...), ## Markdow(ish) text, wrapped: emphasis, strong emphasis, links, code md_text = function(...) clii_md_text(self, private, ...), ## Headers h1 = function(text, id, class = NULL) clii_h1(self, private, text, id, class), h2 = function(text, id, class = NULL) clii_h2(self, private, text, id, class), h3 = function(text, id, class = NULL) clii_h3(self, private, text, id, class), ## Block quote blockquote = function(quote, citation = NULL, id, class = NULL) clii_blockquote(self, private, quote, citation, id, class), ## Lists ul = function(items = NULL, id = NULL, class = NULL, .close = TRUE) clii_ul(self, private, items, id, class, .close), ol = function(items = NULL, id, class = NULL, .close = TRUE) clii_ol(self, private, items, id, class, .close), dl = function(items = NULL, id, class = NULL, .close = TRUE) clii_dl(self, private, items, id, class, .close), it = function(items = NULL, id = NULL, class = NULL) clii_it(self, private, items, id, class), ## Code code = function(lines, id, class = NULL) clii_code(self, private, lines, class), ## Tables table = function(cells, id, class = NULL) clii_table(self, private, cells, class), ## Alerts alert = function(text, id, class = NULL, wrap = FALSE) clii_alert(self, private, "alert", text, id, class, wrap), alert_success = function(text, id, class = NULL, wrap = FALSE) clii_alert(self, private, "alert-success", text, id, class, wrap), alert_danger = function(text, id, class = NULL, wrap = FALSE) clii_alert(self, private, "alert-danger", text, id, class, wrap), alert_warning = function(text, id, class = NULL, wrap = FALSE) clii_alert(self, private, "alert-warning", text, id, class, wrap), alert_info = function(text, id, class = NULL, wrap = FALSE) clii_alert(self, private, "alert-info", text, id, class, wrap), ## Progress bars progress_bar = function(id, ...) clii_progress_bar(self, private, id, ...), progress = function(id, operation, ...) clii_progress(self, private, id, operation, ...) ), private = list( raw_themes = NULL, theme = NULL, margin = 0, state = NULL, output = NULL, get_matching_styles = function() tail(private$state$matching_styles, 1)[[1]], get_style = function() tail(private$state$styles, 1)[[1]], xtext = function(..., .list = NULL, indent = 0) clii__xtext(self, private, ..., .list = .list, indent = indent), vspace = function(n = 1) clii__vspace(self, private, n), inline = function(..., .list = NULL) clii__inline(self, private, ..., .list = .list), item_text = function(type, name, cnt_id, ..., .list = NULL) clii__item_text(self, private, type, name, cnt_id, ..., .list = .list), get_width = function() clii__get_width(self, private), cat = function(lines) clii__cat(self, private, lines), cat_ln = function(lines, indent = 0) clii__cat_ln(self, private, lines, indent), match_theme = function(element_path) clii__match_theme(self, private, element_path), progress_bars = list(), get_progress_bar = function() clii__get_progress_bar(self, private), cleanup_progress_bars = function() clii__cleanup_progress_bars(self, private) ) ) #' @importFrom xml2 read_html xml_find_first clii_init <- function(self, private, theme, user_theme, output) { private$output <- output private$raw_themes <- list( default = builtin_theme(), optional = theme) private$theme <- theme_create(private$raw_themes) private$state <- list(doc = read_html("")) private$state$current <- xml_find_first(private$state$doc, "./body") private$state$matching_styles <- list(body = private$match_theme("./body")) root_styles <- private$theme[private$state$matching_styles[[1]], ] root_style <- list(main = list(), before = list(), after = list()) for (i in seq_len(nrow(root_styles))) { root_style <- merge_styles(root_style, root_styles[i,]) } private$state$styles <- list(body = root_style) private$state$xstyles <- character() self$add_theme(user_theme) invisible(self) } ## Text ------------------------------------------------------------- #' @importFrom fansi strwrap_ctl clii_text <- function(self, private, ...) { private$xtext(...) } clii_verbatim <- function(self, private, ..., .envir) { style <- private$get_style()$main text <- paste(unlist(list(...), use.names = FALSE), collapse = "\n") if (!is.null(style$fmt)) text <- style$fmt(text) private$cat_ln(text) invisible(self) } clii_md_text <- function(self, private, ...) { stop("Markdown text is not implemented yet") } ## Headers ---------------------------------------------------------- clii_h1 <- function(self, private, text, id, class) { clii__header(self, private, "h1", text, id, class) } clii_h2 <- function(self, private, text, id, class) { clii__header(self, private, "h2", text, id, class) } clii_h3 <- function(self, private, text, id, class) { clii__header(self, private, "h3", text, id, class) } clii__header <- function(self, private, type, text, id, class) { id <- new_uuid() clii__container_start(self, private, type, id = id, class = class) on.exit(clii__container_end(self, private, id), add = TRUE) text <- private$inline(text) style <- private$get_style()$main if (is.function(style$fmt)) text <- style$fmt(text) private$cat_ln(text) invisible(self) } ## Block quote ------------------------------------------------------ clii_blockquote <- function(self, private, quote, citation, id, class) { stop("Quotes are not implemented yet") } ## Table ------------------------------------------------------------ clii_table <- function(self, private, cells, id, class) { stop("Tables are not implemented yet") } ## Alerts ----------------------------------------------------------- clii_alert <- function(self, private, type, text, id, class, wrap) { clii__container_start(self, private, "div", id = id, class = paste(class, "alert", type)) on.exit(clii__container_end(self, private, id), add = TRUE) text <- private$inline(text) style <- private$get_style() text[1] <- paste0(style$before$content, text[1]) text[length(text)] <- paste0(text[length(text)], style$after$content) if (is.function(style$main$fmt)) text <- style$main$fmt(text) if (wrap) text <- strwrap_ctl(text, exdent = 2) private$cat_ln(text) invisible(self) } cliapp/R/html-readme.R0000644000176200001440000000250713375764176014274 0ustar liggesusers knit_print.html <- function(x, zoom = 2, ...) { x <- paste(x, collapse = "\n") html <- html_page(fansi::sgr_to_html(x)) html_file <- tempfile(fileext = ".html") font_file <- file.path(dirname(html_file), "Menlo-Regular.ttf") file.copy( system.file(package = "cli", "Menlo-Regular.ttf"), font_file ) on.exit(unlink(c(html_file, font_file)), add = TRUE) image_file <- tempfile(fileext = ".png") on.exit(unlink(image_file), add = TRUE) cat(html, file = html_file) asNamespace("webshot")$webshot(html_file, image_file, selector = "#content", zoom = zoom) img <- readBin(image_file, "raw", file.info(image_file)[, "size"]) structure( list(image = img, extension = ".png", url = NULL), class = "html_screenshot" ) } html_page <- function(content) { html <- paste0( '
\n',
    content, '
         
' ) structure(html, class = "html") } cliapp/R/utils.R0000644000176200001440000000244713375603045013223 0ustar liggesusers `%||%` <- function(l, r) if (is.null(l)) r else l vcapply <- function(X, FUN, ..., USE.NAMES = TRUE) { vapply(X, FUN, FUN.VALUE = character(1), ..., USE.NAMES = USE.NAMES) } viapply <- function(X, FUN, ..., USE.NAMES = TRUE) { vapply(X, FUN, FUN.VALUE = integer(1), ..., USE.NAMES = USE.NAMES) } vlapply <- function(X, FUN, ..., USE.NAMES = TRUE) { vapply(X, FUN, FUN.VALUE = logical(1), ..., USE.NAMES = USE.NAMES) } new_uuid <- (function() { cnt <- 0 function() { cnt <<- cnt + 1 paste0("cli-", cliappenv$pid, "-", cnt) } })() #' @importFrom utils tail tail_na <- function(x, n = 1) { tail(c(rep(NA, n), x), n) } #' @importFrom crayon col_substr dedent <- function(x, n = 2) { first_n_char <- strsplit(col_substr(x, 1, n), "")[[1]] n_space <- cumsum(first_n_char == " ") d_n_space <- diff(c(0, n_space)) first_not_space <- head(c(which(d_n_space == 0), n + 1), 1) col_substr(x, first_not_space, nchar(x)) } strrep <- function(x, times) { x <- as.character(x) if (length(x) == 0L) return(x) r <- .mapply( function(x, times) { if (is.na(x) || is.na(times)) return(NA_character_) if (times <= 0L) return("") paste0(replicate(times, x), collapse = "") }, list(x = x, times = times), MoreArgs = list() ) unlist(r, use.names = FALSE) } cliapp/R/docs.R0000644000176200001440000001522013375751644013015 0ustar liggesusers #' CLI inline markup #' #' @section Command substitution: #' #' All text emitted by cliapp supports glue interpolation. Expressions #' enclosed by braces will be evaluated as R code. See [glue::glue()] for #' details. #' #' In addition to regular glue interpolation, cliapp can also add classes #' to parts of the text, and these classes can be used in themes. For #' example #' #' ``` #' cli_text("This is {emph important}.") #' ``` #' #' adds a class to the "important" word, class "emph". Note that in this #' cases the string within the braces is not a valid R expression. If you #' want to mix classes with interpolation, add another pair of braces: #' #' ``` #' adjective <- "great" #' cli_text("This is {emph {adjective}}.") #' ``` #' #' An inline class will always create a `span` element internally. So in #' themes, you can use the `span.emph` CSS selector to change how inline #' text is emphasized: #' #' ``` #' cli_div(theme = list(span.emph = list(color = "red"))) #' adjective <- "nice and red" #' cli_text("This is {emph {adjective}}.") #' ``` #' #' @section Classes: #' #' The default theme defines the following inline classes: #' * `emph` for emphasized text. #' * `strong` for strong importance. #' * `code` for a piece of code. #' * `pkg` for a package name. #' * `fun` for a function name. #' * `arg` for a function argument. #' * `key` for a keyboard key. #' * `file` for a file name. #' * `path` for a path (essentially the same as `file`). #' * `email` for an email address. #' * `url` for a URL. #' * `var` for a variable name. #' * `envvar` for the name of an environment variable. #' #' See examples below. #' #' You can simply add new classes by defining them in the theme, and then #' using them, see the example below. #' #' @name inline-markup #' @examples #' ## Some inline markup examples #' cli_ul() #' cli_it("{emph Emphasized} text") #' cli_it("{strong Strong} importance") #' cli_it("A piece of code: {code sum(a) / length(a)}") #' cli_it("A package name: {pkg cliapp}") #' cli_it("A function name: {fun cli_text}") #' cli_it("A function argument: {arg text}") #' cli_it("A keyboard key: press {key ENTER}") #' cli_it("A file name: {file /usr/bin/env}") #' cli_it("An email address: {email bugs.bunny@acme.com}") #' cli_it("A URL: {url https://acme.com}") #' cli_it("A variable name: {var mtcars}") #' cli_it("An environment variable: {envvar R_LIBS}") #' cli_end() #' #' ## Adding a new class #' cli_div(theme = list( #' span.myclass = list(color = "lightgrey"), #' "span.myclass::before" = list(content = "["), #' "span.myclass::after" = list(content = "]"))) #' cli_text("This is {myclass in brackets}.") #' cli_end() NULL #' CLI containers #' #' Container elements may contain other elements. Currently the following #' commands create container elements: [cli_div()], [cli_par()], the list #' elements: [cli_ul()], [cli_ol()], [cli_dl()], and list items are #' containers as well: [cli_it()]. #' #' Container elements need to be closed with [cli_end()]. For convenience, #' they are have an `.auto_close` argument, which allows automatically #' closing a container element, when the function that created it #' terminates (either regularly, or with an error). #' #' @name containers #' @examples #' ## div with custom theme #' d <- cli_div(theme = list(h1 = list(color = "blue", #' "font-weight" = "bold"))) #' cli_h1("Custom title") #' cli_end(d) #' #' ## Close automatically #' div <- function() { #' cli_div(class = "tmp", theme = list(.tmp = list(color = "yellow"))) #' cli_text("This is yellow") #' } #' div() #' cli_text("This is not yellow any more") NULL #' CLI themes #' #' CLI elements can be styled via a CSS-like language of selectors and #' properties. Note that while most of the CSS3 language is supported, #' a lot visual properties cannot be implemented on a terminal, so these #' will be ignored. #' #' @section Adding themes: #' The style of an element is calculated from themes from four sources. #' These form a stack, and the styles on the top of the stack take #' precedence, over styles in the bottom. #' #' 1. The cliapp package has a builtin theme. This is always active. #' See [builtin_theme()]. #' 2. When an app object is created via [start_app()], the caller can #' specify a theme, that is added to theme stack. If no theme is #' specified for [start_app()], the content of the `cli.theme` option #' is used. Removed when the corresponding app stops. #' 3. The user may speficy a theme in the `cli.user_theme` option. This #' is added to the stack _after_ the app's theme (step 2.), so it can #' override its settings. Removed when the app that added it stops. #' 4. Themes specified explicitly in [cli_div()] elements. These are #' removed from the theme stack, when the corresponding [cli_div()] #' elements are closed. #' #' @section Writing themes: #' A theme is a named list of lists. The name of each entry is a CSS #' selector. Most features of CSS selectors are supported here:, for a #' complete reference, see the selectr package. #' #' The content of a theme list entry is another named list, where the #' names are CSS properties, e.g. `color`, or `font-weight` or #' `margin-left`, and the list entries themselves define the values of #' the properties. See [builtin_theme()] and [simple_theme()] for examples. #' #' @section CSS pseudo elements: #' Currently only the `::before` and `::after` pseudo elements are #' supported. #' #' @section Formatter callbacks: #' For flexibility, themes may also define formatter functions, with #' property name `fmt`. These will be called once the other styles are #' applied to an element. They are only called on elements that produce #' output, i.e. _not_ on container elements. #' #' @section Supported properties: #' Right now only a limited set of properties are supported. These include #' left, right, top and bottom margins, background and foreground colors, #' bold and italic fonts, underlined text. The `content` property is #' supported to insert text via `::before` and `::after` selectors. #' #' More properties might be adder later. #' #' Please see the example themes and the source code for now for the #' details. #' #' @section Examples: #' Color of headers, that are only active in paragraphs with an #' 'output' class: #' ``` #' list( #' "par.output h1" = list("background-color" = "red", color = "#e0e0e0"), #' "par.output h2" = list("background-color" = "orange", color = "#e0e0e0"), #' "par.output h3" = list("background-color" = "blue", color = "#e0e0e0") #' ) #' ``` #' #' Create a custom alert type: #' ``` #' list( #' ".alert-start::before" = list(content = symbol$play), #' ".alert-stop::before" = list(content = symbol$stop) #' ) #' ``` #' @name themes NULL cliapp/R/internals.R0000644000176200001440000000420313376002042014041 0ustar liggesusers #' @importFrom fansi strwrap_ctl clii__xtext <- function(self, private, ..., .list, indent) { style <- private$get_style()$main text <- private$inline(..., .list = .list) text <- strwrap_ctl(text, width = private$get_width()) if (!is.null(style$fmt)) text <- style$fmt(text) private$cat_ln(text, indent = indent) invisible(self) } clii__get_width <- function(self, private) { style <- private$get_style()$main left <- style$`margin-left` %||% 0 right <- style$`margin-right` %||% 0 console_width() - left - right } clii__cat <- function(self, private, lines) { if (private$output == "message") { clii__message(lines, appendLF = FALSE) } else { cat(lines, sep = "") } private$margin <- 0 } clii__cat_ln <- function(self, private, lines, indent) { if (!is.null(item <- private$state$delayed_item)) { private$state$delayed_item <- NULL return(private$item_text(item$type, NULL, item$cnt_id, .list = lines)) } style <- private$get_style()$main ## left margin left <- style$`margin-left` %||% 0 if (length(lines) && left) lines <- paste0(strrep(" ", left), lines) ## indent or negative indent if (length(lines)) { if (indent < 0) { lines[1] <- dedent(lines[1], - indent) } else if (indent > 0) { lines[1] <- paste0(strrep(" ", indent), lines[1]) } } ## zero out margin private$margin <- 0 bar <- private$get_progress_bar() if (is.null(bar)) { if (private$output == "message") { clii__message(paste0(lines, "\n"), appendLF = FALSE) } else { cat(paste0(lines, "\n"), sep = "") } } else { msg <- paste(lines, sep = "\n") msg <- crayon::reset(msg) bar$message(msg, set_width = FALSE) } } clii__vspace <- function(self, private, n) { if (private$margin < n) { sp <- strrep("\n", n - private$margin) if (private$output == "message") { clii__message(sp, appendLF = FALSE) } else { cat(sp) } private$margin <- n } } clii__message <- function(..., domain = NULL, appendLF = TRUE) { msg <- .makeMessage(..., domain = domain, appendLF = appendLF) msg <- crayon::reset(msg) message(msg, appendLF = FALSE) } cliapp/R/themes.R0000644000176200001440000001264213375752302013347 0ustar liggesusers #' @importFrom cli symbol clii_list_themes <- function(self, private) { private$raw_themes } clii_add_theme <- function(self, private, theme) { id <- new_uuid() private$raw_themes <- c(private$raw_themes, structure(list(theme), names = id)) private$theme <- theme_create(private$raw_themes) id } clii_remove_theme <- function(self, private, id) { if (! id %in% names(private$raw_themes)) return(invisible(FALSE)) private$raw_themes[[id]] <- NULL private$theme <- theme_create(private$raw_themes) invisible(TRUE) } #' The built-in CLI theme #' #' This theme is always active, and it is at the bottom of the theme #' stack. See [themes]. #' #' @seealso [themes], [simple_theme()]. #' @return A named list, a CLI theme. #' #' @export builtin_theme <- function() { list( body = list(), h1 = list( "font-weight" = "bold", "font-style" = "italic", "margin-top" = 1, "margin-bottom" = 1), h2 = list( "font-weight" = "bold", "margin-top" = 1, "margin-bottom" = 1), h3 = list( "text-decoration" = "underline", "margin-top" = 1), ".alert::before" = list( content = paste0(symbol$arrow_right, " ") ), ".alert-success::before" = list( content = paste0(crayon::green(symbol$tick), " ") ), ".alert-danger::before" = list( content = paste0(crayon::red(symbol$cross), " ") ), ".alert-warning::before" = list( content = paste0(crayon::yellow("!"), " ") ), ".alert-info::before" = list( content = paste0(crayon::cyan(symbol$info), " ") ), par = list("margin-top" = 1, "margin-bottom" = 1), ul = list("list-style-type" = symbol$bullet), "ul ul" = list("list-style-type" = symbol$circle), "ul ul ul" = list("list-style-type" = symbol$line), ol = list(), dl = list(), it = list("margin-left" = 2), .code = list(), span.emph = list("font-style" = "italic"), span.strong = list("font-weight" = "bold"), span.code = list(color = "magenta"), "span.code::before" = list(content = "`"), "span.code::after" = list(content = "`"), span.pkg = list(color = "magenta"), span.fun = list(color = "magenta"), "span.fun::after" = list(content = "()"), span.arg = list(color = "magenta"), span.key = list(color = "magenta"), "span.key::before" = list(content = "<"), "span.key::after" = list(content = ">"), span.file = list(color = "magenta"), span.path = list(color = "magenta"), span.email = list(color = "magenta"), span.url = list(color = "blue"), "span.url::before" = list(content = "<"), "span.url::after" = list(content = ">"), span.var = list(color = "magenta"), span.envvar = list(color = "magenta") ) } #' @importFrom selectr css_to_xpath to_xpath <- function(sel) { sel2 <- sub(":?:before$", "", sel) sel3 <- sub(":?:after$", "", sel2) css_to_xpath(sel3) } get_selector_mode <- function(sel) { ifelse(grepl(":?:before$", sel), "before", ifelse(grepl(":?:after$", sel), "after", "main")) } theme_create <- function(theme) { mtheme <- unlist(theme, recursive = FALSE, use.names = FALSE) mtheme[] <- lapply(mtheme, create_formatter) selectors <- unlist(lapply(theme, names)) res <- data.frame( stringsAsFactors = FALSE, selector = selectors, xpath = to_xpath(selectors), mode = get_selector_mode(selectors), style = I(mtheme) ) rownames(res) <- NULL res } #' @importFrom crayon bold italic underline make_style combine_styles create_formatter <- function(x) { is_bold <- identical(x[["font-weight"]], "bold") is_italic <- identical(x[["font-style"]], "italic") is_underline <- identical(x[["text-decoration"]], "underline") is_color <- "color" %in% names(x) is_bg_color <- "background-color" %in% names(x) if (!is_bold && !is_italic && !is_underline && !is_color && !is_bg_color) return(x) fmt <- c( if (is_bold) list(bold), if (is_italic) list(italic), if (is_underline) list(underline), if (is_color) make_style(x[["color"]]), if (is_bg_color) make_style(x[["background-color"]], bg = TRUE) ) new_fmt <- do.call(combine_styles, fmt) if (is.null(x[["fmt"]])) { x[["fmt"]] <- new_fmt } else { orig_fmt <- x[["fmt"]] x[["fmt"]] <- function(x) orig_fmt(new_fmt(x)) } x } #' @importFrom xml2 xml_path xml_find_all clii__match_theme <- function(self, private, element_path) { el <- xml_find_first(private$state$doc, element_path) paths <- lapply( private$theme$xpath, function(xp) { vcapply(xml_find_all(private$state$doc, xp), xml_path) } ) which(vlapply(paths, `%in%`, x = xml_path(el))) } #' @importFrom utils modifyList merge_styles <- function(old, new) { old[[new$mode]] <- modifyList(as.list(old[[new$mode]]), new$style[[1]]) old } merge_embedded_styles <- function(oldstyle, newstyle) { old <- oldstyle$main new <- newstyle$main ## side margins are additive, rest is updated, counter is reset top <- new$`margin-top` %||% 0L bottom <- new$`margin-bottom` %||% 0L left <- (old$`margin-left` %||% 0L) + (new$`margin-left` %||% 0L) right <- (old$`margin-right` %||% 0L) + (new$`margin-right` %||% 0L) start <- new$start %||% 1L mrg <- modifyList(old, new) mrg[c("margin-top", "margin-bottom", "margin-left", "margin-right", "start")] <- list(top, bottom, left, right, start) oldstyle$main <- mrg oldstyle$before <- newstyle$before oldstyle$after <- newstyle$after oldstyle } cliapp/R/inline.R0000644000176200001440000000455213375603045013340 0ustar liggesusers #' @importFrom glue glue glue_collapse inline_list <- NULL #' @importFrom utils globalVariables if (getRversion() >= "2.15.1") globalVariables(c("self", "private")) inline_generic <- function(self, private, class, x) { id <- clii__container_start(self, private, "span", class = class) on.exit(clii__container_end(self, private, id), add = TRUE) style <- private$get_style() xx <- paste0(style$before$content, x, style$after$content) if (!is.null(style$main$fmt)) xx <- style$main$fmt(xx) xx } inline_transformer <- function(code, envir) { res <- tryCatch({ expr <- parse(text = code, keep.source = FALSE) eval(expr, envir = envir) }, error = function(e) e) if (!inherits(res, "error")) return(res) code <- glue_collapse(code, "\n") m <- regexpr("(?s)^([[:alnum:]_]+)[[:space:]]+(.+)", code, perl = TRUE) has_match <- m != -1 if (!has_match) stop(res) starts <- attr(m, "capture.start") ends <- starts + attr(m, "capture.length") - 1L captures <- substring(code, starts, ends) funname <- captures[[1]] text <- captures[[2]] out <- glue(text, .envir = envir, .transformer = inline_transformer) inline_generic(self, private, funname, out) } cmd_transformer <- function(code, envir) { res <- tryCatch({ expr <- parse(text = code, keep.source = FALSE) eval(expr, envir = envir) }, error = function(e) e) if (!inherits(res, "error")) return(res) code <- glue_collapse(code, "\n") m <- regexpr("(?s)^([[:alnum:]_]+)[[:space:]]+(.+)", code, perl = TRUE) has_match <- m != -1 if (!has_match) stop(res) starts <- attr(m, "capture.start") ends <- starts + attr(m, "capture.length") - 1L captures <- substring(code, starts, ends) funname <- captures[[1]] text <- captures[[2]] out <- glue(text, .envir = envir, .transformer = cmd_transformer) paste0("{", funname, " ", out, "}") } glue_cmd <- function(..., .envir) { ## This makes a copy that can refer to self and private str <- unlist(list(...), use.names = FALSE) environment(cmd_transformer) <- environment() args <- c(str, list(.envir = .envir, .transformer = cmd_transformer)) do.call(glue, args) } clii__inline <- function(self, private, ..., .list) { ## This makes a copy that can refer to self and private environment(inline_transformer) <- environment() args <- c(list(...), .list, list(.transformer = inline_transformer)) do.call(glue, args) } cliapp/R/containers.R0000644000176200001440000001370113375603045014223 0ustar liggesusers #' @importFrom withr defer #' @importFrom xml2 xml_add_child #' @importFrom glue glue clii__container_start <- function(self, private, tag, class = NULL, id = NULL) { id <- id %||% new_uuid() if (is.null(class)) { private$state$current <- xml_add_child( private$state$current, tag, id = id) } else { private$state$current <- xml_add_child( private$state$current, tag, id = id, class = class) } matching_styles <- private$match_theme( glue("descendant-or-self::*[@id = '{id}']")) new_styles <- private$theme[ setdiff(matching_styles, private$get_matching_styles()), ] private$state$matching_styles <- c(private$state$matching_styles, structure(list(matching_styles), names = id)) new_style <- list(main = list(), before = list(), after = list()) for (i in seq_len(nrow(new_styles))) { new_style <- merge_styles(new_style, new_styles[i, ]) } new_style <- merge_embedded_styles(private$get_style(), new_style) private$state$styles <- c(private$state$styles, structure(list(new_style), names = id)) ## Top margin, if any private$vspace(new_style$main$`margin-top` %||% 0) invisible(id) } #' @importFrom xml2 xml_find_first xml_name xml_remove xml_parent #' xml_attr #' @importFrom utils head #' @importFrom stats na.omit clii__container_end <- function(self, private, id) { ## Do not remove the if (xml_name(private$state$current) == "body") return(invisible(self)) ## Defaults to last container if (is.null(id) || is.na(id)) { id <- xml_attr(private$state$current, "id") } ## Do we have 'id' at all? cnt <- xml_find_first( private$state$doc, glue("descendant-or-self::*[@id = '{id}']")) if (is.na(xml_name(cnt))) return(invisible(self)) ## Remove the whole subtree of 'cnt', pointer is on its parent private$state$current <- xml_parent(cnt) xml_remove(cnt, free = TRUE) rm(cnt) ## Bottom margin del_from <- match(id, names(private$state$matching_styles)) bottom <- max(viapply( private$state$styles[del_from:length(private$state$styles)], function(x) as.integer(x$main$`margin-bottom` %||% 0L) )) private$vspace(bottom) ## Remove styles as well deleted_styles <- tail(names(private$state$matching_styles), -(del_from - 1)) private$state$matching_styles <- head(private$state$matching_styles, del_from - 1) private$state$styles <- head(private$state$styles, del_from - 1) ## Styles that are to be removed when the container ends xstyles <- na.omit(private$state$xstyles[deleted_styles]) if (length(xstyles)) { private$raw_themes[xstyles] <- NULL private$theme <- theme_create(private$raw_themes) private$state$xstyles <- setdiff(private$state$xstyles, xstyles) } invisible(self) } ## div -------------------------------------------------------------- clii_div <- function(self, private, id, class, theme) { theme_id <- self$add_theme(theme) clii__container_start(self, private, "div", class, id) private$state$xstyles <- c(private$state$xstyles, structure(theme_id, names = id)) id } ## Paragraph -------------------------------------------------------- clii_par <- function(self, private, id, class) { clii__container_start(self, private, "par", class, id) } ## Lists ------------------------------------------------------------ clii_ul <- function(self, private, items, id, class, .close) { id <- clii__container_start(self, private, "ul", id = id, class = class) if (length(items)) { self$it(items); if (.close) self$end(id) } invisible(id) } clii_ol <- function(self, private, items, id, class, .close) { id <- clii__container_start(self, private, "ol", id = id, class = class) if (length(items)) { self$it(items); if (.close) self$end(id) } invisible(id) } clii_dl <- function(self, private, items, id, class, .close) { id <- clii__container_start(self, private, "dl", id = id, class = class) if (length(items)) { self$it(items); if (.close) self$end(id) } invisible(id) } #' @importFrom xml2 xml_parent xml_path xml_attr clii_it <- function(self, private, items, id, class) { id <- id %||% new_uuid() ## check the last active list container last <- private$state$current while (! xml_name(last) %in% c("ul", "ol", "dl", "body")) { prev <- last last <- xml_parent(last) } ## if not the last container, close the ones below it if (xml_name(last) != "body" && xml_path(last) != xml_path(private$state$current)) { self$end(xml_attr(prev, "id")) } ## if none, then create an ul container if (xml_name(last) == "body") { cnt_id <- self$ul() type <- "ul" } else { cnt_id <- xml_attr(last, "id") type <- xml_name(last) } if (length(items) > 0) { for (i in seq_along(items)) { id <- clii__container_start(self, private, "it", id = id, class = class) private$item_text(type, names(items)[i], cnt_id, items[[i]]) if (i < length(items)) self$end(id) } } else { private$state$delayed_item <- list(type = type, cnt_id = cnt_id) id <- clii__container_start(self, private, "it", id = id, class = class) } invisible(id) } clii__item_text <- function(self, private, type, name, cnt_id, ..., .list) { style <- private$get_style()$main head <- if (type == "ul") { paste0(style$`list-style-type` %||% "*", " ") } else if (type == "ol") { res <- paste0(private$state$styles[[cnt_id]]$main$start %||% 1L, ". ") private$state$styles[[cnt_id]]$main$start <- (private$state$styles[[cnt_id]]$main$start %||% 1L) + 1L res } else if (type == "dl") { paste0(name, ": ") } private$xtext(.list = c(list(head), list(...), .list), indent = -2) } ## Code ------------------------------------------------------------- clii_code <- function(self, private, lines, id, class) { stop("Code is not implemented yet") } ## Close container(s) ----------------------------------------------- clii_end <- function(self, private, id) { clii__container_end(self, private, id) } cliapp/R/client.R0000644000176200001440000003124713375744455013354 0ustar liggesusers #' CLI text #' #' It is wrapped to the screen width automatically. It may contain inline #' markup. (See [inline-markup].) #' #' @param ... The text to show, in character vectors. They will be #' concatenated into a single string. Newlines are _not_ preserved. #' @param .envir Environment to evaluate the glue expressions in. #' #' @export #' @examples #' cli_text("Hello world!") #' cli_text(packageDescription("cliapp")$Description) #' #' ## Arguments are concatenated #' cli_text("this", "that") #' #' ## Command substitution #' greeting <- "Hello" #' subject <- "world" #' cli_text("{greeting} {subject}!") #' #' ## Inline theming #' cli_text("The {fun cli_text} function in the {pkg cliapp} package") #' #' ## Use within container elements #' ul <- cli_ul() #' cli_it() #' cli_text("{emph First} item") #' cli_it() #' cli_text("{emph Second} item") #' cli_end(ul) cli_text <- function(..., .envir = parent.frame()) { cli__message("text", as.list(glue_cmd(..., .envir = .envir))) } #' CLI verbatim text #' #' It is not wrapped, but printed as is. #' #' @param ... The text to show, in character vectors. Each element is #' printed on a new line. #' @param .envir Environment to evaluate the glue expressions in. #' #' @export #' @examples #' cli_verbatim("This has\nthree", "lines") cli_verbatim <- function(..., .envir = parent.frame()) { cli__message("verbatim", c(list(...), list(.envir = .envir))) } #' CLI headers #' #' @param text Text of the header. It can contain inline markup. #' @param id Id of the header element, string. It can be used in themes. #' @param class Class of the header element, string. It can be used in #' themes. #' @param .envir Environment to evaluate the glue expressions in. #' #' @export #' @examples #' cli_h1("Main title") #' cli_h2("Subtitle") #' cli_text("And some regular text....") cli_h1 <- function(text, id = NULL, class = NULL, .envir = parent.frame()) { cli__message("h1", list(text = glue_cmd(text, .envir = .envir), id = id, class = class)) } #' @rdname cli_h1 #' @export cli_h2 <- function(text, id = NULL, class = NULL, .envir = parent.frame()) { cli__message("h2", list(text = glue_cmd(text, .envir = .envir), id = id, class = class)) } #' @rdname cli_h1 #' @export cli_h3 <- function(text, id = NULL, class = NULL, .envir = parent.frame()) { cli__message("h3", list(text = glue_cmd(text, .envir = .envir), id = id, class = class)) } #' Generic CLI container #' #' See [containers]. A `cli_div` container is special, because it may #' add new themes, that are valid within the container. #' #' @param id Element id, a string. If `NULL`, then a new id is generated #' and returned. #' @param class Class name, sting. Can be used in themes. #' @param theme A custom theme for the container. See [themes]. #' @param .auto_close Whether to close the container, when the calling #' function finishes (or `.envir` is removed, if specified). #' @param .envir Environment to evaluate the glue expressions in. It is #' also used to auto-close the container if `.auto_close` is `TRUE`. #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' ## div with custom theme #' d <- cli_div(theme = list(h1 = list(color = "blue", #' "font-weight" = "bold"))) #' cli_h1("Custom title") #' cli_end(d) #' #' ## Close automatically #' div <- function() { #' cli_div(class = "tmp", theme = list(.tmp = list(color = "yellow"))) #' cli_text("This is yellow") #' } #' div() #' cli_text("This is not yellow any more") cli_div <- function(id = NULL, class = NULL, theme = NULL, .auto_close = TRUE, .envir = parent.frame()) { cli__message("div", list(id = id, class = class, theme = theme), .auto_close = .auto_close, .envir = .envir) } #' CLI paragraph #' #' See [containers]. #' #' @param id Element id, a string. If `NULL`, then a new id is generated #' and returned. #' @param class Class name, sting. Can be used in themes. #' @inheritParams cli_div #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' id <- cli_par() #' cli_text("First paragraph") #' cli_end(id) #' id <- cli_par() #' cli_text("Second paragraph") #' cli_end(id) cli_par <- function(id = NULL, class = NULL, .auto_close = TRUE, .envir = parent.frame()) { cli__message("par", list(id = id, class = class), .auto_close = .auto_close, .envir = .envir) } #' Close a CLI container #' #' @param id Id of the container to close. If missing, the current #' container is closed, if any. #' #' @export #' @examples #' ## If id is omitted #' cli_par() #' cli_text("First paragraph") #' cli_end() #' cli_par() #' cli_text("Second paragraph") #' cli_end() cli_end <- function(id = NULL) { cli__message("end", list(id = id %||% NA_character_)) } #' Unordered CLI list #' #' An unordered list is a container, see [containers]. #' #' @param items If not `NULL`, then a character vector. Each element of #' the vector will be one list item, and the list container will be #' closed by default (see the `.close` argument). #' @param id Id of the list container. Can be used for closing it with #' [cli_end()] or in themes. If `NULL`, then an id is generated and #' retuned invisibly. #' @param class Class of the list container. Can be used in themes. #' @param .close Whether to close the list container if the `items` were #' specified. If `FALSE` then new items can be added to the list. #' @inheritParams cli_div #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' ## Specifying the items at the beginning #' cli_ul(c("one", "two", "three")) #' #' ## Adding items one by one #' cli_ul() #' cli_it("one") #' cli_it("two") #' cli_it("three") #' cli_end() #' #' ## Complex item, added gradually. #' cli_ul() #' cli_it() #' cli_verbatim("Beginning of the {emph first} item") #' cli_text("Still the first item") #' cli_end() #' cli_it("Second item") #' cli_end() cli_ul <- function(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) { cli__message( "ul", list( items = vcapply(items, glue_cmd, .envir = .envir), id = id, class = class, .close = .close), .auto_close = .auto_close, .envir = .envir) } #' Ordered CLI list #' #' An ordered list is a container, see [containers]. #' #' @inheritParams cli_ul #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' ## Specifying the items at the beginning #' cli_ol(c("one", "two", "three")) #' #' ## Adding items one by one #' cli_ol() #' cli_it("one") #' cli_it("two") #' cli_it("three") #' cli_end() #' #' ## Nested lists #' cli_div(theme = list(ol = list("margin-left" = 2))) #' cli_ul() #' cli_it("one") #' cli_ol(c("foo", "bar", "foobar")) #' cli_it("two") #' cli_end() #' cli_end() cli_ol <- function(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) { cli__message( "ol", list( items = vcapply(items, glue_cmd, .envir = .envir), id = id, class = class, .close = .close), .auto_close = .auto_close, .envir = .envir) } #' Definition list #' #' A definition list is a container, see [containers]. #' #' @param items Named character vector, or `NULL`. If not `NULL`, they #' are used as list items. #' @inheritParams cli_ul #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' ## Specifying the items at the beginning #' cli_dl(c(foo = "one", bar = "two", baz = "three")) #' #' ## Adding items one by one #' cli_dl() #' cli_it(c(foo = "one")) #' cli_it(c(bar = "two")) #' cli_it(c(baz = "three")) #' cli_end() cli_dl <- function(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) { cli__message( "dl", list( items = vcapply(items, glue_cmd, .envir = .envir), id = id, class = class, .close = .close), .auto_close = .auto_close, .envir = .envir) } #' CLI list item(s) #' #' A list item is a container, see [containers]. #' #' @param items Character vector of items, or `NULL`. #' @param id Id of the new container. Can be used for closing it with #' [cli_end()] or in themes. If `NULL`, then an id is generated and #' retuned invisibly. #' @param class Class of the item container. Can be used in themes. #' @inheritParams cli_div #' @return The id of the new container element, invisibly. #' #' @export #' @examples #' ## Adding items one by one #' cli_ul() #' cli_it("one") #' cli_it("two") #' cli_it("three") #' cli_end() #' #' ## Complex item, added gradually. #' cli_ul() #' cli_it() #' cli_verbatim("Beginning of the {emph first} item") #' cli_text("Still the first item") #' cli_end() #' cli_it("Second item") #' cli_end() cli_it <- function(items = NULL, id = NULL, class = NULL, .auto_close = TRUE, .envir = parent.frame()) { cli__message( "it", list( items = vcapply(items, glue_cmd, .envir = .envir), id = id, class = class), .auto_close = .auto_close, .envir = .envir) } #' CLI alerts #' #' Alerts are typically short status messages. #' #' @param text Text of the alert. #' @param id Id of the alert element. Can be used in themes. #' @param class Class of the alert element. Can be used in themes. #' @param wrap Whether to auto-wrap the text of the alert. #' @param .envir Environment to evaluate the glue expressions in. #' #' @export #' @examples #' #' cli_alert("Cannot lock package library.") #' cli_alert_success("Package {pkg cliapp} installed successfully.") #' cli_alert_danger("Could not download {pkg cliapp}.") #' cli_alert_warning("Internet seems to be unreacheable.") #' cli_alert_info("Downloaded 1.45MiB of data") cli_alert <- function(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) { cli__message("alert", list(text = glue_cmd(text, .envir = .envir), id = id, class = class, wrap = wrap)) } #' @rdname cli_alert #' @export cli_alert_success <- function(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) { cli__message("alert_success", list(text = glue_cmd(text, .envir = .envir), id = id, class = class, wrap = wrap)) } #' @rdname cli_alert #' @export cli_alert_danger <- function(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) { cli__message("alert_danger", list(text = glue_cmd(text, .envir = .envir), id = id, class = class, wrap = wrap)) } #' @rdname cli_alert #' @export cli_alert_warning <- function(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) { cli__message("alert_warning", list(text = glue_cmd(text, .envir = .envir), id = id, class = class, wrap = wrap)) } #' @rdname cli_alert #' @export cli_alert_info <- function(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) { cli__message("alert_info", list(text = glue_cmd(text, .envir = .envir), id = id, class = class, wrap = wrap)) } #' CLI progress bar #' #' A progress bar using the progress package #' #' @param ... All arguments are passed to the constuctor of the #' [progress::progress_bar] class. #' @return A remote progress bar object that can be used the same way #' as [progress::progress_bar], see examples below. #' #' @export #' @examples #' { #' p <- cli_progress_bar(total = 10) #' cli_alert_info("Starting computation") #' for (i in 1:10) { p$tick(); Sys.sleep(0.2) } #' cli_alert_success("Done") #' } cli_progress_bar <- function(...) { id <- cli__message("progress_bar", list(id = NULL, ...)) cli__remote_progress_bar(id) } cli__message <- function(type, args, .auto_close = TRUE, .envir = NULL) { if ("id" %in% names(args) && is.null(args$id)) args$id <- new_uuid() if (.auto_close && !is.null(.envir) && !identical(.envir, .GlobalEnv)) { defer(cli_end(id = args$id), envir = .envir, priority = "first") } cond <- list(message = paste("cli message", type), type = type, args = args, pid = cliappenv$pid) class(cond) <- c("cliapp_message", "callr_message", "condition") withRestarts({ signalCondition(cond) cli__default_handler(cond) }, muffleMessage = function() NULL) invisible(args$id) } cli__default_handler <- function(msg) { custom_handler <- getOption("cli.default_handler") if (is.function(custom_handler)) { custom_handler(msg) } else { cli_server_default(msg) } } cliapp/R/width.R0000644000176200001440000000072013346167022013170 0ustar liggesusers #' Determine the width of the console #' #' It uses the `RSTUDIO_CONSOLE_WIDTH` environment variable, if set. #' Otherwise it uses the `width` option. If this is not set either, #' then 80 is used. #' #' @return Integer scalar, the console with, in number of characters. #' #' @export console_width <- function() { width <- getOption( "cli.width", Sys.getenv( "RSTUDIO_CONSOLE_WIDTH", getOption("width", 80) ) ) as.integer(width) } cliapp/R/simple-theme.R0000644000176200001440000001350113375752175014456 0ustar liggesusers #' A simple CLI theme #' #' Note that this is in addition to the builtin theme. To use this theme, #' you can set it as the `cli.theme` option: #' #' ``` #' options(cli.theme = cliapp::simple_theme()) #' ``` #' #' and then CLI apps started after this will use it as the default theme. #' You can also use it temporarily, in a div element: #' #' ``` #' cli_div(theme = cliapp::simple_theme()) #' ``` #' #' @param dark Whether the theme should be optiomized for a dark #' background. If `"auto"`, then cliapp will try to detect this. #' Detection usually works in recent RStudio versions, and in iTerm #' on macOS, but not on other platforms. #' #' @seealso [themes], [builtin_theme()]. #' @export #' @examples #' cli_div(theme = cliapp::simple_theme()) #' #' cli_h1("Header 1") #' cli_h2("Header 2") #' cli_h3("Header 3") #' #' cli_alert_danger("Danger alert") #' cli_alert_warning("Warning alert") #' cli_alert_info("Info alert") #' cli_alert_success("Success alert") #' cli_alert("Alert for starting a process or computation", #' class = "alert-start") #' #' cli_text("Packages and versions: {pkg cliapp} {version 1.0.0}.") #' cli_text("Time intervals: {timestamp 3.4s}") #' #' cli_text("{emph Emphasis} and {strong strong emphasis}") #' #' cli_text("This is a piece of code: {code sum(x) / length(x)}") #' cli_text("Function names: {fun cliapp::simple_theme} and {arg arguments}.") #' #' cli_text("Files: {file /usr/bin/env}") #' cli_text("URLs: {url https://r-project.org}") #' #' cli_h2("Longer code chunk") #' cli_par(class = "r-code") #' cli_verbatim( #' '# window functions are useful for grouped mutates', #' 'mtcars %>%', #' ' group_by(cyl) %>%', #' ' mutate(rank = min_rank(desc(mpg)))') #' cli_end() #' #' cli_h2("Even longer code chunk") #' cli_par(class = "r-code") #' cli_verbatim(format(ls)) #' cli_end() #' #' cli_end() simple_theme <- function(dark = "auto") { if (dark == "auto") { dark <- if (Sys.getenv("RSTUDIO", "0") == "1") { tryCatch( rstudioapi::getThemeInfo()$dark, error = function(x) FALSE) } else if (is_iterm()) { is_iterm_dark() } else { FALSE } } list( h1 = list( "margin-top" = 1, "margin-bottom" = 0, color = "cyan", fmt = function(x) cli::rule(x, line_col = "cyan")), h2 = list( "margin-top" = 1, "margin-bottom" = 0, color = "cyan", fmt = function(x) paste0(symbol$line, " ", x, " ", symbol$line, symbol$line)), h3 = list( "margin-top" = 1, "margin-bottom" = 0, color = "cyan"), par = list("margin-top" = 0, "margin-bottom" = 1), ".alert-danger" = list( "background-color" = "red", color = "white" ), ".alert-danger::before" = list( content = paste0(symbol$cross, " ") ), ".alert-warning" = list( color = "orange", "font-weight" = "bold"), ".alert-warning::before" = list( content = paste0("!", " ") ), ".alert-success::before" = list( content = paste0(crayon::green(symbol$tick), " ") ), ".alert-info::before" = list( content = paste0(crayon::cyan(symbol$info), " ") ), ".alert-start::before" = list( content = paste0(symbol$arrow_right, " ")), span.pkg = list( color = "blue", "font-weight" = "bold"), span.version = list(color = "blue"), .code = simple_theme_code(dark), "span.code::before" = list(content = "`"), "span.code::after" = list(content = "`"), ".r-code" = list( fmt = simple_theme_r_code(dark), "margin-top" = 1, "margin-bottom" = 1), span.emph = simple_theme_emph(), span.strong = list("font-weight" = "bold", "font-style" = "italic"), span.fun = simple_theme_code(dark), "span.fun::after" = list(content = "()"), span.arg = simple_theme_code(dark), span.key = simple_theme_code(dark), "span.key::before" = list(content = "<"), "span.key::after" = list(content = ">"), span.file = simple_theme_file(), span.path = simple_theme_file(), span.email = simple_theme_url(), span.url = simple_theme_url(), "span.url::before" = list(content = "<"), "span.url::after" = list(content = ">"), span.var = simple_theme_code(dark), span.envvar = simple_theme_code(dark), span.timestamp = list(color = "grey"), "span.timestamp::before" = list( content = "["), "span.timestamp::after" = list( content = "]") ) } simple_theme_emph <- function() { list("font-style" = "italic") } simple_theme_url <- function() { list(color = "blue") } simple_theme_code <- function(dark) { if (dark) { list("background-color" = "#232323", color = "#f0f0f0") } else{ list("background-color" = "#f8f8f8", color = "#202020") } } simple_theme_file <- function() { list(color = "blue") } simple_theme_r_code <- function(dark) { dark <- dark style <- if (dark) { crayon::combine_styles( crayon::make_style("#232323", bg = TRUE), crayon::make_style("#f0f0f0") ) } else { crayon::combine_styles( crayon::make_style("#f8f8f8", bg = TRUE), crayon::make_style("#202020") ) } function(x) { lines <- strsplit(x, "\n", fixed = TRUE)[[1]] code <- tryCatch(prettycode::highlight(lines), error = function(x) lines) len <- fansi::nchar_ctl(code) padded <- paste0(" ", code, strrep(" ", max(len) - len), " ") style(padded) } } is_iterm <- function() { isatty(stdout()) && Sys.getenv("TERM_PROGRAM", "") == "iTerm.app" } is_iterm_dark <- function() { tryCatch( error = function(x) FALSE, { osa <- ' tell application "iTerm2" tell current session of current window get background color end tell end tell ' out <- system2("osascript", c("-e", shQuote(osa)), stdout = TRUE) nums <- scan(text = gsub(",", "", out), quiet = TRUE) mean(nums) < 20000 }) } cliapp/R/lorem.R0000644000176200001440000000310613346165114013170 0ustar liggesusers lorem_words <- c( "ad", "adipisicing", "aliqua", "aliquip", "amet", "anim", "aute", "cillum", "commodo", "consectetur", "consequat", "culpa", "cupidatat", "deserunt", "do", "dolor", "dolore", "duis", "ea", "eiusmod", "elit", "enim", "esse", "est", "et", "eu", "ex", "excepteur", "exercitation", "fugiat", "id", "in", "incididunt", "ipsum", "irure", "labore", "laboris", "laborum", "Lorem", "magna", "minim", "mollit", "nisi", "non", "nostrud", "nulla", "occaecat", "officia", "pariatur", "proident", "qui", "quis", "reprehenderit", "sint", "sit", "sunt", "tempor", "ullamco", "ut", "velit", "veniam", "voluptate" ) lorem_ipsum <- function(paragraphs = 1, par_sentence_range = 5:10, sentence_word_range = 5:15) { vcapply( 1:paragraphs, function(x, ...) lorem_paragraph(...), par_sentence_range = par_sentence_range, sentence_word_range = sentence_word_range ) } lorem_paragraph <- function(par_sentence_range, sentence_word_range) { num <- sample(par_sentence_range, 1) paste( collapse = " ", vcapply( 1:num, function(x, ...) lorem_sentence(...), sentence_word_range = sentence_word_range ) ) } lorem_sentence <- function(sentence_word_range) { num <- sample(sentence_word_range, 1) words <- sample(lorem_words, num, replace = TRUE) words[1] <- capitalize(words[1]) paste0(paste(words, collapse = " "), ".") } capitalize <- function(x) { substr(x, 1, 1) <- toupper(substr(x, 1, 1)) x } cliapp/R/package.R0000644000176200001440000000576113375747006013466 0ustar liggesusers #' Create Rich Command Line Applications #' #' Create rich command line applications, with colors, headings, lists, #' alerts, progress bars, etc. It uses CSS for theming. #' #' See [themes] for theming, [containers] for container elements, #' [inline-markup] for more about command substitution and inline markup. #' #' See also the various CLI elements: #' * Text elements: [cli_text()], [cli_verbatim()], [cli_h1()]. #' * Containers: [cli_div()], [cli_par()], [cli_end()]. #' * Lists: [cli_ul()], [cli_ol()], [cli_dl()], [cli_it()]. #' * Alerts: [cli_alert()]. #' * Progress bars: [cli_progress_bar()]. #' #' @docType package #' @name cliapp "_PACKAGE" cliappenv <- new.env() cliappenv$stack <- list() cliappenv$pid <- Sys.getpid() .onLoad <- function(libname, pkgname) { if (is.null(getOption("callr.condition_handler_cliapp_message"))) { options(callr.condition_handler_cliapp_message = cli__default_handler) } } #' Start, stop, query the default cli application #' #' `start_app` creates an app, and places it on the top of the app stack. #' #' `stop_app` removes the top app, or multiple apps from the app stack. #' #' `default_app` returns the default app, the one on the top of the stack. #' #' @param theme Theme to use, passed to the [cliapp] initializer. #' @param output How to print the output, passed to [cliapp] initializer. #' @param .auto_close Whether to stop the app, when the calling frame #' is destroyed. #' @param .envir The environment to use, instead of the calling frame, #' to trigger the stop of the app. #' @param app App to stop. If `NULL`, the current default app is stopped. #' Otherwise we find the supplied app in the app stack, and remote it, #' together with all the apps above it. #' @return #' `start_app` returns the new app, `default_app` returns the default app. #' `stop_app` does not return anything. #' #' @export start_app <- function(theme = getOption("cli.theme"), output = c("message", "stdout"), .auto_close = TRUE, .envir = parent.frame()) { app <- cliapp$new( theme = theme, user_theme = getOption("cli.user_theme"), output = match.arg(output)) cliappenv$stack[[length(cliappenv$stack) + 1]] <- app if (.auto_close && !identical(.envir, globalenv())) { defer(stop_app(app = app), envir = .envir, priority = "first") } invisible(app) } #' @export #' @importFrom utils head #' @name start_app stop_app <- function(app = NULL) { if (is.null(app)) { cliappenv$stack <- head(cliappenv$stack, -1) } else { if (!inherits(app, "cliapp")) stop("Not a CLI app") ndl <- format.default(app) nms <- vapply(cliappenv$stack, format.default, character(1)) if (! ndl %in% app) { warning("No app to end") return() } wh <- which(nms == ndl)[1] cliappenv$stack <- head(cliappenv$stack, wh - 1) } invisible() } #' @export #' @importFrom utils tail #' @name start_app default_app <- function() { top <- tail(cliappenv$stack, 1) if (length(top)) top[[1]] else NULL } cliapp/R/progress-bar.R0000644000176200001440000000323113375603045014461 0ustar liggesusers #' @importFrom progress progress_bar clii_progress_bar <- function(self, private, id, ...) { stream <- stderr() if (!nzchar(stream)) stream <- stdout() bar <- progress_bar$new( ..., stream = stream, width = private$get_width()) stbar <- list(bar) names(stbar) <- id private$progress_bars <- c(private$progress_bars, stbar) private$cleanup_progress_bars() invisible() } clii__get_progress_bar <- function(self, private) { finished <- vlapply(private$progress_bars, function(x) x$finished) last <- tail_na(which(!finished)) if (is.na(last)) NULL else private$progress_bars[[last]] } clii__cleanup_progress_bars <- function(self, private) { finished <- vlapply(private$progress_bars, function(x) x$finished) private$progress_bars <- private$progress_bars[!finished] } cli__remote_progress_bar <- function(id) { id <- id bar <- list( tick = function(len = 1, tokens = list()) cli__message("progress", list(id, "tick", len, tokens)), update = function(ratio, tokens = list()) cli__message("progress", list(id, "update", ratio, tokens)), message = function(msg, set_width = TRUE) cli__message("progress", list(id, "message", msg, set_width)), terminate = function() cli__message("progress", list(id, "terminate")), finished = FALSE ) class(bar) <- "cli_remote_progress_bar" bar } clii_progress <- function(self, private, id, operation, ...) { if (!id %in% names(private$progress_bars)) return() bar <- private$progress_bars[[id]] if (bar$finished) { private$progress_bars[[id]] <- NULL } else { bar[[operation]](...) } if (bar$finished) private$progress_bars[[id]] <- NULL } cliapp/README.md0000644000176200001440000000535513375762447013033 0ustar liggesuserscliapp ================ > Create Rich Command Line Applications [![lifecycle](https://img.shields.io/badge/lifecycle-maturing-blue.svg)](https://tidyverse.org/lifecycle/#maturing) [![Linux Build Status](https://travis-ci.org/r-lib/cliapp.svg?branch=master)](https://travis-ci.org/r-lib/cliapp) [![Windows Build status](https://ci.appveyor.com/api/projects/status/github/r-lib/cliapp?svg=true)](https://ci.appveyor.com/project/gaborcsardi/cliapp) [![](http://www.r-pkg.org/badges/version/cliapp)](http://www.r-pkg.org/pkg/cliapp) [![CRAN RStudio mirror downloads](http://cranlogs.r-pkg.org/badges/cliapp)](http://www.r-pkg.org/pkg/cliapp) [![Coverage Status](https://img.shields.io/codecov/c/github/r-lib/cliapp/master.svg)](https://codecov.io/github/r-lib/cliapp?branch=master) Create rich command line applications, with colors, headings, lists, alerts, progress bars, etc. It uses CSS for theming. --- ## Installation ``` r install.packages("cliapp") ``` ## Usage This README uses the simple theme, included in the package, see `?simple_theme()`. ``` r library(cliapp) start_app(theme = simple_theme()) ``` ### Headings `cli_h1()`, `cli_h2()` and `cli_h3()` create three levels of headings: ``` r cli_h1("Title") cli_h2("Subtitle") cli_h3("Subsubtitle") ``` ![](man/figures/headings-1.png)![](man/figures/headings-2.png)![](man/figures/headings-3.png) ### Text and inline markup All (non-verbatim) outputted text runs through `glue::glue()`. In addition to glue interpolation, cliapp also supports inline markup via the `{markup text}` form. The builtin theme defines inline markup classes, see `?inline-markup`. ``` r cli_text("{emph Emphasized text}, {strong Strong} importance. A piece of code: {code sum(a) / length(a)}. Package names: {pkg cliapp}, file names: {path /usr/bin/env}, etc.") ``` ![](man/figures/inline-markup-1.png) ### Alerts ``` r cli_alert("Generic alert") cli_alert_danger("Something went horribly wrong") cli_alert_warning("Better watch out!") cli_alert_info("About to download 1.4GiB of data.") cli_alert_success("All downloads finished successfully") ``` ![](man/figures/alerts-1.png)![](man/figures/alerts-2.png)![](man/figures/alerts-3.png)![](man/figures/alerts-4.png)![](man/figures/alerts-5.png) ### Lists Ordered, unordered and definition lists, they can be nested. See `?cli_ol()`, `?cli_ul()`, `?cli_dl()` and `?cli_it()`. ``` r cli_div(theme = list(ol = list("margin-left" = 2))) cli_ul("one", .close = FALSE) cli_ol(c("foo", "bar", "foobar")) cli_it("two") cli_end() cli_end() ``` ![](man/figures/lists-1.png) ### Progress bars Progress bars are supported via the [progress package](https://github.com/r-lib/progress). ## License MIT © RStudio cliapp/MD50000644000176200001440000000677313405461705012054 0ustar liggesusers6bd2222a39369229a01f647a09b32438 *DESCRIPTION db8df6852a9a4942bd575b66a884b35e *LICENSE 3419b99d49f09d8236514a372f51d79d *NAMESPACE 0c09a262b53f02936bd37ea222c25ec3 *NEWS.md 9f680c4d6576d82ce38d96654bcc2a38 *R/cli.R e585390d0d3bf47dd4a9ee4fea1bf98c *R/client.R d129b53ee3c0c3145d143ee015cc7fea *R/containers.R 9be2a5f01ef3c3fac94127fe1acc5e4d *R/docs.R 1e699fbc79237e169a98b02c984d8d4d *R/html-readme.R af68fa2fd00027a3faa8b3071233f92f *R/inline.R c6b93e66659e6b80afbbd4d36ab83bd7 *R/internals.R ff681a26e738a802bd685bd2961a5039 *R/lorem.R 32ffb08b5d552e22789474ecfa717e3d *R/package.R 159057ceced58d35220d687c6c328224 *R/progress-bar.R 35592b45641d2b147f2d369e5eca46df *R/server.R cf153ddf7f5f4462c3cd74bec971ad61 *R/simple-theme.R 356cb8effff00bf781f1d8a725210596 *R/themes.R ceb6bb3da82c55a1ff1f0968a154bfcb *R/utils.R f854e6ecceade5a650a56a9a87a49ba2 *R/width.R 4af238cb87bc49e1294f90aa5c6227ce *README.md d0a0726da9ccde178a89b7b47a7bda38 *inst/scripts/news.R 8d879471914c9df43ab46d42e5b81ec2 *inst/scripts/outdated.R 0ca0af9956bd9fc2b073053942e092be *inst/scripts/search.R f8e88581365bd3ac8cc9702c44cfd4b5 *inst/scripts/up.R ee02f4443aa4522aaa539e6e7a6a485f *man/builtin_theme.Rd 9ace4754055e9af396d2b6f0660fec77 *man/cli_alert.Rd eaad7699839ecaefe532316c5b606abc *man/cli_div.Rd 6fda3dd1591179ce91b043f477192d96 *man/cli_dl.Rd c6127837fd5c80513c82b4073e689054 *man/cli_end.Rd e963177a506eac0c1a00c03014bcc2d5 *man/cli_h1.Rd 0e0b2a42825c8c5c7a695cfde65dacfd *man/cli_it.Rd ba14bd819ddaad138404897286bcb68d *man/cli_ol.Rd ec8dac8d8338ffd9df7fc60f57e1ef26 *man/cli_par.Rd ac6e96ca84c0873b0ea2e1c9d41db766 *man/cli_progress_bar.Rd 77e203ddd2cfd65b0b1886799d39d867 *man/cli_text.Rd 5b1a5947feedc42998265d8052e1e830 *man/cli_ul.Rd 70da10c978a278924f0294553ea76310 *man/cli_verbatim.Rd 2a6f528b256176ede3eb7ea569dee97e *man/cliapp.Rd af2b8af7935f0dacce4f41f646885a85 *man/console_width.Rd ef46676fd502a3c043229a85623870b0 *man/containers.Rd 5c317cd7c601a237dd8d050dbdbeae7c *man/figures/alerts-1.png 123fa2791de861cc7b1aea42ceaccd6e *man/figures/alerts-2.png 5de86fc300ed9b898b93491d9ed205f1 *man/figures/alerts-3.png 546385190d3ca75fde1d7d4d27f60d90 *man/figures/alerts-4.png 6b36335c351e2714b886c6ff8da915c0 *man/figures/alerts-5.png bffb147000ac04f7ffdfa99e5e4793cf *man/figures/headings-1.png 46053838120342dfab960a74150588a0 *man/figures/headings-2.png d6f003cd105b7ebd5115fd19b05b6665 *man/figures/headings-3.png dfa924577d3ecbfad57d06ee1daadc21 *man/figures/inline-markup-1.png a7a54373cf52b94bc9dd9f4d970c4592 *man/figures/lists-1.png 7479c2468fe123b6cca32f557631043a *man/inline-markup.Rd 558e0bf46790c1c1bccacc74f39b3fce *man/simple_theme.Rd fc2f836a475c1a7190a6f9e5ef28415d *man/start_app.Rd 0a655fa124d9d43957d3febb042e93c5 *man/themes.Rd 7cc6a3e1700de623eea1f2835d5f4438 *tests/testthat.R 8f2e27f155bd4812490a2ad59af15281 *tests/testthat/helper.R 754ba49173a37dc068cc151e0798039d *tests/testthat/test-alerts.R 248a2e02daeffef74e7ffb29f829ef5f *tests/testthat/test-containers.R 5dc5cd95dcccf12605d07373678c42c7 *tests/testthat/test-custom-handler.R fc56969e627760ac89ea7ba6bc79893b *tests/testthat/test-headers.R 1f58b7718493e1ce169795ef8148db42 *tests/testthat/test-inline.R ab342b9ef5e8a6e33bec158aa5e9895f *tests/testthat/test-lists.R 6ec716a7608bd65a6c27dd7fbe73b6f0 *tests/testthat/test-progress-bars.R d233d66c7d64c75b861c99f83c820862 *tests/testthat/test-subprocess.R c971bd6c1ec5e354df75164b4586249d *tests/testthat/test-substitution.R bbb435c5bd6e5e70276ad3f4c48e7905 *tests/testthat/test-text.R 07d96b5ee7da1eac6c83f06291938893 *tests/testthat/test-themes.R cliapp/DESCRIPTION0000644000176200001440000000136713405461705013244 0ustar liggesusersPackage: cliapp Title: Create Rich Command Line Applications Version: 0.1.0 Author: Gábor Csárdi Maintainer: Gábor Csárdi Description: Create rich command line applications, with colors, headings, lists, alerts, progress bars, etc. It uses CSS for custom themes. License: MIT + file LICENSE LazyData: true URL: https://github.com/r-lib/cliapp#readme BugReports: https://github.com/r-lib/cliapp/issues RoxygenNote: 6.1.1 Imports: cli, crayon, fansi, glue (>= 1.3.0), prettycode, progress (>= 1.2.0), R6, selectr, utils, withr, xml2 Suggests: callr, covr, rstudioapi, testthat Encoding: UTF-8 NeedsCompilation: no Packaged: 2018-12-05 09:41:39 UTC; gaborcsardi Repository: CRAN Date/Publication: 2018-12-16 14:40:05 UTC cliapp/man/0000755000176200001440000000000013375754165012315 5ustar liggesuserscliapp/man/cli_verbatim.Rd0000644000176200001440000000074613375603045015241 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_verbatim} \alias{cli_verbatim} \title{CLI verbatim text} \usage{ cli_verbatim(..., .envir = parent.frame()) } \arguments{ \item{...}{The text to show, in character vectors. Each element is printed on a new line.} \item{.envir}{Environment to evaluate the glue expressions in.} } \description{ It is not wrapped, but printed as is. } \examples{ cli_verbatim("This has\\nthree", "lines") } cliapp/man/figures/0000755000176200001440000000000013375762447013763 5ustar liggesuserscliapp/man/figures/alerts-3.png0000644000176200001440000001553113375762441016122 0ustar liggesusersPNG  IHDRJ+JJ pHYs   IDATxyxUչoIB$SdV@Y+J՟SՊtmk[Vmkũ:Vjq" Ȭa)fsrIyg^g@$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I MgSw'6$I$I$IHz_0^=H îcev-h7>L'3VJ~(xk&oeI{鐕I@I&a7p2$JIf:OS=e =/I$I$I tC.SI$+19Y+%4M2hIVU˕'rWͳ,QwJ'PZ:O%4Rڿ{9v$cj.%QJ۱цު.g^ gIVj.ytI\%I$I$I[Mh*f7D*:29u5diI/!'+% 5J#OI$I$I՘Y\ћyL޺h<5^0 hDDıJc6<>OI$I$I.:=25Qie%q+LV-.ʨ^U\B$3YynWwo,( YIvpQ*қ_b2>mVGA]u&ɡY8L㊟= Cqƈ׾VdWUwUW87fw ҖM2˲ 7Q89oVvOPn.QmN˴mNS%  nW-g bd<EVB4I_,]#*+힗EYC9<LO%'||mD_FܟI8;_2(ǩ$I$I$IuR%Ԋ@Ҟ.΅u9L>T~`N{F^j.9MY8Vvw/qg]UZgz_6nDcgoWonytO˓yTeti2-#pz\R2MKg/oes͟1M3hZ<_w n nx~f5=^xj`VgV<}`"O)@cWKzc=^~T|퐎 XR?pq\hu<={cFr@ʇ_SZIrk,=vzevyJ$I$I$K9sgQE,s,*(8`ivjP)u5Vd*RbZY90rr2aVo֠=[Aډ.Y 1/8>/G>Ӫ >C/?g甽(5;3>~m@JINY`*ןusm뜜LʄRjW|HFrSY >\8 ˴ʂρ0iw]+3-wbByJ$I$I$k \z:7JpHfZΜKQ;9%d.Z79VYP FpQXjGG)iԁ.=+5GD&bRp8V~X93 Y.%eXoގܵsNmwf=ؾm,1~ fQged K֯g{Us4N<}g&]ܶ9 ʠN mV6VX8D8XO4Fn# "NI;w"fU5d8?S"M̄Y{R?NJGb+w\;[C:{$I$I$I.=/l;eP+RJsxcL ./d9v egy_ghKf/۠̅s&= ƍ>)8x م`n2J:w,>~K"}^U{~έ霝MMX+7ٛaͬ]}mk,)(T8PNz&^ fOImr|'Ӻ)¢ ;W6"ss}͔٘xϥ}Ia<^(PX(ТQױ hɝL:;CY%GsE͜k7sgb|um N\}sߘ _d)I$I$Iw(%ާJv:&+P|JO% 5^FUK+?ŠFƕ#W>kx˿ >I$I$IVS:2}3ͬ]:(tBbgrM+%vC\ZMlџ'`hCہS9%36c:#Q"P R)O zDϲL],Z+K'P}菎G[jߟdc2J0["K{NiA#%2/{k5 f *fKWcfA L܋Ox{^h|8rn%yd)۔$I$I$I+XqwnC-.6iBmE@KLJu+ DR]{ vpcpobVq(-gs۹8? فA;%f%dιK[WfAWcE U8 ̦%!e{lO 8#|:=;2,e-%$`i]֚vmrhg-fVϾ䳪%\\k>/=DcD1;%9+ֱ}.ѭ%4Mv}}RwX{QK$I$I$jtU{֗kX:%i&gO\ Agp/qLʴx_oK C{;NS7mo;ݴ}L weeËFP%&mh/{pd0wE|7}Acz1?^鵫]=ɓmKHbpr2%k ;g?W&=n_>iKิҵ;u{Řƍh!yKI$I$I=](ۃM[ٸ~} 3^vf:s^ MޝK}sf6f^pܶ9y-[vt/wEnp {`AŲWO5j|]~_E2ƍDȏoH%Cldudob/!#I$I$I}՘<Al_ҢiHO_ࢠQyppK[N n/8~RR<&yu.י"%9O 9-LZ0Z)_ZS{@G(_t2ށuY<4bZG}MHI 5|Y#-LzC!e+Sy<1ϥF4 {^y,]|p ׬a Y]=KVd NJlm^=/g4B:Vl`Uٞ;36c/? w4'9yA,῵=k\y@;9mh>OI$I$I}Y=r?yO=yO==Ӌ5DUc>s0/8YםεfZ9sPSyK㟕En.鞺׹xGcDcriJ[3x _y-%ږ%;~;SU4:kC8]y.(`wl' y1hI7qT_B?s5KU, M3h:Lkל/?wmMJ[$>Co<t67ɘj^jn?ϊFq~<'&wGʂsenQdB2;*>ppfjELZG뒜|`"A.P #{r)8C9!1@NfuYCbfy}Y?&y&تƻE~5-ng -JͧP3)I$I$I/13>aLJ!Vq)P4=W=ϚكU^ɕYNs2&îgyo' X^g(X$ܖgoCy>DZRbN.p~cϐ 0Zź1#ïbu|_.*`QeQnyl&UoQ<Θ٘x~6R(U!aKdyy /2> &eTuc}[Ȋcd K*Ces⿡Z3)3/^[$I$I$)Rz{rʠ ۰0KꋥL =$OYg2i;:ʦe}S^uCCrb9hj6N#c:V{>.\sަ߁??'7JѺ-kF) § ڷ9t@,_˲F4p>~%K$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I7DȘIENDB`cliapp/man/figures/headings-3.png0000644000176200001440000001332713375762401016407 0ustar liggesusersPNG  IHDRoBJ pHYs  IDATx{e/pDA%4ЖyZ;򀹻ry`WVz;ڪfW.,smeUN]j05 )s/;Ȁ?>wfy'x*wt&f2mmk|k嗟A%IE՟eMYYY}';;Ɓ{ ѣ)ӝe^KYYYvid++*ۼЮUUUeeeoPY9hihHk떯ΫsWoS[o}:>asɆ:s]_m]d_{˳~>;)ee![E_<7TUUd͚Ymں;]d3^:-7ߝdQ9+˖3 qVc~Y+I:;;$;vx ZWyy =T\lɬYn84rjF7դ#;3n{sAeԨ1io_,]Z.yNҹCOϺb~]L9.C MuuM^~yaOryvy=]]8"ˮV4g__df2RbNy-+ՍHMM_,C cՃظS$Iyywǖ-?稣N͘1#5YlIzYx**jRY@9l؈m:uGrU?In7>wh.|̊|{$s>.:mmkr)ӟJO8sY̜y\/_o@.45sNOOw|\zDz==5jlfμ3Gko 7RN=zŽ/_N|}ȌS<zGs?s!?K%ny}XU[rq*9zWdΜs%'wwn55[=u괜uֵ?%g?]wݣɹ->'IYYy&O>&&Pr|{geeu,>'IEEef̘sι \XYYYJ^l!C;vv;wJ&Oo;̺---ik[uEҽ: r㍟lKG~c'C/5Ozbz=8SQO{̙s^x ޔ=/{ޔW }o=:Cw_ΑG#F>/hEG} mio_dݑMM{f\ٚ^k.zNUUMZZLtkֶ:ɺC (׮~ߥ47?>2f47?Yu~cwnʷD;tg쳿.ԩkuGOR;f=3q?#<-?-y{3͛ur)w}}nB{„7~U(O8y2 s8U.̴if͚?oʕ1,Y8Ir-3seGRs~ w.SW72?As ZC;ʿ [MWcE=\}}['3myI֖sfs?󙛊ϯJf<&/lo?2$1btObkvx[o8E9ԋs h˭g>ԴώNO$ &_E}nÆ /|-\҅y9= ;JggG.By\}y2i!2=hɱA}NCà~fo?G`bŲsΤ^˗ҥM;7%oC Ћ/̙f%gg'gdgs%wd+w]z08f$׮ jn (1ґNUQQ7VGGGo%㽽x==ݹ|>fͽn8ƽq׌Ҋ O=`>9o?X}81cr?j_>Ff޼s䑧&Ijkf*X/r/su7t+3?sl_}m`wGN첲~G2vvvd=޽̚u^f:/ƽ7x775jL.\t1;&$===moo+|.++Keeȏ=,]joJn'~>',[$Og'3oރyKl>֬i/jWW9V}Te}.7=ϛS^^ѣܹߊ~GwΫsEgckEs;vLȢEO%Y]]+OJ[^kw.͵"g?=G+wuufxK˒\_EE6:@߬'go|4u*r!2yS &gєf=c۩伦o=sϝ_}㪪 f|Kǧ=έ,Keeu+u_7l]z|{䪫~E{zzSڞ{'I] ҭ׿~f38:?5'?9vVU Yg]/}5YQQ˼yQr|Ԩ],tumۭY"O=di}y9%^oѢ'޾6ɺwK Z==Y<[<Џr~!E44 n{gMM}?cw>/_tԑgmUS3$uu|o+@݇dР>WjOOOw]WXr^c.5jzv]N0aj3qZWHsmU;y =im.~>B{ݽ}JYنuOOV=UUm(wvuKut-|?k@rw|+eƌY9ԋ jqwӂ)Ǖt_跐]JYYyN>cG}Rw),xW˗2Uӟ^Yg/YIMM];=K)/ɥ~߽*G45+qAaT*ZvXFSTt-W񶦦6 Zbvgo,ߴ %at+5\xw}_bi>{bS_߳ oqn6ۑ/?>ws-[U/ _ ⊏9_9LJK>_g>353jՆc~GQ29g Y|Y?aN̹?klz7t?ᆿUW!z5ko4ޖ/`,uɘmmqUOo2֜սftvD[YvUɘoUVlMww[wߞ??Z2^{{[u$>/ ]ҥ{oʵ~rr#Fqd]ǥzP::3lȴ4穧+,,v {)Y \z8>[*r'f]LWWwjk#fѢ9[i@veLVKWVnO }sI9cv ޔ^z6]HkRyNp$Y5y?~_N?IENDB`cliapp/man/figures/headings-2.png0000644000176200001440000001121213375762401016375 0ustar liggesusersPNG  IHDRoBJ pHYs  l*uG'fvJsssfٲWxsil\gQt1ӧ}?Ÿq3nL[[[[syi _egw9~?w>U:=z|rcݕ[n,Vg]RW7$I֚ں0r K1C0lnLJGr[N8s /u|N]v+?-ӧ`v[}Wg޼b+'?y=^wKc1b~Rl'=ᥗfy7;oqI c|NC5+z 88modPU5`ظVWW+**R(zXLEņ/.TW89sffΜruOgx/x?$_|&ײ`#wG|3ӳ{/aDcc$_媫kd'{G+lPޗg ^j?o3}:[̝{Eν"&}%$[[[zmṶ^鉛X,>XO@߆ds[[kMέsg;"zl ڼ&YGv㭷N]XM̀ C$Iee{|ssOd{*lNҷ2;8*Iֶ&ÇLw]ݰ9zs;s!̐!;>PIZ_ l8pH鹲2[r~8{}Hd{rYt +^$ߧvx-z˝g=wNvCƿsgd+:~ރ'?yӱY9sչG^t:ڒiMCÂ.rw>IN OȘ1sC^^Bf`^n"iOCөMSӚ$ɰa#3hаbmf}KϿ'--Min^d}ѣ?XjUcxlUuum,y)M;M<˗ڵr/RɧWnrۙoI'HeӴÆWϓOޛ> :6rU3mAYx}?873f8'~4s;/sS޽gqe~ԧ$il\~#I0z;2s훹=]6grM 0`o07|Y{16?/5לY7yi9+ }Nc>wCSo:ޏ|sΙnx)\|On%g}l)^{fB^~yagfܸvWUՀkR_?ٛO+AK0pS(O9s.|NsR{9/I $w>񺺡9O欳7/at44,ȢEv2Ғo*GhJemBdĈ]sK_|&f[o+.'LVCzm)\1crС;梋uםn>1y;?y]jjj$ RXv'scb[z*I[/=7x;#wdذxseϮ]]'<Ľ]H:ZZ[]S;%W^:Yc>wi$]5$5u7 _&Ia卹K.26S ϭ~lNP˻Z3]/Y8VgآuuCӻ*Torֶ7lz)+rUR: ~K}46.8s۝w^sȀ} ̚5sRn$텽&y;I${;Cw: IڒddEņS߭-B*d,xQv;wllh$ Nu)SdT֗_{%BUu->R'[hcm}$_{Ovkk|^bYg{"MMkJ@mQ{n`;7ԪH}}yY䖖 S Jt{;I-_xnސ͓[yX}7s淗?6|l~g &eǖS4l4hXƎݿ>C옣Xnj?84ijڒ۽^~a;vgo(zvo%Kj;+qsXe^˃-SNo>w"@ c}s媫QGBN:[9>ԽIZ^x U9e᥾w%W^u]N+BU.e͜9T;I^z,Zh{ʢq=֬YYnmX~{Y̗tQ,ےԪK/;F9sf2̘qS֗U/7dȈL2#?\qC;-DŶ`&N<13f)+۳xqCVx+BUs\׬Y/|aϬXvYN<ݩɸqGT-b1vxqgfܼ&cN;T66cy;C/w V^TV2`\sk:]vCYb=C V|;k֬Le冓Ћ38.ݍ$_E9s;|+PJPK_ɗ$^?˜w_rL򭲾<92je>-WWWw諨tͺuO4C9Y_A&O>W(Te[[SUUBZ{TCٳ/d9IV\Y7&7>a5jLٽӝ2dx )ߣ.y/ĉ'dQꫬ,%Gvhٲr3/Kof@Yf)'|AP矬M%q_O…۹--MY9`]λӱb=wŴu|ڵ+}euoSӚ\r/3lۮOSOݗU;--'[[Sĺuzme  ijZ7GGԩ3;:v9O?@.,\Xb6.W}98F-KNcn“y_w>wgĈ]3i)ijZB2KG3+W.ۢ(s\Əd֭[#FWw4]Lp|F^C^?,ZDzۡXnOzIENDB`cliapp/man/figures/inline-markup-1.png0000644000176200001440000006401513375762406017403 0ustar liggesusersPNG  IHDRoBJ pHYs   IDATxkxՀ_b"ш"jEVS/~ UbUV[V*j(Eb1@$$|?Ξ̜ۜK`ϓ'ggϞ}Z(((l޼yWˠ(={vHwEQE;JwEQEQEQEQEQEQEQ=.((((n_6rЫkZˣ(㶢((U@+(((^S??Q>峞H(ۊ(G8 |;Oi-Q hvgi-Q^"mI`\ˣ򁓁&+c/mM_ _1g01%ReoBǠ= "kxNP툽]M jn3E ։L!y)/Zg-@-C/wI}!6,dM8fF>KwQ~Ty&(f S^Rh˸kй3_}5_>UAqz ZQEQtaƀ|4bkҰ,@D`_zzuOoqRBP<}Vx ,,3U`-08$MeTOp8GQkf7i-Q1h!xc9@ϴNPD%7<4=Rr&]Nmm 9SԹZjkqlf9ŧرQ|,O63)e؋i@MC44|Ǝ$7uVEQ%53TXh\ƃ3x&8_ҿ+*=INЮb\q1šخ= =o긭((J;#qϋ3%1tJrO: IfOK).[\F'ގ)jO3ڟ/ck|>?@ql?b Uꋦ){JvWUj]c2Ბ,%ZGL8ʼnfq=͚{llܜxMEQEiO)EXR*AP\>TX]{H,n:zݍV'N3bvcgB@8Q禥DEǠ=NmF"xU(5r'w;i-Q{ _̨+Ћ a f$FRߦqn/7e5{Gq[QEQj*2>2MI-{=>=kI.6 '>=x:P?)M1s6pgjt jt7 ʞϐ 8~%[Ow2/20-;޽(dU\ͣ V2lHKΆRiL, mQ'E}SmEQEQ~ xWYw?`?D9#? >0\ 3Sټ&Wd֙y>(FƥC i3O"\WD E׈{~Ro 5n'|2P2PK~ɜ7md#@|xZg+p?d3 Tfa(s  GH] GCގ<ޏ\9u+BG m82)&isˁDmf!cЌD6"cl7dzӺc?m4 "dǡWHXLl3'A :#}zLIo3V&ͅ.)ݛWAj@45]kt@.}>E$ݦj^~m[hIc2 J%a+ֱfmd˖49d􍧾Q,_T O, 6 K(3MXj _6@nnMQ?l@DEhc}r5~UKaۡI'bHG5_6Kntq-FTv%ƻ۷4!rsEwq7MkYn=7na{Stߟ‘E}cWj'o&>n+($gB%>V@ +,&<^Dk8q.x8߶!Qxչu@?ۮE"u}D`f8oπ{WA$>3&AH{dיYOo"Ǹ%e糀"[ƠqcX s`G1(g+A6)YfV s|njNE> M چI"m6/Ts~5&b`"pG9"" ?;u+1:7(Ȇ/^D6ڍd޾'\]&Ƞ9?Tqinkf*$T֎As4ds}'2Bj@f!s">i3ngyFwQ7oNW:Ϝ=3\wmfZ̫NgFr}<6ik>fr^ܷ1[YW1ݮh R[Sk>no"7U\]+ MG܏?Dl."p80q#"hH}ffYwᯘ#u֊X\s]7d4(r#ޱBKx':˧\"|x4Fv}vE,d95]=o6&?@tx6n\gsro^g%d4.{oBq S+Aѷ/祰<\dnZ"qHt 2 mf!cД!mK ,RM{+A¿L3άyމ_h'11A P[-bSsϷ![Nʝg7(iD ڸ?6ѧ˾M,ʹgs~R0t8C-y/Osf5GqYAP5fLQ>V1emj6-sO,@匛7{%W1C Ph|!vUn$HoBݪLI P˂rőn'>8$tv6=o6܈&?9OKuȜ68;Y\yWZ 3CyzYwFގ nH;vbZg&b>ȣb%(1DD+ oh87h6v"cdb*@ .A0c6j1hB6HZFQuH6ǥ |&xǴ'~Bۍ-Ȝ'} wdTI kOmlQ4b ÇA6}wWyG Lb~E5~ݧ?eO3SX`knfԌ lF :xz0=y*ڼ Dm(׏E6})9n(NBښE?D Q:UugnewԑؽI܅XzYZ%L6t9=yD@وlKQߊ{!?B,:"mr9̶d}U(F3^@ز= y^#'CΉ``@9o'278cg#}6܃MW>A*INODdj*=qn!2^"!,t>5HP|q @fg#cך61(T r4FCuLDg-=2:`2e(9ްɏ<n|u?ojjCOˇS{Ӗ2q,ʆ8jDUWò5u /R 5{k‡8$FQSrpҐd'Nw]Ô2d9Oa%Ѫi kFp"xn ךU,BpW>6':Vqj%"t۔p+`$)x*.<.ۉ(M!i+"Z_t57AՙE%pqܓp<ح?@ԋD3SywHD:(b!u-EO6t Fk ؅o6jDQ*Hxڌ+s Ȣ 8ˑx&2o&m@mI '|qj3 Y5pgֈ6-M|&}?۩:;،X];AnFsW6> ͜%6,%sCS`tB렠K6dSSyIբČD&~b moG m}u@ ͆W(Øx,,v G }a|3 5ijs2 }ÎJTU_tQ>[iJnƙUwM2ְp>X }mQ٥ -uFdC]1c&?aW>0N>Q;|[7#aЋ~{'7nٳ,09 GM6VVùwVy챥y{9}:JoBAUTVͧtd[峕fH ,7zgיl"vDhmqcL%q7ϣQYg=g>y4"~Ī.y8nDMuf Š,ecؕJ0:Zgs!ċnoH$YuQ<e/[4Vh>MC݈!!líx+D*NĚU,vȼaku#ԊF2'n #_lZ®yQv&e(,NXZoOg jb$fMݮ7"1f-r݈u mf +ޟ½ L2e]G\[q): ] onwԮ[a1v3_1G_HnRh݄S =w{EU֊._16IBsmÍ_puhdi/64{R_̹Ɛ_<|bY}ۦ%KVy(*=}qjlp[Y39#yEc4W~DF}f3VEq(S((JSp~C@]_a3"Av;cYl{|֊׋]DF,Gc5bnm !o.20ݳ.s8x 7-LZ~bƃ.u q/HR݋~㧈4"v+w+f7}3VmkdDq!bI/|GAlAA`*[{q㿈ո*P 9 >;V}$ G8̔E+m7\;L]TCUn0ݹpy{`-/[Ç-D QOuRV PLnMkȜ)qa*߿7vc" UO2m&E.6W ÃΦmDز4E^jVfx9I>ܧ@&of|f%q$EQEQŎ#R/bބ̽0w(#[کw9oe]fx3p?bq'."~(O'9E^a$6'c.7BG_#1I纍D 4Ju-" irD$("M 1ؕb;qM&ޱ6qiш8uވ|ȼakM"'hM#N(MI6PDd+LRںGxNX@rۊFx&&dNFBrA oqeh"o7': ] lWpec=95r67UΆ 6Dѡ9aj/VޱǢųi vT$F䅎y(qzs$gJ"SGC7m\I0q#:sQ@2a KjDz(5tDb&CAlH됱5Zycm+:D˞J"fۆEm6Ku}3b}I]EL<[(s_#k~͆ hA<ؗ7q$Jm#6uP"81ƽVwHޕ2 d.,;zWe\GWְr\SHwSwb? v}_]=ۉޥCSڗT3cAX?j3H>2 u>9ѿeهꁷ'uȚ&U l͵E6d} +FPm6DqcYo/.7cwLyYgA dr;k6;ٴ5kV0n|ڟ:o.:/*RtQ0PcٟQSs(y 1 QX\N}= ^{cs`~ꕁA"ه]ijʑl꛰YKe?#u)((J Ȋ$x[T [o(aGR}6Wɓ>^c}#]Wo챪A֙Y-?#,Og@Rӂ}h/o["/t'lQbxK޽DLmA3'CHo !V7.^PA! RwZjkޤ2lBWTdx,$w(_39;hAYngYp`7 | -yP%Lw2}5r]Æ֬`'u%Cj\I]ղ8sO=ϰoo_f?|![W $Voz`͵[V;-d54xU_+YXg[~ϙ7ɬ(({(Q/&]`E /Q>›x8.#\O;m*]@;-cqEdG,,h̏!D-o^@ 88Su۰[$v# `y>.ao&SXL"f& ''S4ׄbX J ?u@.d!SWoHd Y aZN8ٌ dƦmb|N&kflR%pp\yYgA $A< =oL 72^øNs#'ט*> C(qܫ]/M\dqk,[Ⱥu rpt\+4C\Tƹ2' [o1) mlAʛI2iW"f& 'A'?ӱo2Ic.!a88 h H88i{Ӳ/U E88n!XǠFPm6렠x9xo^q,kd8Lÿn]YgA [W+4Guu6>hn2}wܴyxhvc0ӱY5Dr(>e1[Ϝ?MK`J :萨&dv#T%_f6^\\^ba wȆ Wa%^NUϙNe2؞wӦxƕVo̜i kwEQEQ`SQ-ND?{CWf ''SxcHtmfg.i;"wk{:](#^O#]JvT언JǏ"sso}LxƠFPm]G:"yN,`&z ?Ja8inpA6=F۸AY2:h]u]f׭䮟O1~އ4jl._ɔqW(JG د/r]nͤr],\먵 ̾"*o^"C?6AމZf7 K(g:۶`Sʙ$zxe6Ep}~UgR>v\0$\)\lP.m /wWνq1Bz7];*LB=Z-w"sP5'Ŀ9$s((JVJER#"L&Ab9]Z.{'{D*,>3tU5"֓#J*D;2sjo쯮حY:"BzKHK9mG=Wt*{#B[s" RWH;H0g:GˈxG26 N球m]2Yg.^ ڑ#GƇC7Q chEܗ[Lm#Iurt];qy"츦ERW#}|\.VIJZbsOvI|Զ$'ՆNE"dd5z-V};_8Q_;z ߇H]/ HT&R2^CJGn7^AY2|hX/n)*>AL|[̭td'a77,KU-z֯U45}?svq>UĦˇEе1ܲq5/>9#J9/V1o"j|h/6~Rzl,7-~=4-b"oeETeM3Ö¦C52"l]9*ggTɷI=MUoRUmaI~iɣ<}djS5sܹW Ҿjh<Ӭ{n` ̙\H €2fU=޾ +)pMɜh%%#̪hy-$0eJTEQEI%Nt.C}.@*w?4-6G2]]P"H׊n.?.@tm/R7b}0G| rTNtD3zK-,#.B粱 Qg`owG!BM>-VvT&؎QT9G1V$a+ngi#^B ڕK4sFy,GYUYgH{ơl"oz=vW址鲐U<[}k|79qVG^^Opo^nM%U}3&ݢ x16!mqwd}1/~MAAA,v 4kq(v 3pfvEg,wdL{a]5P]*TrDs\=TZװhNqܰ[gfm͵ΩwU1,T͑ER}EC4 KcKyE*cQUx)]yܰQP˛3p?Fgx%XRlt}CJ+{NDjX4%ECW|t}G3}&YZ`Ęb-IZTv-%WaZjj̥li#I=q!XC5s۸oh++{mɔنtEQE1Nw}`:2=8cm݊g^JgwnV+Ci/!b|>Bv?o_ WmE,~߫;n'㝈K$+&2i:ߛ@b&E/gV7MoHκ`D\)H@-V$qt؄(RͣH*"ǽL31ЈXzN<}c-H}=:J/˩xq"kgα |f?G~̛A ڬD2x3-V7u,}Pe6t-ؿx|)ҟ$rIt^ȯHu`ODyl!y̋nC,MfoG6TL#1$T֎A3CI#\dzȺ;tWu.v^Q\?bDe!]~?SGy3|:pg)cL'8(.{c 51<;Al.~Q9Q5s@yzq :B7y`HmT>QAiq_H2:}!wڞݍ>~؂锍h YOq9mH؋TL_R_4oC*xkBƔOeֽ9{gMvWEQeC 9O%dz>Ȣ)f+,TЍ K>zkD dF J뇸 |&X' _ ikĪtLe*bD0 e1BG!ud@,D{[#lB#L' `no:dP*cg ɞ73mA6ROÀ Ȇe&(,8'>}ˑGcQax]|jd>hR$6.3:?ADC96jaZ4DXdvq2VvBkH8h ΂~Gfټy@c=>a/ز=.۩1" 0@Qů.tiNNa$971tZYWi-+VbKnw7ma{B<5ldcRrY>INgncbWV0$]2i[wְtWHӖt^HFO7/X=G.4ѕrvy귰y3Uz$7Vj–& Cٟ7{d(쁴E ]Q=lDxyqِQZJ'7#QySQ2 D"[Z*$D{#+)1aoq,*Jm'Άݻ2K+P< ԯѓʦ2kⰔCF\5 xa Oj hmQ((bE(JmcU>휁XzaYYS(($!\Y>baUpFM% [Ex.O^ KU.6\Ɇz=΃F3Ϡ}SQEQ%P(Ɖ`H5U{AN~i8$]/$>3c>~2*(({EWSRhU+SsRq3Kz[vTUU*8]c (kT'M,s_=͈ܟ UѾ((tLwEQ|qI: d Ȧ??^EQEQ% eңcx8r3^pY%hhjlM[\3FQ7EQEQ2(ʞπE@+ЌTh$=d&9=7((푮vƮM! !r(l}LB((Ji `p,b(Q%ɴJw!8 CoAۀOPLCME\*]H_1KQEQ)YjK-klK# /FѨQ((,:((($͛7JwEQгgO*((((((((((((((((((((((((((((((((i74W8$~/ƐFxWxJlB = ?|gOfZ<2/EQt ^G;||"suю((((Jh|tZ} X(yEK=XEQƾw+H7 {CsN=<4q0܀b92 >e^DEAr;Cn'xQuYKD,ؿ/t"=ORAPkvMEQEQEQEٻ0Y@w7G+B3 vEQֿ۷Bs=7Zv:[_IYDbyq\Xl tnymLQ›~+K{!:ەv1ֶfl/OFw+((($XEa\Q%CxnM6|W"''CȎBV,Fj`<٘{{ yJ}  a(LE' aeҡeHffHY9}nE5`mioN&p90d8M_CVY K҅E\-CsOo>x|BB QӠS>tk3X_AXcȜ2w>GFrK:#、@9{wcnDq pM&`9jI&)^= M/ 9p0pu&>]կӳ`x!GCV] &Zg= pPufxXR `u]ð:1ȅDk,~GHyr;OqXŸ}eGeL%q; ;y|ב"pxVEQEQEQ@8yO`(v)Ghy,v+<[7[<~7qI}(hcd̊PE&smBQ}:\7!/`*"KD \1$,vXoQ 5pnUq?»<7A!~1]N(ߍB7~}}<5ye4xHy&bWjӌ(XcaOz,W " \ 3!K9gA+ O VӖH[j G\nl aIIBg.8g`ً}%(ȹ 5Rqڷϸ%zkv<͟wG+~9~ڲ*/>S~;`՛ +#/wZ>qlPӵf'`=s'DŽn:h;} : js#!ٟ*jul?F@@SF?Ģ<$5ka//G?.^\nԼ M_7a34qN߯|$| ֯p]QϟqԙއσG c{/k>ڏ94FuȂkwJ}Xmk ,}꿀qg1ȋ8luŮVx5~zO~gN>&!\o g7.=gA;]#FijiwaEQEQEQE X\p_Wv;q f&tpmƻ ~./{c? ZGz*H[k^)GikYirI;ٖ74y݌BU6x|6,eIGA6 Ʊqscu$&V]B.l3=yٝ2~F.]8~L VC\*nHwOsvOoXny9h> z)[\~;ݝ&3v4u]=LE"m-^{`y3*݆(-1=ƥl?ƾsל3DM%d؜ưQ1pA s9z 7;* pދZDyl+ÿ'փDo/nj@vks]T^+ b3`Sk9qptAmO۫gl{]g A&cg|A +(((JJsqbĊd`k"Tsp%ߌ>;a !Q-V$]>u9]#&刅Z$ ,6#V_ՎtwsWYIrĢ?C]YXu܂(g,WB:lY]b[y| ZOIA8-;gg|pqb,<`+O4o=*|dg3< 6m:|C"ǫ2K[btN{b ;џx0[9Itco"睡_!ԝ;]iNq% .ypg<>%e0-\oz߂oCE szvG?[[`ui+K t'QTgK_n{ +c4KCX&xck\f{ac!dtҊXyEFϨkn=GAz#}g Dqy b"Pn9ߗ;r.\ 8v]s^8FI` F":kmWٕ$&DݣԺAO15y!:+1zW+ 1n<0n'ro kk{]ڦX1n$'Š(((^]KH}6b:1_챗- -7#BVD!X$r=O-P"DP37^̀a@" 7|37AH8-Qf] BoXjB:챵S` ywr?^C'Z[Sg{hXq%K'éKI1{r#e'q}!j׹gYш{Or2hNq_H<\+T<X%:5Qg۷BMǗ_Wᔐ}C`͊3>cbOu4Ypmp%|Lv6Kٝݪލ+x3A +Ɂ2dAwaEQEQEQEI X\l[F"zЉiYXe~qtw sZ?˰EoΣ; YIXB !( &aS86GQe`e`TVYa k NY$twzU{Z^UW:9uNWnw޽}w'JZ)6S-h^Zt-7"uIx^ <{-_MjդA&kiFM@|do)pի)ԣNR= K$ITBpwwdwfހσ 'R]{s%T:I8G aU.ZG%gIG Qo !sM?˖z}d'V 0y ?[!#`+-ե0T =rux9YA|³E 0꫈uwn_nQ8{ pB;{s(CFDK$bP5s A+l5 v>ȫ?{0\s:< a."˩UZ;h<Մ]O78`#BVS`r= E]/,P’$I$Eܽ5xyl[eTR:0D+FB1i}l !T>Ugu {Y_-$7I⡲7Aq 08;ubN6=pH >[psbzjnᄩpHNOHyuumO:_Ԕg]aAC`hCBgGY2f>hT$ o@^x$I$IGts,nMSVwhysne%y;xT7z8ptWE%/`_VOs <i<3;%yGK]睰DgŞGUv{3;{ʌJ2- !gd+ʼO+ddP@;:)&S$g \Y&N:0o}Rh=dE#Mޣڽ+l pɎFy5tM8ȋkV;?\+YWdaf,HԽ`s6^~4v;ՆўyVq{&+I$IRգ3&"ۥs7VҘ~;=!Kَ6vIZ l7VtN!k+gl*,)*x? 5~D;-o"=`2`LyOq0\8*U6mv7\LDsX ڸxgaV&5ڹQ{V: _{6nWXY^mŴ] unRY'n4B?n)[|>HG̐0q6|VA>hMS YTK+¯~#TZo,ɳ/s)0r{hYAGfpk u 8}WQ}f>Gx7bQYM$Ih GX`mF:ywFERiMӁǀ/W1iP'>΋\X\dtn,ʬۧ6W~3,)I;!kB% w \8j93a0z\nKK4ɴV;iS-#^[u;- ǯg޿\C;0 ߡ0WS|;5^ttF:wn7uӹ68x zY0Q5B:}X8\={[W)<7N){){pˌ*Mo,IH=lv^&uvsn·4~gA.\x XkLwiܾ$.r;XY8Y/,I$IR"*[2̈́ e2; #t*qNqətG%YJ,&^Ⱥ #>?9anraк Ǿqȍz[cr$aD$ +}xWzΒtwKK @GIMb~u|\gk vt2\ cIT7+tJG;ߚX7] {ɻmK[a0y- :_> s;ht7Q= o@MIah"_/6Fw~EȺ^@qhru[ [ [ Yلz)ٿAVPxY/gK9mVqiǰ[p)xQ*8?ruڅ=>&9J9c'I3`d땣O,~lD`2C5CEuN 9 8x'sO֍W 6KNJ0~zlܵ5G`hp2 Rnw7NìJ-|kOU0|ǒ.ӀS |.{o`haI$Ij߁Ԉ7|Ch䞔]x2,0LU}d::!*?ts1746_?#vEw.&Ep{3w?Yd8r  aZ/:}OIo>UqtG׷&ٶ0Wx 56|`rd]0!rXv.rW1GppP #BB`"wJ  #’a^?95yOK+ٴgҚ ! txjv)~Iu͠D\R4|')>ªyu^~JhORx$[=7't?k#tS軄Gv)]u/*F:eσSt/ d=IDATNʭK{Ƿ[ mBٽ #YKk[NNM2ϊ=.Yo W6#˔-ޠDY[jJ{'gñ[ØH],ϲTPnzQ8oM.,ЁS%Jpb_$I$?!Cא"BC%yИ~{d݇]`ۄ?tFj| >«TމQYwg%}݄ug>F)p&adm%=rC;M|$D:zG% ]|I*#(KIPye|7w_|;$*& ]Urpܟ R,0ZdEGC{.D>߅>>7bt7K8fj3} ^y?m'1DσjjJ;):#*beiK %"zGW!%>:N^a}ArHYv8,s9\ڒs ֓[/3+==]Ze4't! ]-Pn'zy-9>\ ]W+i냤|FOpM_G9%I$I5i)IͶ >7oaDV1Ms27r_qnLh\F !%)*?+nMPyV=v^H$Iԏ%5糒6#˝u#IHVzBx|IJZ >ӷ̳g @$I~w@1ӀoWB=GSq7G3+I}3i핤:X{j1Ϫg%I$I1;Kf'e,^=씷|%/vD$5 $I$In.-n"70"鵷瞷@*iŜ 7ϣ7=l(H]2--s*::~? Br}+~33 jᆏǗ<ֿŮؼ;v9 |[>vg?{:qbjftpIhjj=|J&=6عP,\tJf O@WCWm Jc'<_/F8R1"RqMdg^^*_G84b\.GVueغuo45*Jx=q}U֔mnn- ^0#؀^XnY-xcɒb#6nf^}wDDuŝw^ӵ?2bpMm_}&-6""[M|{[^`ZxTlsVWć>tswoyǏwG)^}WD䧪T`zـPμJz:D])r3ȥR1~qxb׮Gʿf^˗T ^$v*O}tәs b;jīKZ6~4EqbKauqѲlٵ<'WǾ}T 5k>WJRRW j%ZYg5,9%W+:If,9%W+:If,ZɬVYM2Kڙ}ۛj3}-S+h|ssk*97b6s_jթS'b5144Cͦ" /j ~zoj%ZYg5,9%W+:If,9%W+:If,ZɬVYM2Ky?8ULG[_\|C;}}* ǧNZm63 qm@wwotw{矝.:Yd̒je$d{#9%'3HNf瘹߀uuu㡡yzN^&3n qcckY R pѳ}Re{odzf͍+~͙L6nٹ|o[ko_K&W(p1}aT*M 7,g2ٸ|Uq{^ֿ◿IwKؾ?ʕ7Ɩ-OoĦMOTT/pQIMw3¦M7gް;'>qMR/E:-e2ַ:~2'xhj5cQ(t: 裛?~tk5ne燆 qXK˜ؾ3ZZF>ztv>--m7嗯\._>o߿xӄk.jԠ|]KJcs-j1G>_F 鉼l_چ?hZS笿h_M<F{r]\CWpG6rTw&(#ts}Q_*bx~U|4У9zHH<ߘ.^dcժ[⪫>t:sd &QNe- IENDB`cliapp/man/figures/lists-1.png0000644000176200001440000002036513375762447015773 0ustar liggesusersPNG  IHDR pHYs   IDATx}ew]wnUQy"@H$D0MhH@qDl[vӆ02ӽƱgMtCzFqu۽mOȌ6NKie!hH+ϘUJU}Ծ9nZk:>U}&g̹vn=7VTWwUVΫn~zp{?[gWTVP`oU}ww~sv'VqV]ޞ]ٜ9iWƿzN\=9~hv7;@vTCpC5UwyUWuXyiXr|U?YoRg_iqwo)׮ۿ2 ՛{}`6>1;:1@uĘppLVԪasq?>Q)zT;XSZL0&zf@:j7e̿s&ƚ vɇǪTnCL{S;5*{mQW/h~ɛf& ohſ:cWOc[8+ 3gZ\]co-a6VЗ>8g@Ì鵜1/_z:j:zp&g59x^|iFZ6o|B}[7UaywY AZ`ֆarpwafUݦgv>|Fu{Glp~6=`WXlj޽En}SМϪ0:[WnӳNyK[֟WۢZcW]^v]}A n{n~zBuaE `afn9g;~oYl;`i ONzE5:.]Qվ7VhX҅u=: O:Z}~[by Zݲ>WzVuz,=F̩TLѳz:zZ)_kg5]Ұgՙ d?nNܦZ@sGOU:xfuٌKգ#MT qtX&j*W8:_zgU6:?PݹMNϮ/V/-S}k-շ7OKF4̌^W6@k'CpƢﮞT}a)EXn4T=zZuvuVC_, ^VB;8 -UWU8n^O־ꎎˍmo. .7+L~ptUOxT?\]ҰYwUwO v;vlΘCXomXXݶsկ|{QUTOάWo~o5έzNjOP;7Pkh3\@uSuj2.iDw,пS:Y+kN>ax4@Bv:|bِz='ͨ :ҰZگ[%wƳ&x!]l۫gV/}5ջ?2qꫣ?T=ໆe:ag쩞0;vs/zFU hcf̀~ĸULfFw b_RZoXϕЇG<\gaWQVi@sk&ƽoƸs{Qkx A9iu `uB;ڸHcϬ>={O Z]8>V$ l=w4c?Q}blg\{zǗ>zju{I 3Wutoyz޸α@oWhu`ΖZ[yCg4̊y==W9"g{K?--wkC;G''3k >j,_=I@o [G߽Ŵ-XZd|Ӱ ƿwpg^wV5[ţn^v͕չ͞}8>jt~ą5,TSҢ8MV콭ՑMԻˆYMSy'Q=jG>mX{E^_4;|_={3 !>y:,ַ_4K =q\.c͸vVF_>1:?J809Ϫ.LbOR>U=KT߯wT^%ojﰯ.QgOu]k' B}r~zH_*cvկT~ut~:XwU3mշ7]ձM_nXb{Kwm} YO{M)c?R\CwػicN);\}OLY.}a30|T}2 }roѦm 3WVٳ?VW_q){<s}oE7!>z{ujw>V]6n_uG{q4?v̅t^uq@ rMӃׯV̸tTvT?U=ꢅu9h`V蛪WUϩ?zO臫v-wNَ[Ζ@ ƮV?MZ=mgK$]{s[Ǹk6U߼mm/}eW<~bL Q˫+_0-s+k8a>\ xf:>\a ;Y{ 3o@m`!(܍k'{9ui_gsu&g@N95o.S뫯ie_lM{?_7 YnCΆjs3j஧ơ[Uk2^I3k}d]2?Uu~:I{NE4I>԰sSFcT=qY 4]=wWhX6_Q 6ך4%₩a gv2ڇ'?2;^qEU߿.iXv{C !WC TeWT߉QhQ nǷzIWl+[\ի&N%/[5j4@ Z2˧Z@Zj{7wnƸ[ۉ{.oei;gԻfbYj}+ ᆀ{܇B̚v:qf8P=kamK\ct߃ Hrc٭Ro@^4֙էGcΝyn-E7p9аgOU_];TWZq^þ+>2W:4Z>8ڃ'zyZhl6, ,۰3~R՝;)jKkˉ󳷩4+˦rhU\Wx ju2z{V}OKnbqoC୬5ͭ ,8{X\laq8%w?n?bA&{= uպn/.[ovC6yl KpKh_Ñ5ƟC:ٳ'[״s3grЗ4Y|px-4,qkp|?V֚Qs?zD/}b̩sEf2p@}'RGOUr!X_̆媧YnڦZY]0޿Xgr2>='i_7%V`Cp٪4}'7Pc;]e_:m~x֞ꃣYȜnmʌ_X1-b??vn4qv'45ϷVj9ѹ 9]=|uCRՋbr˪x{u㋫W#%}ձ㕋mE7 KE5q1:Xmcwεs奄zwu[.Z|uaot1+6]uV)o/立Von3v'V]i]V{YkqϾY+ܸ]3pѵ77nF[b[]v7v󴽑˥m?:ˉn`XzGVt.,?%7putt>^{{kG[G߸ߚ2w휎Ǫmq|aP~kH7MϽ!_wONCTvrU;궉g~o)ΜRʎ+k'щ3Ui =ՇF_7PY^}'߯.X:gLnǪ˦\WݾvszRCCòi [_U}l9eUIDAT6yɊIENDB`cliapp/man/figures/alerts-1.png0000644000176200001440000000721313375762441016116 0ustar liggesusersPNG  IHDRJ+JJ pHYs  =IDATximgY=e"E) T+P*A DLj"*($c8D?qƩ A#bT&"c)նi{o~x>3߶_rZ]z} y:X..WǫVZ~paݥP]U۪/ܷS[ƴ^+n#1FRꏫwpg6ZU4G߯޺bL_}MuIUoΩ>cc'N=^CKG#8mW>zJy-HwLe75mﭼccM^Y}cTzl/LO~\u} V?r=緿iv]yOj{%኱=~1*Rzh%_ѩ?N8#ҷK=Q}l^1n$۫pFn6Ϯ.kzr'SCߺAkL|]fQ)uVc~]}kN{ނ+ZMzT}=n =)ky5/k{Z=T[oVai縤zjw{ycE.mvLHįv^ ͎tS?jvВɥG擧%69&o$9z;uI-sM ~AK.[yQ-Nvϟ ?\}6c܊V{/?ګ1=Fz'6;h>n&e: =<}݂6k,.o6a}T_Ǫor6^7\,I\ӮlfƳonC}N}|?_ Wklo@WU8R0|{'Џu>1wuҹ=f'*7֊^_V}jWFխ+-6}]uPlկ(ڿmg4k$_}n5f+@?mAc՟7*Vov^Kmu7^;ufT |Om\l\~OveSp/s.U>^'#mF{Yv^WۤkWod ͝Z4겹c74Mc+ڽ{+jlijp'sFꅓ^wQe_[=kף彫/i4g-97͍WM[\y7`,ӞTׯA/p>46;h[ͮ|mFn;ZQZi-O@/OѨ=okL}ƲyL\+ `6o2FyL>{AS ku6unPl;jWUGZ>w=秓_46l?qPp0z~$Ykj>˖mɹ˚MBȤ\0SV?ukky* ۪OX{3j:~'VfkQ=skHcƩ{pT6)VkwSmvju6矱ɽ֝٨}ӱQuIkInpߪϮo-iU_ݷgSOzO[;u|Ϳoh+Fv۫]ẽ/v^Y=?ΏU? _߉??(wn{UonԄL@W삸V[ /z7V>2}y.'M'JozY:wM{;$-՟VxV;#->blvFyᵍqSu. vZ~՗޷žiA? 荪MlTn-ƵJt2}; ;5!v}W.w'm7.gl#]mUeInn߻n vkBo lٵg_Il_PynXGx7;nrUW^Ш:_VF=V't_xӵ'Z\l_oi+W?ˏ8:vqE}WG[gc5WHWO}_uƳzRF2ƻMb91m[9<`?~}Ύ>(IENDB`cliapp/man/figures/alerts-5.png0000644000176200001440000001612113375762441016120 0ustar liggesusersPNG  IHDRJ+JJ pHYs  IDATx{%U}/r@" K|%Hc3FhtbFPƐ5!#8F D^ }ޞ?~[UιW?kպΩڵkU{$I$I$I$I$I$I$I$I$I$I$I$I$I$I$Ikǁm5fӆ LGܗuc)6X S`Q˭nu"p?ppp֜o Wgy>~˹ hyy]׳-9-T$I$I:C: |xO}W+>v /OZ:V;&wXƈkg ^ \N|]}﹭[=画|ƈ! p՟5|k1ArZ꿩$I$I$tЧ toDz^`V`:iNvַAjs_nr׍n&KD/֕};._oSL^/DCYlIF-J$I$I1|p[;G IzSsmIz?wQκLq8Ysk2;G}8R?|Ucbԃ׳ ~SI$I$Ibi~d}7A o"~="1Y<ZX&;:LuI" L#Yq")̗[o*I$I$i ZWٺ8o~Sa[G33b I#9C&9J$I$IZbb1~4n 7fq*zD`''>IS6<41wVu^ܻUN'w 78n.ÔY݀J<|5jDnniz88-D{.uўSnZ$cz.{QOv{}*mL&i 17Đw &<VFՕC"wi1*~=D~ >@r֍?^7$_O-m]V{X1$$I$I& }\q99qW\'PH7<ȋms͓]^AspgMZyϩ/Û<]/黅\ܐ x\{ !rj4wW@JSަa=]&U&(ιZ]58)gZ9FYkOފ \Cf=dFMaPs- D!3kIh+_[Ki |<[Cڟ }fNC׶Ҟ[:ǟ&oLgtX֕Dt&͙N+0iP͐0iYN_O} 8E^~"8u3DZcZ37C$pq+q 䔳=b*7M|vw6+u#,W{"dg?M<Sq>UC{/9߅;keo%FZ$I$I4Rs^ײRwgbn[ߛ?MsrHyQXwW!{]Pf(!> !Tm.ɾ+.=lQf]ݞwSJyvgy^"p6MDCZ u V?ׇ)G8bT׍: kd-U9Yt>ϿX~z7vޟ 䔫= 5n ő,WQ5oc9Y7r^r*O?w[71c*S?(+u=%I$I$e*ϗ { H_xc8]SoXVu7Sו:gR:)vY)?N>+qa3M}ZEϢX?屫ݦn*57ܿV|} mo*\(ׇiAG>o>VmZ7i3fn/ prg=5=R~>AQrQ/X_qGVκyg9S(u~)5۝O>-I$I$[ɜGf?$r6PׯK^OSč2y=ivCc79Mˀl{>!R_p;/J>[MoiWdS)hn T\{)ga"W68Fӈ`|םT?0 |8a֗Q׃6PSbH蹘004 r^{J )/1w(@N=^Oggri0ٞ۳]ǀ߮f1w#G/I$I$ik>79s߬eGexUVfS_G1hp>A+Ӟsw˥bbq/`놆*F .DOO{b$:u5oud۩Nm|Yfw2X|==k[ {A}IL w\v{w;T޾ ;trs}`$?}m ڞ=|on@U{R{K3׫[[}$I$IԱ#؋س; $<ݼ7Gx{giK5Lbm쾎^/ w zELS}Qi*3 sP=_e=6xBb=k{&1z.[!x 8wUPO4BW|x 1C;mLǞ/=圶`TS 9TI=A-CcQ5I$I$iڑyId>\N194o'"p=ƒ׏<we7˛cQ#=V7?@ u7kE憞y$gJA&Q^]~o׎̞z͝ex) ~D;]ּo=7÷4` ba{& 䔣=}CЛSwY7Rg=A޺\H<0NԻ3ߒl--I$I$)1~k1ÇyW(C=Ch,-h\塨wvn>ݛށ)l|Dj:w4CvBL[ r>Wk8ַ)>@mҜ&=F ?J i03D}^%@V0*S]gWi4Eks!aFI9iur^=b}bWS?Ň$I$ISw*di43viLN{ATӜmd6%^Q y$ǁ3=thi/$y)pUg}^>ymF2"]\Ui5hXZ AAKޛW3&Ӏ[BiOUԟ[gPbaL+gh#l!urkZS>= !I$I$)7e[ԭz{6S p$n# 7|)T>i@z-A?,W 5f Q+}7ߦ0LYfoT8p(KDl8!zힼމ?X-&h6.h|z&YRh9lO+׫b pZMR HLPu#N+g݀׳؞ oݨwP>I}N=? ;I$I$I&8q- ˗s:`[\b7b}Vs%w 3D~>X jO9)n3EuO+JеcKDv{ܝxeMZ9sc UN$wn9lO甶bpv_6Ml 1OnmTo; !q L+gY9S)oxo ݨwPҺ2~$I$Iko站$\\}Mw7nxchұ|- 6(YX_CMn0Ay/_~R5'L}b0]LU59ˬ`ހH'q&KTYN \I롚s+`'vPN5i\ЫrO{eznt >"߉!yK5M|6oH)m9c7]Gu`-y&ʶ|{: p=:n6STh~8ie/xV+xm+_GVκs*s @n9Fyi;(WZ'T췉j$I$I*0^ќ)| B7ӛ6V=nnN3uG0?9j>O)}^wSуnزn*5TXnߜ?L2z0Ks6tV%}fض~j|moف٦e3DGqU2-\ցk9nOH#}p-]J+WY9S5i4n#Kծ%I$I$-"/`$I$I$Bg@b7&D0lbۇLh"h @d:Ǽ.W`s@O_7d^D/;`0s9$ݏEK.1D@nQ&_"B#>!8wrٞB#9Wub(\u#g/4u{@YI~2$I$I$I$IZs|_ّ$I$I$I$-E+pMSH$I$Is*K$IKˈ!| অȔ$I$I$I$ii9].\$I$I$I$IKpS /I$I$iܒ$IZNygI_?[|I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$)xIENDB`cliapp/man/figures/alerts-2.png0000644000176200001440000001665213375762441016126 0ustar liggesusersPNG  IHDRJ+JJ pHYs  \IDATxl7L0 !i &)uېr06xK[Pn^셆D&R6 beMNQ)FSQYThiݰM !&Sènj3x~x/|gyOH$iByI$I$IlOv$I$I$I$I %I$I$I$IeaZ$I$I$IT& 7χu0<{e8 =ݸ8cm:Kbú]8Tj]68RoWBqؽff = kwL 5?oǐ$I$I$}jj[W]_ y*|Y4=qaf=ԍ/qf7d3kf#ZDlb0/Aq?Pd}!I$I$I @7774¬!{K5WClkҚWj1UJd7kp='u$I$I$Ic45k|C]2"#6/]m?e6EJwA3IWFvI$I$I4aS -E}`?BG`BXz39tv6GRe1w^nmI$I$I%N??3_UcyӇa?MʷmÔʧFJ<$I$I$I@'50XtziU~q:k=?@a1G9}l5\iK=E6lxCe2 K8|x =z9E۶ X:-m|1 ;mh@䕭o 1̴y礳%_4 ~$l)v"u @Oo¢t >^ C9_*mW <$I$I$i:)|>'6fUK#Sv+~hiX  .Ib |t%On#0/ӮĢ[+#1۞m+7o?p? rZHcp7$,lGȶ>xp96// K_ ܷ} B]߅yr?k0zvXcqޣa5vGGt&66UAh C#ljG(B7\?·]IXVhŏwW ÖҾ#|>?w?4;J<vÂL^>:Z @){z@[oAx,]$I$IΧyI3@ Uqh|O^(ASpIvf+Ì=5MGT|hVonX^ (P7 ?X9;c2)/ >@]#|g?/,1]IՅC渕>UW}߆gFl(=T,(;g+|hCJ Bܶ ?z̾n}={7ϐ,D\ZyH$I$Iv>,m#*:7:'v;&M ‰$?y r|d$xݍy?ˆ!y<ݶ+aUd^~KEȮ̥!@MvVc~C4009~S@C 8ѓ^4oaúI< G1rJim??@(7*gm@AA3Z#pwNu`0p7N=pͅMca"(<5y˟Kkt@a&$J8 HNi8#7_u[dps <>vT`4ce%V,וg6Y{P})aAAaѢJkD]xb;g`wxٗ#r;p4\^pKz+`nïf9| ~}rl1Y-7i9:Él7sQz1 u d]X~V}&>+uuu.`e_ghQwy: \.̀%` orzwВ9^}a^ h&1"REFUbhx1Ol/4@d|"f->$I$I$i NKE>_xJٵ va'`0ct_ñ( )xG]wDZC(5HuehCSːfTcۦE,فOS,}O SQ.Dv MJӹ_umvݼ˳S}Tg7i"ZTo mʹxձg/fW',&C@zv;܎uCbә9zT6##myJM3E_P$;kV$I$I45eSpW/~^P,^_|NJIv-^pT;WG2,Z#5't%՗w 8E?BCˬ놑r+\$%^?'6 dp?پQfzU  M־ i9LX⫟ MAGGw@Vp]S~*V?qu`0<3ƨr}#.v+,1~H$I$Iu$\R|*KaGGBGtB['ڜ6c9p/d}||2 +ޤsFU8U = il7- #^U}l(jރ9ȼ`?píB  al0@^7gt+6.Xk}Zf5$I$I4Mu5_ݫne ovDK[<ϯl~6j4~Q0<:sE`_d`dOȱ[}(tP. T8\I>/(\.6g3@$I$Ih{퉃жv}y=}tr-,I`n\`TL0S_ZWKn x'\~ J}?Cf}Km@F2f}/o+uOV~VN>[)#T9-@0uU#gz|,7Uet<hK=3SptˮYCH3W]=//O6uM`ƆZ~H$I$Is>9'mAjWlaaύVx}p?-ʿ_.w(~Jnu-.o%c"v#o*}D/s۴mJSPߐlz8iko&ŒYvW2Ji,{Y0+p@%g g$I$I$M1{[2AhyĎ6؝ zUkhhl][aEY?K /~pkKKwX#;|\I=Vش*lH#s,.UkK1Čp7gy#(~ˣ78]QO7HP7kn/{$I$I4ńsTw *آ`i,7 K^lyF l`Nsx5.)s|:aVv5¡/@MlF LE99e+}pRJeuֿÝya'gF hX DNpߨam bLL)ze88Wü`x:yh?+Trk^M}'3z{a)3x,\ayvA)S.ߟA|qC:Aν/fFg~VBC4$"ENGFWBFfG8g3GRiwj I$I$ISūL XYԔ'[W_ǦYCK 84;htzhnѹ'Ex۾A}=C] .5ne\6g_Ǡ!R̮\:6ΣŲ9]pz07O_ OjϖS-߃ʩif] R{Aec;FCSEσ`ڛEҜONz#ˆ9~ UiG(d DhW5 $I$I[#<$ Yxێ6xp 篓[r"x;0dHhZpԳ-T-r㼘/GqgQg)s-p;_l^2c>a6$I$I4a&Rhea28 OAW %07Pq~^I=6p\YXa I$I$I`Z c0w^oqH޿uH4^}T3@$I$I&+^nشҭ4{Lv+4>$I$I$i @Ktzn> u1e"o OCgr[*z/T*]>vi|H$I$IR9w4ٍ$IyI$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I,C GIENDB`cliapp/man/figures/alerts-4.png0000644000176200001440000002046713375762441016127 0ustar liggesusersPNG  IHDRJ+JJ pHYs   IDATx{$uyoTA+Q h9&FИGh4D=GGMQU@EEAeݙ:vuO_gg˯k~USopio\U/XMkVm{λ8O H 6qa_L=x>~s$I$I$IQ9S6VVl#޽Ǟ{~{n;bry>Jdl2uw6O]3EI$I$I$I⪬{.Z̝vsؗvZCC[ PTbvdrbΜP$I$I$I$Il,_۬7 =KGNox[-I$I$I$I9WZ]Z|B~.eȲ H!+Q*C>w_\b V\͆ XlQ[yPn\-݀k:|?< K\'RZbj<֜nNq;pqcS$I$IҒQT*{+cLM$Sd?gیÚemdAg)WTwgE_҇\ XYi(m΢ZLv~Fo|8N_N_t;(ކt-#>|` p~*#_[:|?l"&'Aew&(cS$I$IDD%2X3 $l~{M۹͌Kz#K!ɠT\i%q~s5.1F/^sFB XD[jU`5X[g!SGlG?>C'r>EYkS7{n o[_{}xpmUˉk$I$IP%+g$Iʖ*P+=3k8GQ`gMrcc%(@iJ\x9:FpaS,8J',rU+:-|uڲTx\yF)bm$׭v2m/\ ^C'|?leG >9ZzK6-pFը^%I$I$m*YT]MlX%eu9դJ>B I,Xb kVi{2A~06JPOgD&hJAy |-فۀϡm3j | \TibȈSAmQq`4 /k9;tM$I$IdiF&f9*_p;-\7@J9Yf rsq=o p41^:YtPYWyFa3vs(wAZ0p9fKKk[>Q%`-Ác{muDYig$I$IҔ4Wm 2,k~v;3 4c\"M *IPÃr$t!2j%če N:AdqؑFZ;&m17A{*u| hM1׿ ֻٖ2aE)x"#u_eo]Eq<~"3zO!GcG)i>sh'eWtXॣKtD9p1uBgxjF}ר.]y1i{+{}M$I$IVR%RzFKd%,/QQMRDM33IF v%dقTR>F4g'7 (m ٙs8(]_^ |x;.8F\8e[Lj`!Kd.w˲vάZ6vX |(y.kna8zCskPj/}%plOyuNdotcMilb\GۊE ߼Q*?I\o#_Gs&7iz^ j%,pq<:P"ͽ#AxW^T$I$I$-% Y>aBFz^B"qulNK"݂TEۜw"+L"81~r]J<Q^ݕ=oS]Nu \?iרnׁ"ulO10EM$I$IPI*I$YiXel"؃f5PVտ!V)YW;I~z/"V=Ɓ:&" yϷ#P C}C~ Qyl3N&D[6 O̥}im߲ =EdCtߴ,OuXW|1p@i}&"~_0әp.x S&2sGݺh;-ߧՃ qK|Då<6S. O>Q}ƀO7Y_}c9( ^NBE?\{=\\P 4s+a}!n#0y<:P"ֱ~Ki~`^ܲ0EM$I$IPVFrY jÚs6iF$YJ%w ա}2ߔFzyopޜ>([D\kh "Xeɫlc~B,;YLȤۉ8׳ |duB8CLݱ6(lgP˘]J_MFdn>~zz_xUZ)눀L^}2>FI"`}lmz3"x>6'R J{Ɖ!ꙩ1ϊKYa;PJtU#q}b|u>=E)OiTQ86:>쇫 _ѧM\lXI$I$IZʐ i+eZ3YRdIB 5]&2Ƚ^,"?`v[G y@榗YV i2~ez1=\ȿ|:/0 얛A ,~C.]{8tc}$ٞ^Is\}lm~ J3D|P677(}\% \=bef[Q5!뉠yn֍5c?}xAi?vaM$I$IVe)Ye^d YvE u$iM4g|-~`u7 3nMDsb>ΙA\V1}oX^/Oe@1N~bv&R$;'ާtc~H#_ =1NtV[>` #7dow v"6u3!"Rs:fQDgۼ& װ.@" S׺ŸF}lgi>7?eZ m$I$I*$ U{iɳ$!M~҄$j o| q~$h/B^R^MA}mmܼ qS`vDcTLRg5t#a||Xl{(}g}WSh#G(Q^6i{ Ww.σ9FNe[ "RIpͥ]?#_;oDF4q;x q J4J#/k0a<$2-Qn$I$IPI$e$+K!YU>*C)0~gۈqi%o ,|#vtO76cyjn\va;Ix}٫Ӻ|_T?"AƸ3D8A'1n'sƱ9|woRtX*N~[Oh^׋"%4xxkzY툱5R |1qj EI$I$I!4Ȳ_Y Y$}#%#^J"[.#2v$%;7*}ZgfےM(qi]\xcayJsq;bNzҊg݀m`Sk;[f:fLQP )1 4?$QtX u?}u[7gq}X%:" :}˽e)\ql B#}Fm$I$IFL%K3$%/)$Y1$2ܽBz\IB m c1kX{S}[nfk*,N&Pkӷѭ]I#y8ȖƉ\~.0uE8Kˀ?}9o<J<(Q?[qN%8xp837_zR{MdۉL2:[õn~P>bL i<0},s&I$I$iU2ҜMJȤNҌtxq'{Czs@X=TfvP1qrZ{=ufmiot/g~["[#퉇:R,M oSKU&fĿmO=߱ezXcY^I "f"hb|]vFO30v9Xt>OvV}bw -iN&e=8CCc4?\pRbx%[}EEYyfm!,O$I$IFI4K,%MߛAnFnLOW$0zt8c@?L'u D\ q;ٖ]4g=ܒ)~ S9:Y4guɿ ,A:"UOEoi3o uU5ە{GN{Xx*DzSn[{{u!MY>k]e;3ȾpQ&杉߹e ^8ĹgE>?KkwE4_%ƇsШ*̏'=M +j6 zMf}n-H$I$Iqdc 謯pѕ/|Ϲu\u$Y,Mz7q`/9w|0tϰ+gv.iC3pOn?-JcOl3+:|I~`((uZ73|/7= ü0XOFܖaS}z~vpH]k~طci6˜C~},S>k=.1b\^"Bi !N^O9MD~x Gcs8s?ia(4ulv˦~&Ϡ6ǵ$I$IBe4Y4߯_ί~s7m}-&I!$,'goX67=,nN>NidV\ކ |xN'ڴ.1;8Dz@`>ZhMG*}.QXev 4x1rݑr=l*xu rۻ=]oqimKi[xKegS4O_EFUfU3aӀ31sMv$I$I$meSIdf4ֲUJWʌWʔ^.ͪTl|߳7n^K3Cslx~s"p}!zоL?XؽxnYDV?/%T,xMۇXqg}^W&C[jZGcv^G;'45w5EN#v]BogМ=Qn~1^Od_-q"Xں@lD}h{UB`⸺W/h+D{|~+> ڼ^N8F<3b\뉿ŇZ xssШ*VAv? 2V|n$I$IL%+=ls*V Lujj󕛦ן_KXcAםFfbjs='Th;A}9^uڿP/Z>oZ\q <*Snzg:gbx`g}CXȧ@sU{uw"hxLuw-[n>'ӁÈ vgF+/%;'E}d Pu/VDZ3Y{Ej@)qհǰ.Zb͛g>[e2~ |n$I$ILy]lzƍW%Շ i:C:3y Lo/=ާ@n*иy\\")[Dp.;8[M_n$Zvh";n:>^[R"۩]hX%\LEdmj34\S8g=+ "p9^u1aWm)?.˽Os4C?}XOF]}n(]>|<|bFnru).us.{ @ =滱6+h_b>I?3BJd<Pt>sPssQԱy&J67q]o|>aS^s$I$I!gꨉUO8TۡTfJWVʲl:Ku5ӛ6||"ֽƀe,SD"#lPڕ(g{\&'2!=K6"7uzov^Fd@F8(-%E<ql^;v747<8gL|)Q^[͖9cs 8g}ں㡯Qn$I$IQ: g2͞x֬rL<~h<]4ze Ҵe^u]$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$IIDAT$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I$I&oj&IENDB`cliapp/man/cli_alert.Rd0000644000176200001440000000245413375603045014535 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_alert} \alias{cli_alert} \alias{cli_alert_success} \alias{cli_alert_danger} \alias{cli_alert_warning} \alias{cli_alert_info} \title{CLI alerts} \usage{ cli_alert(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) cli_alert_success(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) cli_alert_danger(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) cli_alert_warning(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) cli_alert_info(text, id = NULL, class = NULL, wrap = FALSE, .envir = parent.frame()) } \arguments{ \item{text}{Text of the alert.} \item{id}{Id of the alert element. Can be used in themes.} \item{class}{Class of the alert element. Can be used in themes.} \item{wrap}{Whether to auto-wrap the text of the alert.} \item{.envir}{Environment to evaluate the glue expressions in.} } \description{ Alerts are typically short status messages. } \examples{ cli_alert("Cannot lock package library.") cli_alert_success("Package {pkg cliapp} installed successfully.") cli_alert_danger("Could not download {pkg cliapp}.") cli_alert_warning("Internet seems to be unreacheable.") cli_alert_info("Downloaded 1.45MiB of data") } cliapp/man/cliapp.Rd0000644000176200001440000000233213375603045014042 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/package.R \docType{package} \name{cliapp} \alias{cliapp} \alias{cliapp-package} \title{Create Rich Command Line Applications} \description{ Create rich command line applications, with colors, headings, lists, alerts, progress bars, etc. It uses CSS for theming. } \details{ See \link{themes} for theming, \link{containers} for container elements, \link{inline-markup} for more about command substitution and inline markup. See also the various CLI elements: \itemize{ \item Text elements: \code{\link[=cli_text]{cli_text()}}, \code{\link[=cli_verbatim]{cli_verbatim()}}, \code{\link[=cli_h1]{cli_h1()}}. \item Containers: \code{\link[=cli_div]{cli_div()}}, \code{\link[=cli_par]{cli_par()}}, \code{\link[=cli_end]{cli_end()}}. \item Lists: \code{\link[=cli_ul]{cli_ul()}}, \code{\link[=cli_ol]{cli_ol()}}, \code{\link[=cli_dl]{cli_dl()}}, \code{\link[=cli_it]{cli_it()}}. \item Alerts: \code{\link[=cli_alert]{cli_alert()}}. \item Progress bars: \code{\link[=cli_progress_bar]{cli_progress_bar()}}. } } \seealso{ Useful links: \itemize{ \item \url{https://github.com/r-lib/cliapp#readme} \item Report bugs at \url{https://github.com/r-lib/cliapp/issues} } } cliapp/man/cli_ol.Rd0000644000176200001440000000310513375603045014032 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_ol} \alias{cli_ol} \title{Ordered CLI list} \usage{ cli_ol(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{items}{If not \code{NULL}, then a character vector. Each element of the vector will be one list item, and the list container will be closed by default (see the \code{.close} argument).} \item{id}{Id of the list container. Can be used for closing it with \code{\link[=cli_end]{cli_end()}} or in themes. If \code{NULL}, then an id is generated and retuned invisibly.} \item{class}{Class of the list container. Can be used in themes.} \item{.close}{Whether to close the list container if the \code{items} were specified. If \code{FALSE} then new items can be added to the list.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ An ordered list is a container, see \link{containers}. } \examples{ ## Specifying the items at the beginning cli_ol(c("one", "two", "three")) ## Adding items one by one cli_ol() cli_it("one") cli_it("two") cli_it("three") cli_end() ## Nested lists cli_div(theme = list(ol = list("margin-left" = 2))) cli_ul() cli_it("one") cli_ol(c("foo", "bar", "foobar")) cli_it("two") cli_end() cli_end() } cliapp/man/cli_it.Rd0000644000176200001440000000234113375603045014035 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_it} \alias{cli_it} \title{CLI list item(s)} \usage{ cli_it(items = NULL, id = NULL, class = NULL, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{items}{Character vector of items, or \code{NULL}.} \item{id}{Id of the new container. Can be used for closing it with \code{\link[=cli_end]{cli_end()}} or in themes. If \code{NULL}, then an id is generated and retuned invisibly.} \item{class}{Class of the item container. Can be used in themes.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ A list item is a container, see \link{containers}. } \examples{ ## Adding items one by one cli_ul() cli_it("one") cli_it("two") cli_it("three") cli_end() ## Complex item, added gradually. cli_ul() cli_it() cli_verbatim("Beginning of the {emph first} item") cli_text("Still the first item") cli_end() cli_it("Second item") cli_end() } cliapp/man/cli_par.Rd0000644000176200001440000000157613375603045014214 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_par} \alias{cli_par} \title{CLI paragraph} \usage{ cli_par(id = NULL, class = NULL, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{id}{Element id, a string. If \code{NULL}, then a new id is generated and returned.} \item{class}{Class name, sting. Can be used in themes.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ See \link{containers}. } \examples{ id <- cli_par() cli_text("First paragraph") cli_end(id) id <- cli_par() cli_text("Second paragraph") cli_end(id) } cliapp/man/console_width.Rd0000644000176200001440000000067113375603045015437 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/width.R \name{console_width} \alias{console_width} \title{Determine the width of the console} \usage{ console_width() } \value{ Integer scalar, the console with, in number of characters. } \description{ It uses the \code{RSTUDIO_CONSOLE_WIDTH} environment variable, if set. Otherwise it uses the \code{width} option. If this is not set either, then 80 is used. } cliapp/man/containers.Rd0000644000176200001440000000225413375744611014747 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{containers} \alias{containers} \title{CLI containers} \description{ Container elements may contain other elements. Currently the following commands create container elements: \code{\link[=cli_div]{cli_div()}}, \code{\link[=cli_par]{cli_par()}}, the list elements: \code{\link[=cli_ul]{cli_ul()}}, \code{\link[=cli_ol]{cli_ol()}}, \code{\link[=cli_dl]{cli_dl()}}, and list items are containers as well: \code{\link[=cli_it]{cli_it()}}. } \details{ Container elements need to be closed with \code{\link[=cli_end]{cli_end()}}. For convenience, they are have an \code{.auto_close} argument, which allows automatically closing a container element, when the function that created it terminates (either regularly, or with an error). } \examples{ ## div with custom theme d <- cli_div(theme = list(h1 = list(color = "blue", "font-weight" = "bold"))) cli_h1("Custom title") cli_end(d) ## Close automatically div <- function() { cli_div(class = "tmp", theme = list(.tmp = list(color = "yellow"))) cli_text("This is yellow") } div() cli_text("This is not yellow any more") } cliapp/man/cli_div.Rd0000644000176200001440000000247613375744611014221 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_div} \alias{cli_div} \title{Generic CLI container} \usage{ cli_div(id = NULL, class = NULL, theme = NULL, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{id}{Element id, a string. If \code{NULL}, then a new id is generated and returned.} \item{class}{Class name, sting. Can be used in themes.} \item{theme}{A custom theme for the container. See \link{themes}.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ See \link{containers}. A \code{cli_div} container is special, because it may add new themes, that are valid within the container. } \examples{ ## div with custom theme d <- cli_div(theme = list(h1 = list(color = "blue", "font-weight" = "bold"))) cli_h1("Custom title") cli_end(d) ## Close automatically div <- function() { cli_div(class = "tmp", theme = list(.tmp = list(color = "yellow"))) cli_text("This is yellow") } div() cli_text("This is not yellow any more") } cliapp/man/start_app.Rd0000644000176200001440000000242713375747070014603 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/package.R \name{start_app} \alias{start_app} \alias{stop_app} \alias{default_app} \title{Start, stop, query the default cli application} \usage{ start_app(theme = getOption("cli.theme"), output = c("message", "stdout"), .auto_close = TRUE, .envir = parent.frame()) stop_app(app = NULL) default_app() } \arguments{ \item{theme}{Theme to use, passed to the \link{cliapp} initializer.} \item{output}{How to print the output, passed to \link{cliapp} initializer.} \item{.auto_close}{Whether to stop the app, when the calling frame is destroyed.} \item{.envir}{The environment to use, instead of the calling frame, to trigger the stop of the app.} \item{app}{App to stop. If \code{NULL}, the current default app is stopped. Otherwise we find the supplied app in the app stack, and remote it, together with all the apps above it.} } \value{ \code{start_app} returns the new app, \code{default_app} returns the default app. \code{stop_app} does not return anything. } \description{ \code{start_app} creates an app, and places it on the top of the app stack. } \details{ \code{stop_app} removes the top app, or multiple apps from the app stack. \code{default_app} returns the default app, the one on the top of the stack. } cliapp/man/cli_ul.Rd0000644000176200001440000000313413375603045014042 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_ul} \alias{cli_ul} \title{Unordered CLI list} \usage{ cli_ul(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{items}{If not \code{NULL}, then a character vector. Each element of the vector will be one list item, and the list container will be closed by default (see the \code{.close} argument).} \item{id}{Id of the list container. Can be used for closing it with \code{\link[=cli_end]{cli_end()}} or in themes. If \code{NULL}, then an id is generated and retuned invisibly.} \item{class}{Class of the list container. Can be used in themes.} \item{.close}{Whether to close the list container if the \code{items} were specified. If \code{FALSE} then new items can be added to the list.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ An unordered list is a container, see \link{containers}. } \examples{ ## Specifying the items at the beginning cli_ul(c("one", "two", "three")) ## Adding items one by one cli_ul() cli_it("one") cli_it("two") cli_it("three") cli_end() ## Complex item, added gradually. cli_ul() cli_it() cli_verbatim("Beginning of the {emph first} item") cli_text("Still the first item") cli_end() cli_it("Second item") cli_end() } cliapp/man/simple_theme.Rd0000644000176200001440000000364113375752204015253 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/simple-theme.R \name{simple_theme} \alias{simple_theme} \title{A simple CLI theme} \usage{ simple_theme(dark = "auto") } \arguments{ \item{dark}{Whether the theme should be optiomized for a dark background. If \code{"auto"}, then cliapp will try to detect this. Detection usually works in recent RStudio versions, and in iTerm on macOS, but not on other platforms.} } \description{ Note that this is in addition to the builtin theme. To use this theme, you can set it as the \code{cli.theme} option: } \details{ \preformatted{options(cli.theme = cliapp::simple_theme()) } and then CLI apps started after this will use it as the default theme. You can also use it temporarily, in a div element:\preformatted{cli_div(theme = cliapp::simple_theme()) } } \examples{ cli_div(theme = cliapp::simple_theme()) cli_h1("Header 1") cli_h2("Header 2") cli_h3("Header 3") cli_alert_danger("Danger alert") cli_alert_warning("Warning alert") cli_alert_info("Info alert") cli_alert_success("Success alert") cli_alert("Alert for starting a process or computation", class = "alert-start") cli_text("Packages and versions: {pkg cliapp} {version 1.0.0}.") cli_text("Time intervals: {timestamp 3.4s}") cli_text("{emph Emphasis} and {strong strong emphasis}") cli_text("This is a piece of code: {code sum(x) / length(x)}") cli_text("Function names: {fun cliapp::simple_theme} and {arg arguments}.") cli_text("Files: {file /usr/bin/env}") cli_text("URLs: {url https://r-project.org}") cli_h2("Longer code chunk") cli_par(class = "r-code") cli_verbatim( '# window functions are useful for grouped mutates', 'mtcars \%>\%', ' group_by(cyl) \%>\%', ' mutate(rank = min_rank(desc(mpg)))') cli_end() cli_h2("Even longer code chunk") cli_par(class = "r-code") cli_verbatim(format(ls)) cli_end() cli_end() } \seealso{ \link{themes}, \code{\link[=builtin_theme]{builtin_theme()}}. } cliapp/man/cli_text.Rd0000644000176200001440000000174113375603045014410 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_text} \alias{cli_text} \title{CLI text} \usage{ cli_text(..., .envir = parent.frame()) } \arguments{ \item{...}{The text to show, in character vectors. They will be concatenated into a single string. Newlines are \emph{not} preserved.} \item{.envir}{Environment to evaluate the glue expressions in.} } \description{ It is wrapped to the screen width automatically. It may contain inline markup. (See \link{inline-markup}.) } \examples{ cli_text("Hello world!") cli_text(packageDescription("cliapp")$Description) ## Arguments are concatenated cli_text("this", "that") ## Command substitution greeting <- "Hello" subject <- "world" cli_text("{greeting} {subject}!") ## Inline theming cli_text("The {fun cli_text} function in the {pkg cliapp} package") ## Use within container elements ul <- cli_ul() cli_it() cli_text("{emph First} item") cli_it() cli_text("{emph Second} item") cli_end(ul) } cliapp/man/cli_dl.Rd0000644000176200001440000000257213375603045014026 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_dl} \alias{cli_dl} \title{Definition list} \usage{ cli_dl(items = NULL, id = NULL, class = NULL, .close = TRUE, .auto_close = TRUE, .envir = parent.frame()) } \arguments{ \item{items}{Named character vector, or \code{NULL}. If not \code{NULL}, they are used as list items.} \item{id}{Id of the list container. Can be used for closing it with \code{\link[=cli_end]{cli_end()}} or in themes. If \code{NULL}, then an id is generated and retuned invisibly.} \item{class}{Class of the list container. Can be used in themes.} \item{.close}{Whether to close the list container if the \code{items} were specified. If \code{FALSE} then new items can be added to the list.} \item{.auto_close}{Whether to close the container, when the calling function finishes (or \code{.envir} is removed, if specified).} \item{.envir}{Environment to evaluate the glue expressions in. It is also used to auto-close the container if \code{.auto_close} is \code{TRUE}.} } \value{ The id of the new container element, invisibly. } \description{ A definition list is a container, see \link{containers}. } \examples{ ## Specifying the items at the beginning cli_dl(c(foo = "one", bar = "two", baz = "three")) ## Adding items one by one cli_dl() cli_it(c(foo = "one")) cli_it(c(bar = "two")) cli_it(c(baz = "three")) cli_end() } cliapp/man/cli_progress_bar.Rd0000644000176200001440000000127613375603045016117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_progress_bar} \alias{cli_progress_bar} \title{CLI progress bar} \usage{ cli_progress_bar(...) } \arguments{ \item{...}{All arguments are passed to the constuctor of the \link[progress:progress_bar]{progress::progress_bar} class.} } \value{ A remote progress bar object that can be used the same way as \link[progress:progress_bar]{progress::progress_bar}, see examples below. } \description{ A progress bar using the progress package } \examples{ { p <- cli_progress_bar(total = 10) cli_alert_info("Starting computation") for (i in 1:10) { p$tick(); Sys.sleep(0.2) } cli_alert_success("Done") } } cliapp/man/builtin_theme.Rd0000644000176200001440000000062413375752204015426 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/themes.R \name{builtin_theme} \alias{builtin_theme} \title{The built-in CLI theme} \usage{ builtin_theme() } \value{ A named list, a CLI theme. } \description{ This theme is always active, and it is at the bottom of the theme stack. See \link{themes}. } \seealso{ \link{themes}, \code{\link[=simple_theme]{simple_theme()}}. } cliapp/man/inline-markup.Rd0000644000176200001440000000533213375603045015350 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{inline-markup} \alias{inline-markup} \title{CLI inline markup} \description{ CLI inline markup } \section{Command substitution}{ All text emitted by cliapp supports glue interpolation. Expressions enclosed by braces will be evaluated as R code. See \code{\link[glue:glue]{glue::glue()}} for details. In addition to regular glue interpolation, cliapp can also add classes to parts of the text, and these classes can be used in themes. For example\preformatted{cli_text("This is {emph important}.") } adds a class to the "important" word, class "emph". Note that in this cases the string within the braces is not a valid R expression. If you want to mix classes with interpolation, add another pair of braces:\preformatted{adjective <- "great" cli_text("This is {emph {adjective}}.") } An inline class will always create a \code{span} element internally. So in themes, you can use the \code{span.emph} CSS selector to change how inline text is emphasized:\preformatted{cli_div(theme = list(span.emph = list(color = "red"))) adjective <- "nice and red" cli_text("This is {emph {adjective}}.") } } \section{Classes}{ The default theme defines the following inline classes: \itemize{ \item \code{emph} for emphasized text. \item \code{strong} for strong importance. \item \code{code} for a piece of code. \item \code{pkg} for a package name. \item \code{fun} for a function name. \item \code{arg} for a function argument. \item \code{key} for a keyboard key. \item \code{file} for a file name. \item \code{path} for a path (essentially the same as \code{file}). \item \code{email} for an email address. \item \code{url} for a URL. \item \code{var} for a variable name. \item \code{envvar} for the name of an environment variable. } See examples below. You can simply add new classes by defining them in the theme, and then using them, see the example below. } \examples{ ## Some inline markup examples cli_ul() cli_it("{emph Emphasized} text") cli_it("{strong Strong} importance") cli_it("A piece of code: {code sum(a) / length(a)}") cli_it("A package name: {pkg cliapp}") cli_it("A function name: {fun cli_text}") cli_it("A function argument: {arg text}") cli_it("A keyboard key: press {key ENTER}") cli_it("A file name: {file /usr/bin/env}") cli_it("An email address: {email bugs.bunny@acme.com}") cli_it("A URL: {url https://acme.com}") cli_it("A variable name: {var mtcars}") cli_it("An environment variable: {envvar R_LIBS}") cli_end() ## Adding a new class cli_div(theme = list( span.myclass = list(color = "lightgrey"), "span.myclass::before" = list(content = "["), "span.myclass::after" = list(content = "]"))) cli_text("This is {myclass in brackets}.") cli_end() } cliapp/man/themes.Rd0000644000176200001440000000640213375751674014075 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/docs.R \name{themes} \alias{themes} \title{CLI themes} \description{ CLI elements can be styled via a CSS-like language of selectors and properties. Note that while most of the CSS3 language is supported, a lot visual properties cannot be implemented on a terminal, so these will be ignored. } \section{Adding themes}{ The style of an element is calculated from themes from four sources. These form a stack, and the styles on the top of the stack take precedence, over styles in the bottom. \enumerate{ \item The cliapp package has a builtin theme. This is always active. See \code{\link[=builtin_theme]{builtin_theme()}}. \item When an app object is created via \code{\link[=start_app]{start_app()}}, the caller can specify a theme, that is added to theme stack. If no theme is specified for \code{\link[=start_app]{start_app()}}, the content of the \code{cli.theme} option is used. Removed when the corresponding app stops. \item The user may speficy a theme in the \code{cli.user_theme} option. This is added to the stack \emph{after} the app's theme (step 2.), so it can override its settings. Removed when the app that added it stops. \item Themes specified explicitly in \code{\link[=cli_div]{cli_div()}} elements. These are removed from the theme stack, when the corresponding \code{\link[=cli_div]{cli_div()}} elements are closed. } } \section{Writing themes}{ A theme is a named list of lists. The name of each entry is a CSS selector. Most features of CSS selectors are supported here:, for a complete reference, see the selectr package. The content of a theme list entry is another named list, where the names are CSS properties, e.g. \code{color}, or \code{font-weight} or \code{margin-left}, and the list entries themselves define the values of the properties. See \code{\link[=builtin_theme]{builtin_theme()}} and \code{\link[=simple_theme]{simple_theme()}} for examples. } \section{CSS pseudo elements}{ Currently only the \code{::before} and \code{::after} pseudo elements are supported. } \section{Formatter callbacks}{ For flexibility, themes may also define formatter functions, with property name \code{fmt}. These will be called once the other styles are applied to an element. They are only called on elements that produce output, i.e. \emph{not} on container elements. } \section{Supported properties}{ Right now only a limited set of properties are supported. These include left, right, top and bottom margins, background and foreground colors, bold and italic fonts, underlined text. The \code{content} property is supported to insert text via \code{::before} and \code{::after} selectors. More properties might be adder later. Please see the example themes and the source code for now for the details. } \section{Examples}{ Color of headers, that are only active in paragraphs with an 'output' class:\preformatted{list( "par.output h1" = list("background-color" = "red", color = "#e0e0e0"), "par.output h2" = list("background-color" = "orange", color = "#e0e0e0"), "par.output h3" = list("background-color" = "blue", color = "#e0e0e0") ) } Create a custom alert type:\preformatted{list( ".alert-start::before" = list(content = symbol$play), ".alert-stop::before" = list(content = symbol$stop) ) } } cliapp/man/cli_h1.Rd0000644000176200001440000000141313375603045013730 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_h1} \alias{cli_h1} \alias{cli_h2} \alias{cli_h3} \title{CLI headers} \usage{ cli_h1(text, id = NULL, class = NULL, .envir = parent.frame()) cli_h2(text, id = NULL, class = NULL, .envir = parent.frame()) cli_h3(text, id = NULL, class = NULL, .envir = parent.frame()) } \arguments{ \item{text}{Text of the header. It can contain inline markup.} \item{id}{Id of the header element, string. It can be used in themes.} \item{class}{Class of the header element, string. It can be used in themes.} \item{.envir}{Environment to evaluate the glue expressions in.} } \description{ CLI headers } \examples{ cli_h1("Main title") cli_h2("Subtitle") cli_text("And some regular text....") } cliapp/man/cli_end.Rd0000644000176200001440000000070513375603045014171 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/client.R \name{cli_end} \alias{cli_end} \title{Close a CLI container} \usage{ cli_end(id = NULL) } \arguments{ \item{id}{Id of the container to close. If missing, the current container is closed, if any.} } \description{ Close a CLI container } \examples{ ## If id is omitted cli_par() cli_text("First paragraph") cli_end() cli_par() cli_text("Second paragraph") cli_end() } cliapp/LICENSE0000644000176200001440000000005413346163137012535 0ustar liggesusersYEAR: 2018 COPYRIGHT HOLDER: Gábor Csárdi