| Title: | Tools for Tracing, Shiny Routing, and JavaScript Dependencies |
|---|---|
| Description: | Provides utility tools designed to homogenize development patterns across projects. This includes specialized tracing utilities, mechanisms for generating unique identifiers, JavaScript dependency management, targeting unique input from multiple HTML tags within Shiny apps and more. |
| Authors: | Philippe Peret [aut, cre, cph] (ORCID: <https://orcid.org/0009-0003-9666-7490>) |
| Maintainer: | Philippe Peret <[email protected]> |
| License: | GPL (>= 3) |
| Version: | 0.9.10 |
| Built: | 2026-10-08 16:58:41 UTC |
| Source: | https://github.com/thekangaroofactory/ktools |
Wrapper function around shiny::actionLink() to produce multiple action links with unique ids but same target input.
action_link( id, pattern = "action_link", label = "", icon = NULL, target, value = "this.id", namespace = NULL, event = TRUE, as_character = FALSE, ... )action_link( id, pattern = "action_link", label = "", icon = NULL, target, value = "this.id", namespace = NULL, event = TRUE, as_character = FALSE, ... )
id |
a vector or list of ids. |
pattern |
the pattern to generate the actionLink ids. |
label |
the label of the link. |
icon |
an optional icon (passed to |
target |
the name of the target input. |
value |
an optional value to pass to the target input. |
namespace |
an option character string, for the id of the module. |
event |
a logical if shiny should treat the click as an event. |
as_character |
a logical if the shiny.tag should be returned or a character value. |
... |
Named attributes to pass to the shiny::actionLink() function. |
The actionLink inputId will be computed based on namespace, pattern and id
so that it should be unique across different module instances.
All produced actionLinks will target the same input entry with different values. By default, it will send the id of the link, which could be used a character string to decode.
This behavior can be tuned to send a list (see onclick_event()).
When value is a list, the id will be added to that list so that one can detect
what link was clicked.
When the target input belongs to a shiny module server, the id of the module
server instance should be passed to namespace.
a list or a vector of length 1.
onclick_event(), shiny::actionLink()
## Not run: # basic use case (single actionLink): action_link(id = "foo", label = "click", target = "on_click") # Send tag id to the target input: # input$on_click will get "action_link_1", "action_link_2", "action_link_3" action_link(id = c(1,2,3), label = "click", target = "on_click", value = NULL) # Send specific pattern to the target input: # input$on_click will get "do_this_1", "do_this_2" or "do_this_3" action_link(id = c(1,2,3), label = "click", target = "on_click", pattern = "do_this") # Send specific value to the target input: # input$on_click will get "do_this" no matter what link is clicked action_link(id = c(1,2,3), label = "click", target = "on_click", value = "do_this") # Send a list of values to the target input: # input$on_click will get list(a = 1, id = 1) after clicking on the first link action_link(id = c(1,2,3), label = "click", target = "on_click", value = list(a = 1)) # Use with Shiny module: action_link(id = c(1,2,3), label = "click", target = "on_click", pattern = "do_this", namespace = "module_id") ## End(Not run)## Not run: # basic use case (single actionLink): action_link(id = "foo", label = "click", target = "on_click") # Send tag id to the target input: # input$on_click will get "action_link_1", "action_link_2", "action_link_3" action_link(id = c(1,2,3), label = "click", target = "on_click", value = NULL) # Send specific pattern to the target input: # input$on_click will get "do_this_1", "do_this_2" or "do_this_3" action_link(id = c(1,2,3), label = "click", target = "on_click", pattern = "do_this") # Send specific value to the target input: # input$on_click will get "do_this" no matter what link is clicked action_link(id = c(1,2,3), label = "click", target = "on_click", value = "do_this") # Send a list of values to the target input: # input$on_click will get list(a = 1, id = 1) after clicking on the first link action_link(id = c(1,2,3), label = "click", target = "on_click", value = list(a = 1)) # Use with Shiny module: action_link(id = c(1,2,3), label = "click", target = "on_click", pattern = "do_this", namespace = "module_id") ## End(Not run)
This wrapper function aims at enabling a trace level mechanism that relies on the cat function.
catl(..., level = 1, debug = Sys.getenv("TRACE_LEVEL"), newline = TRUE)catl(..., level = 1, debug = Sys.getenv("TRACE_LEVEL"), newline = TRUE)
... |
R objects as defined in cat |
level |
a numeric value indicating the level of trace |
debug |
an optional (usually omitted) value to indicate the level of trace to be displayed |
newline |
a logical. If TRUE (default), new line |
The goal is to provide a trace level mechanism that can be disabled in a production context (as printing output to the console or file is costly).
The different levels are left flexible.
By default, debug is set to Sys.getenv("TRACE_LEVEL")
If the environment variable is not set, no output will be produced (silent mode)
When the variable is set, the function will pass calls with level <= debug
to the original cat function.
The trace_level function can be used to activate a specific trace level.
None (invisible NULL).
# silent unless TRACE_LEVEL is set catl("Awesome message here") # force print no matter if TRACE_LEVEL is set catl("Awesome message here", debug = 1) # demonstrate trace levels catl("Awesome message here", level = 2, debug = 1) catl("Awesome message here", level = 1, debug = 2)# silent unless TRACE_LEVEL is set catl("Awesome message here") # force print no matter if TRACE_LEVEL is set catl("Awesome message here", debug = 1) # demonstrate trace levels catl("Awesome message here", level = 2, debug = 1) catl("Awesome message here", level = 1, debug = 2)
Copy Package Template Files.
copy_template(template, pkg = "ktools", path = getwd(), filename = NULL)copy_template(template, pkg = "ktools", path = getwd(), filename = NULL)
template |
the name of the template file to be copied. |
pkg |
the name of the package where to find the template. |
path |
destination path where to copy the template (default = working directory). |
filename |
an optional name for the copy. |
By default, the function addresses templates delivered along with this package
(i.e. pkg = "ktools").
When filename is not provided, the copy will have same name as the template
without the "template_" prefix pattern.
An error will be thrown if the template file is not found.
a logical (see file.copy()
## Not run: copy_template(template = "template_shiny_server.R", path = "shinyapp", filename = "my_server.R") ## End(Not run)## Not run: copy_template(template = "template_shiny_server.R", path = "shinyapp", filename = "my_server.R") ## End(Not run)
Builds a basic code counts report.
count_lines(con, verbose = FALSE)count_lines(con, verbose = FALSE)
con |
a connection object or a character string (passed to readLines). |
verbose |
a logical (FALSE by default) if counts should be printed to the console. |
The report will contain the following information:
total
code
comment
documentation
spacing
Code lines ending with a comment are counted as code lines (hence ignored from comments).
a named vector.
infile <- tempfile() lines <- "#' This\n#'\n\n# comment\np <- 1\n\nif(p==1) print(p)\n" writeLines(lines, infile) count_lines(infile)infile <- tempfile() lines <- "#' This\n#'\n\n# comment\np <- 1\n\nif(p==1) print(p)\n" writeLines(lines, infile) count_lines(infile)
Build an empty data.frame from a vector of colClasses.
create_data(colClasses)create_data(colClasses)
colClasses |
a named vector of classes. |
The names of the vector will be used to name the columns and the values to cast the columns to the given classes.
If NA is given as input for colClasses, then read.table() will return
an empty data.frame (0 obs. of 0 variables)
a data.frame.
create_data(colClasses = c(id = "numeric", date = "Date", comment = "character"))create_data(colClasses = c(id = "numeric", date = "Date", comment = "character"))
Compute specific range between two dates.
date_range(min, max, type = "this_year")date_range(min, max, type = "this_year")
min |
a Date for the lower value. |
max |
a Date for the higher value. |
type |
an optional character vector, to set the strategy (default = "this_year"). |
a Date vector c(start, end).
## Not run: date_range(min = Sys.Date()-365, max = Sys.Date()+365, type = "this_year") ## End(Not run)## Not run: date_range(min = Sys.Date()-365, max = Sys.Date()+365, type = "this_year") ## End(Not run)
Filter a data.frame by specific date range.
filter_date(x, colname = NULL, ref = Sys.Date(), unit = "month")filter_date(x, colname = NULL, ref = Sys.Date(), unit = "month")
x |
a data.frame with a Date or POSIXct column. |
colname |
an optional character string, the name of the column to use in filter. |
ref |
an optional Date value to be used as a reference for the date range. |
unit |
a string to compute the date range (default = "month") (see round_date). |
The purpose of this function is to make data navigation between date range easier. By default, it will filter the input data.frame to keep dates belonging to the current month.
When colname = NULL (the default), it will look for a 'date' column in x.
a filtered data.frame.
# -- this month (the default) filter_date(data.frame(date = Sys.Date() - runif(n = 10, min = -50, max = 50))) # -- previous month filter_date(data.frame(date = Sys.Date() - runif(n = 10, min = -50, max = 50)), ref = Sys.Date() - as.integer(format(Sys.Date(), "%d")))# -- this month (the default) filter_date(data.frame(date = Sys.Date() - runif(n = 10, min = -50, max = 50))) # -- previous month filter_date(data.frame(date = Sys.Date() - runif(n = 10, min = -50, max = 50)), ref = Sys.Date() - as.integer(format(Sys.Date(), "%d")))
Trick to solve the use of :: for package functions in do.call()
getNsFunction(x)getNsFunction(x)
x |
the name of the function, most probably as pkg::fun() |
the exported function name in namespace pkg
## Not run: getNsFunction("pkg::fun") ## End(Not run)## Not run: getNsFunction("pkg::fun") ## End(Not run)
Compute a numeric timestamp.
getTimestamp(k = 1000, digits = 0, silent = FALSE)getTimestamp(k = 1000, digits = 0, silent = FALSE)
k |
a numeric (default = 1000), used as a multiplication factor. |
digits |
an integer (default = 0) to round the value. |
silent |
an optional (default = FALSE) logical. If TRUE, no traces will go to the console. |
By default (k = 1000), the function returns a numeric up to the millisecond.
Output should not be used as a unique id if users / systems may call it more than one time per millisecond.
a numeric.
# compute up to the second timestamp getTimestamp(k = 1, digits = 0) # compute up to the millisecond timestamp getTimestamp(k = 1000) getTimestamp()# compute up to the second timestamp getTimestamp(k = 1, digits = 0) # compute up to the millisecond timestamp getTimestamp(k = 1000) getTimestamp()
Detects Date and/or POSIXct column(s) in a data.frame.
has_date(x, single = TRUE)has_date(x, single = TRUE)
x |
a data.frame object. |
single |
a logical (default TRUE) if it should return only the first column. |
the name of the column(s) or NA if no date column is found.
has_date(data.frame(date = Sys.Date())) has_date(data.frame(date = Sys.Date(), update = Sys.Date()), single = FALSE) has_date(data.frame(date = Sys.Date(), update = Sys.Date()), single = TRUE)has_date(data.frame(date = Sys.Date())) has_date(data.frame(date = Sys.Date(), update = Sys.Date()), single = FALSE) has_date(data.frame(date = Sys.Date(), update = Sys.Date()), single = TRUE)
incat(x, sep = "")incat(x, sep = "")
x |
R objects. |
sep |
a character vector of strings to append after each element (default is ""). |
When the function detects a direct call (i.e. not from another function), then it basically just do cat otherwise it finds the calling function name and print indented output based on callstack position.
None (invisible NULL).
# default incat("direct call") # call from different levels foo <- function() incat("inside foo") bar <- function() {incat("inside bar"); foo()} foo() bar()# default incat("direct call") # call from different levels foo <- function() incat("inside foo") bar <- function() {incat("inside bar"); foo()} foo() bar()
Split an input value into a named vector.
input_decode(x)input_decode(x)
x |
the (input) value to decode. |
The function is used together with action_link() / onclick_event()
when their value is left to the HTML tag id.
The expected pattern for x is "namespace-action_value" or "action_value".
More complex use cases should be covered using a list value in action_link().
a named vector c(namespace, action, value) or c(action, value).
input_decode("module1-add_leg_896") input_decode("add_leg_896")input_decode("module1-add_leg_896") input_decode("add_leg_896")
Matches a named list against a reference.
match.list(x, reference)match.list(x, reference)
x |
a named list to check. |
reference |
a named list to use as a reference. |
The function will drop any element from x that does not fit with a name
found in reference and add missing ones.
It will also check that elements in x have same classes as matching
element in reference.
a list.
match.list(x = list(foo = 1), reference = list(foo = 0, bar = "dummy"))match.list(x = list(foo = 1), reference = list(foo = 0, bar = "dummy"))
Matches a named list against the one expected in function arguments.
match.option(fun, arg, value)match.option(fun, arg, value)
fun |
the reference of the function, without (). |
arg |
the name of the argument to test. |
value |
the value to test. |
The list of options, including missing ones.
# function expecting a list as argument foo <- function(options = list(a = 1, b = 2)){} # match user input match.option(foo, "options", list(a = 1))# function expecting a list as argument foo <- function(options = list(a = 1, b = 2)){} # match user input match.option(foo, "options", list(a = 1))
This function helps building onclick event to pass complex instructions to a given listener. This is particularly useful when working with lists of links, most probably generated within an apply instruction over a data.frame.
onclick_event(target, value = "this.id", namespace = NULL, event = TRUE)onclick_event(target, value = "this.id", namespace = NULL, event = TRUE)
target |
the input to update on click. |
value |
the value to send to the input (see details). |
namespace |
the id of the module to target if so. |
event |
should Shiny treat it as an event. |
target defines the name of the input entry to update (i.e. input$target).
value will be passed to the target input.
By default, it will send the id of the HTML tag (ex: actionLink, actionButton).
This behavior can be tuned to send a more complex instruction. In particular, a list can be passed to the target input (see example).
a character string.
## Not run: # baseline: # input$btn_clicked will get the id of the html tag onclick_event(target = "btn_clicked") # custom value: # input$btn_clicked will get "foo" onclick_event(target = "btn_clicked", value = "foo") # custom list: # input$btn_clicked will get the list onclick_event(target = "btn_clicked", value = list(a = "foo", b = "bar")) # -- shiny module: # input$btn_clicked inside "module_id" will get 12 onclick_event(target = "btn_clicked", value = 12, namespace = "module_id") ## End(Not run)## Not run: # baseline: # input$btn_clicked will get the id of the html tag onclick_event(target = "btn_clicked") # custom value: # input$btn_clicked will get "foo" onclick_event(target = "btn_clicked", value = "foo") # custom list: # input$btn_clicked will get the list onclick_event(target = "btn_clicked", value = list(a = "foo", b = "bar")) # -- shiny module: # input$btn_clicked inside "module_id" will get 12 onclick_event(target = "btn_clicked", value = 12, namespace = "module_id") ## End(Not run)
Generates a code report for a given path.
scan_code(path = getwd())scan_code(path = getwd())
path |
a path to scan. |
a data.frame.
## Not run: scan_code() ## End(Not run)## Not run: scan_code() ## End(Not run)
seq_timestamp(n = 2)seq_timestamp(n = 2)
n |
the desired output vector length. |
a numeric vector of timestamps.
## Not run: seq_timestamp(n = 2) ## End(Not run)## Not run: seq_timestamp(n = 2) ## End(Not run)
Wrapper around Shiny *Output functions.
simple_ui(id, output, type = "ui", ...)simple_ui(id, output, type = "ui", ...)
id |
the id of the module. |
output |
the name of the output. |
type |
the type of output: "ui" (default), "text", "plot", "table". |
... |
other arguments to pass to the *Output function. |
id can be a vector of ids in case of sub module.
an HTML tag.
simple_ui(id = "my_module", output = "my_output")simple_ui(id = "my_module", output = "my_output")
Source all files from a given path.
source_code(path, verbose = FALSE)source_code(path, verbose = FALSE)
path |
a character vector of the path to explore. |
verbose |
a logical value (default = FALSE). If TRUE, then details about sourced files will be sent to the console. |
Given path is explored with "*.R" extension pattern. Sub-directories will be explored as well.
an integer, how many functions have been attached to the environment.
## Not run: source_code("./R") ## End(Not run)## Not run: source_code("./R") ## End(Not run)
Capitalize First Letters
toupper_words(s, strict = FALSE)toupper_words(s, strict = FALSE)
s |
a character string. |
strict |
a logical (default = FALSE) if other characters should be forced to lower. |
a character string.
toupper_words("this is an example")toupper_words("this is an example")
Capitalize First Letter
toupperfirst(x)toupperfirst(x)
x |
a character vector, or an object that can be coerced to character by as.character. |
a character vector.
toupperfirst("capitalize first letter") toupperfirst(1)toupperfirst("capitalize first letter") toupperfirst(1)
A helper function to get/set the trace level printed by catl().
trace_level(level = NULL)trace_level(level = NULL)
level |
an integer (or NULL). |
level is used to define the level of trace printed by catl().
Use 0 to set the trace OFF or NULL to get the current trace level.
Nothing or the active trace level.
trace_level() trace_level(2) trace_level(0)trace_level() trace_level(2) trace_level(0)
Add an environment variable to the project.
update_r_environ(path = getwd(), key, value)update_r_environ(path = getwd(), key, value)
path |
the path to the .Renviron file (default is working directory). |
key |
a character string for the name of the variable. |
value |
the value to be assigned to the variable. |
a logical (TRUE if success, else FALSE)
## Not run: update_r_environ(key = "MY_VAR", value = "my_value") ## End(Not run)## Not run: update_r_environ(key = "MY_VAR", value = "my_value") ## End(Not run)
Create a theme function that can be used across a project.
use_plot_theme(path = getwd())use_plot_theme(path = getwd())
path |
where to copy the template. |
a logical.
## Not run: use_plot_theme() ## End(Not run)## Not run: use_plot_theme() ## End(Not run)
Create .Renviron File
use_r_environ(path = getwd())use_r_environ(path = getwd())
path |
the path where to create the file. |
By default, path is set to the working directory.
a logical (see file.create())
## Not run: use_r_environ() ## End(Not run)## Not run: use_r_environ() ## End(Not run)
Compute unique identifier.
uuid()uuid()
By default getTimestamp() gives a value up to the millisecond.
In some use cases, for example when a sequence of ids need to be generated grammatically, multiple identical values will be generated within the same millisecond.
This wrapper calls getTimestamp() with k = 1000000 to get a value up to
the microsecond. This is usually enough the get unique value for example
when it's called from applying a function over a list.
a numeric.
uuid() # showing what the function is trying to solve any(duplicated(replicate(100, getTimestamp()))) any(duplicated(replicate(100, uuid())))uuid() # showing what the function is trying to solve any(duplicated(replicate(100, getTimestamp()))) any(duplicated(replicate(100, uuid())))
Checks whether a specific dependency is already inserted in the UI with this function, and performs the insert if necessary.
with_js(package, src, script, session = shiny::getDefaultReactiveDomain())with_js(package, src, script, session = shiny::getDefaultReactiveDomain())
package |
the name of the package. |
src |
where to find the script (see details). |
script |
the script to include (relative to src). |
session |
the session object of the Shiny server. |
The function is designed to be called from another function creating/updating a widget that requires JavaScript. With this, the user does not need to manage the dependency manually.
When session is NULL, the function will return without doing anything.
This is useful when the function is called from ui side. The JavaScript
dependency will be attached next time the function is called from server side.
This is because the session$userData object cannot be updated from ui side.
Details about src can be found in htmlDependency.
NULL (invisibly)
## Not run: with_js(package = "ktag", src = "assets", script = "js/ktag.js", session = shiny::getDefaultReactiveDomain()) ## End(Not run)## Not run: with_js(package = "ktag", src = "assets", script = "js/ktag.js", session = shiny::getDefaultReactiveDomain()) ## End(Not run)