You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, we discussed at Appsilon how to extract all packages and function from the script and those are our findings.
Insights
NCmisc::list.functions.in.file() -> lists all functions from the script. It needs library() calls to be executed first. For example:
# main.R
library(dplyr)
internal_function<-function() {
return("This is an internal function")
}
internal_function()
df<-iris %>%
filter(Petal.Length>1.5) %>%
select(Species, Petal.Length)
print(head(df))
Gives
Without loading the library it gives
To find all library/require calls you can regular expressions, but for more reliability you can use XML Xpath queries or treesitter.
This is not {box} compatible though.
2. For box you can take inspiration from box.linters::box_usage_linter() and box.linters::box_unused_att_pkg_fun_linter() functions implementations in box.linters package.
A PoC for NCmisc version
In details, I attach the PoC. Note that since this PoC works on regular expressions, it fails on lines like # library(...), i.e., it recognises them as imports.
Details
get_functions_df<-function(file) {
# Extract packages from file (both library and require)code<- readLines(file)
# Match library() and require() with various quote styleslib_pattern<-'(library|require)\\s*\\(\\s*["\']?([^"\'\\)\\s]+)["\']?\\s*\\)'matches<- regmatches(code, gregexpr(lib_pattern, code))
# Extract package namespkgs<- unique(unlist(lapply(matches, function(m) {
gsub(lib_pattern, '\\2', m)
})))
# Load packagesinvisible(lapply(pkgs, function(p) {
suppressPackageStartupMessages(require(p, character.only=TRUE, quietly=TRUE))
}))
# Get functions from NCmiscfunc_list<-NCmisc::list.functions.in.file(file)
# Process into clean data framedf_list<-list()
for (namein names(func_list)) {
funcs<-func_list[[name]]
if (length(funcs) ==0) next# Handle multiple packagesif (grepl("^c\\(", name)) {
# Extract individual package namespkgs<- gsub('"', '', unlist(strsplit(gsub("c\\(|\\)", "", name), ", ")))
pkg_str<- paste(pkgs, collapse=", ")
} else {
pkg_str<- gsub('"', '', name)
}
# Clean up package namespkg_str<- gsub("character\\(0\\)", "user_defined", pkg_str)
df_list[[length(df_list) +1]] <-data.frame(
func_name=funcs,
package=pkg_str,
stringsAsFactors=FALSE
)
}
# Combine and sortresult<- do.call(rbind, df_list)
result[order(result$package, result$func_name), ]
}
# Example usage:df<- get_functions_df("main.R")
print(df)
For the main.R from above we get, note that filter is in both dplyr and stats
To find all library/require calls you can regular expressions, but for more reliability you can use XML Xpath queries or treesitter.
This is not {box} compatible though. 2. For box you can take inspiration from box.linters::box_usage_linter() and box.linters::box_unused_att_pkg_fun_linter() functions implementations in box.linters package.
A PoC for NCmisc version
In details, I attach the PoC. Note that since this PoC works on regular expressions, it fails on lines like # library(...), i.e., it recognises them as imports.
get_functions_df <- function(file) {
Extract packages from file (both library and require)
code <- readLines(file)
Match library() and require() with various quote styles
Activity
pstorozenko commentedon May 28, 2025
Hi, we discussed at Appsilon how to extract all packages and function from the script and those are our findings.
Insights
NCmisc::list.functions.in.file()-> lists all functions from the script. It needslibrary()calls to be executed first. For example:Gives
Without loading the library it gives
To find all
library/requirecalls you can regular expressions, but for more reliability you can use XML Xpath queries or treesitter.This is not
{box}compatible though.2. For
boxyou can take inspiration frombox.linters::box_usage_linter()andbox.linters::box_unused_att_pkg_fun_linter()functions implementations in box.linters package.A PoC for NCmisc version
In
details, I attach the PoC. Note that since this PoC works on regular expressions, it fails on lines like# library(...), i.e., it recognises them as imports.Details
For the main.R from above we get, note that filter is in both
dplyrandstatsI hope it helps anyone working on this in the future.
laxamanaj commentedon Jun 6, 2025
Hi, @pstorozenko .
I appreciate you looking into this. I like how you are able to extract both the functions and the packages that they are being called from.
This could potentially be helpful information to merge with what I did here in #20 .
We can take this back to our R Consortium colleagues to get their feedback to see if they still want this.