Nothing
thin <- make_cran_thinner()
test_that("help accepts symbol and string topics", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
expect_error(capture.output(engine$eval_text("(help mean)", env = env)), NA)
expect_error(capture.output(engine$eval_text("(help \"mean\")", env = env)), NA)
})
test_that("help shows Arl special-form docs", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help if)", env = env))
expect_true(any(grepl("Topic: if", output)))
expect_true(any(grepl("Usage: (if test", output, fixed = TRUE)))
expect_true(any(grepl("^Examples:", output)))
})
test_that("help shows Arl stdlib docs via attributes", {
thin()
engine <- make_engine()
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help funcall)", env = env))
expect_true(any(grepl("\\(funcall fn args\\)", output)))
})
test_that("help shows builtin load docs via attributes", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help load)", env = env))
expect_true(any(grepl("Topic: load", output)))
expect_true(any(grepl("Usage: (load path env = NULL)", output, fixed = TRUE)))
expect_true(any(grepl("Defaults to the current environment.", output, fixed = TRUE)))
})
test_that("help shows Arl macro docs from stdlib files", {
thin()
engine <- make_engine()
env <- engine$get_env()
import_stdlib_modules(engine, c("control"))
output <- capture.output(engine$eval_text("(help when)", env = env))
expect_true(any(grepl("Topic: when", output)))
expect_true(any(grepl("\\(when test \\. body\\)", output)))
})
test_that("help shows usage for lambda without docstring", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
engine$eval_text("(define add (lambda (x y) (+ x y)))", env = env)
output <- capture.output(engine$eval_text("(help add)", env = env))
expect_true(any(grepl("Usage: \\(add x y\\)", output)))
})
# Initialization tests
test_that("HelpSystem initialization requires Env and MacroExpander", {
thin()
env <- new.env()
arl_env <- arl:::Env$new(env)
# Need both arl_env and macro_expander
expect_true(inherits(arl_env, "ArlEnv"))
# Create full engine to get macro_expander
engine <- make_engine(load_prelude = FALSE)
expect_true(inherits(engine_field(engine, "help_system"), "ArlHelpSystem"))
})
test_that("HelpSystem builds special forms help on init", {
thin()
engine <- make_engine(load_prelude = FALSE)
help_sys <- engine_field(engine, "help_system")
# Should have help for all special forms
specials_help <- environment(help_sys$help_in_env)$private$specials_help
expect_true("if" %in% names(specials_help))
expect_true("lambda" %in% names(specials_help))
expect_true("define" %in% names(specials_help))
expect_true("quote" %in% names(specials_help))
})
# Help lookup chain tests
test_that("help shows all special forms", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Test a few key special forms
specials <- c("quote", "if", "lambda", "define", "set!", "begin", "module", "import")
for (special in specials) {
output <- capture.output(engine$eval_text(sprintf("(help %s)", special), env = env))
expect_true(any(grepl(paste0("Topic: ", special), output)),
info = sprintf("Help for %s should show topic", special))
}
})
test_that("help shows macro usage", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Define a macro without inline docstring (inline docstrings no longer detected)
engine$eval_text("(defmacro test-macro (x y) (list x y))", env = env)
output <- capture.output(engine$eval_text("(help test-macro)", env = env))
expect_true(any(grepl("Topic: test-macro", output)))
expect_true(any(grepl("\\(test-macro x y\\)", output)))
})
test_that("help shows R function signatures", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# R function with formals
env$test_fn <- function(x, y = 10) x + y
output <- capture.output(engine$eval_text("(help test_fn)", env = env))
expect_true(any(grepl("Usage:", output)))
expect_true(any(grepl("test_fn", output)))
})
test_that("help handles functions without formals", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Primitive functions have no formals
env$primitive_fn <- base::`+`
output <- capture.output(engine$eval_text("(help primitive_fn)", env = env))
# Should show topic even if usage is minimal
expect_true(any(grepl("Topic: primitive_fn", output)))
})
test_that("help shows arl_doc attribute on functions", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Function with arl_doc
env$documented <- function(x) x * 2
attr(env$documented, "arl_doc") <- list(
description = "Double the input value.",
usage = "(documented value)"
)
output <- capture.output(engine$eval_text("(help documented)", env = env))
expect_true(any(grepl("Double the input value", output)))
expect_true(any(grepl("\\(documented value\\)", output)))
})
test_that("help shows structured R docs for non-Arl topics", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help \"c\")", env = env))
expect_true(any(grepl("Topic: c", output)))
expect_true(any(grepl("^Usage:", output)))
expect_true(any(grepl("^Description:", output)))
})
test_that("help supports package-qualified R help", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help \"writeLines\" :package \"base\")", env = env))
expect_true(any(grepl("Topic: writeLines", output)))
expect_true(any(grepl("R package: base", output)))
expect_true(any(grepl("^Description:", output)))
})
test_that("help package-qualified form validates keyword syntax", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
expect_error(
engine$eval_text("(help \"writeLines\" :pkg \"base\")", env = env),
"unused argument"
)
})
test_that("help prints explicit message for unknown topics", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
expect_message(
engine$eval_text("(help \"nonexistent_topic_arl_foo\")", env = env),
"No help found for topic: nonexistent_topic_arl_foo"
)
})
test_that("help notes other package matches when available", {
thin()
candidates <- c("lag", "filter", "time", "plot", "window")
counts <- vapply(candidates, function(topic) {
length(suppressWarnings(utils::help(topic, help_type = "text", try.all.packages = TRUE)))
}, integer(1))
topic <- candidates[which(counts > 1)[1]]
if (is.na(topic) || !nzchar(topic)) {
skip("No multi-package help topic available in this R library set")
}
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text(sprintf("(help \"%s\")", topic), env = env))
expect_true(any(grepl("Also found in packages:", output)))
})
test_that("help R fallback is robust to user bindings named like base helpers", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
engine$eval_text("(define capture.output 123)", env = env)
engine$eval_text("(define tail 456)", env = env)
output <- capture.output(engine$eval_text("(help \"sum\")", env = env))
expect_true(any(grepl("Topic: sum", output)))
expect_true(any(grepl("^Description:", output)))
})
test_that("help package argument accepts symbol package names", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
output <- capture.output(engine$eval_text("(help \"sum\" :package base)", env = env))
expect_true(any(grepl("Topic: sum", output)))
expect_true(any(grepl("R package: base", output)))
})
test_that("help R doc rendering does not emit warnings", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
warning_count <- 0L
output <- withCallingHandlers(
capture.output(engine$eval_text("(help \"sum\")", env = env)),
warning = function(w) {
warning_count <<- warning_count + 1L
invokeRestart("muffleWarning")
}
)
expect_true(any(grepl("Topic: sum", output)))
expect_equal(warning_count, 0L)
})
test_that("help prioritizes specials over macros", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Try to define a macro with same name as special (won't override special help)
# 'quote' is a special form
output <- capture.output(engine$eval_text("(help quote)", env = env))
# Should show special form help
expect_true(any(grepl("Return expr without evaluat", output)))
})
test_that("help handles arl_closure with param_specs", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Lambda creates arl_closure
engine$eval_text("(define adder (lambda (x y) (+ x y)))", env = env)
output <- capture.output(engine$eval_text("(help adder)", env = env))
expect_true(any(grepl("\\(adder x y\\)", output)))
})
test_that("help handles arl_closure with defaults", {
thin()
engine <- make_engine()
env <- engine$get_env()
# Lambda with default argument
engine$eval_text("(define greet (lambda ((name \"World\")) (string-append \"Hello, \" name)))", env = env)
output <- capture.output(engine$eval_text("(help greet)", env = env))
# Should show default in usage
expect_true(any(grepl("greet", output)))
})
test_that("help handles arl_closure with rest params", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
# Lambda with rest parameter
engine$eval_text("(define variadic (lambda (x . rest) x))", env = env)
output <- capture.output(engine$eval_text("(help variadic)", env = env))
# Should show rest param in usage
expect_true(any(grepl("variadic", output)))
expect_true(any(grepl("\\.", output)))
})
# Usage generation tests
test_that("usage_from_closure handles empty params", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
engine$eval_text("(define no_args (lambda () 42))", env = env)
output <- capture.output(engine$eval_text("(help no_args)", env = env))
expect_true(any(grepl("\\(no_args\\)", output)))
})
test_that("usage_from_formals formats R function signatures", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
env$complex_fn <- function(a, b = 1, c = NULL, ...) a + b
output <- capture.output(engine$eval_text("(help complex_fn)", env = env))
expect_true(any(grepl("complex_fn", output)))
expect_true(any(grepl("Usage:", output)))
})
test_that("usage_from_macro shows macro parameters", {
thin()
engine <- make_engine(load_prelude = FALSE)
env <- engine$get_env()
engine$eval_text("(defmacro my-macro (x y z) (list x y z))", env = env)
output <- capture.output(engine$eval_text("(help my-macro)", env = env))
expect_true(any(grepl("\\(my-macro x y z\\)", output)))
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.