@@ -39,6 +39,34 @@ type_to_param <- list(
3939 boolean = " b"
4040)
4141
42+ # ' Convert a CamelCase function name to snake_case with appropriate prefix
43+ # '
44+ # ' @param title The function title (e.g., "ST_AsEWKB", "RS_Width")
45+ # ' @returns Character snake_case name with appropriate prefix (e.g., "sd_as_ewkb", "rs_width")
46+ camel_to_snake <- function (title ) {
47+ # Determine prefix based on original function type
48+ if (grepl(" ^RS_" , title )) {
49+ prefix <- " rs_"
50+ } else {
51+ prefix <- " sd_"
52+ }
53+
54+ # Remove ST_, RS_, or S2_ prefix
55+ name <- sub(" ^(ST|RS|S2)_" , " " , title )
56+
57+ # Insert underscore before uppercase letters that follow lowercase letters
58+ # e.g., "AsEWKB" -> "As_EWKB"
59+ name <- gsub(" ([a-z])([A-Z])" , " \\ 1_\\ 2" , name )
60+
61+ # Insert underscore before uppercase letters followed by lowercase
62+ # (to handle acronyms like EWKB before lowercase)
63+ # e.g., "EWKBTest" -> "EWKB_Test"
64+ name <- gsub(" ([A-Z]+)([A-Z][a-z])" , " \\ 1_\\ 2" , name )
65+
66+ # Convert to lowercase and add appropriate prefix
67+ paste0(prefix , tolower(name ))
68+ }
69+
4270# Apache license header
4371license_header <- " # Licensed to the Apache Software Foundation (ASF) under one
4472# or more contributor license agreements. See the NOTICE file
@@ -425,7 +453,9 @@ generate_translation <- function(sd_name, fn_name, args, variadic = FALSE) {
425453# ' @param file_hash MD5 hash of source .qmd file
426454# ' @returns Character string with complete R file content
427455generate_r_file <- function (fn_name , frontmatter , description , file_hash ) {
428- sd_name <- sub(" ^st_" , " sd_" , fn_name )
456+ # Use title from frontmatter to get proper snake_case naming
457+ title <- frontmatter $ title %|| % fn_name
458+ sd_name <- camel_to_snake(title )
429459 kernel_info <- parse_kernel_params(frontmatter $ kernels , fn_name )
430460 title <- frontmatter $ description %|| % frontmatter $ title
431461
@@ -472,7 +502,15 @@ generate_r_file <- function(fn_name, frontmatter, description, file_hash) {
472502# ' @returns List with status ("generated", "skipped", "failed") and error message if failed
473503generate_from_qmd <- function (qmd_path , force = FALSE ) {
474504 fn_name <- tools :: file_path_sans_ext(basename(qmd_path ))
475- sd_name <- sub(" ^st_" , " sd_" , fn_name )
505+
506+ # Parse frontmatter early to get the proper sd_name from title
507+ frontmatter <- tryCatch(
508+ extract_frontmatter(qmd_path ),
509+
510+ error = function (e ) list (title = fn_name )
511+ )
512+ title <- frontmatter $ title %|| % fn_name
513+ sd_name <- camel_to_snake(title )
476514 output_path <- file.path(output_dir , paste0(sd_name , " .R" ))
477515
478516 # Compute hash
@@ -493,7 +531,10 @@ generate_from_qmd <- function(qmd_path, force = FALSE) {
493531 {
494532 message(" Generating " , sd_name , " .R from " , fn_name , " .qmd" )
495533
496- frontmatter <- extract_frontmatter(qmd_path )
534+ # Re-parse frontmatter if initial parse failed (used fallback)
535+ if (is.null(frontmatter $ kernels )) {
536+ frontmatter <- extract_frontmatter(qmd_path )
537+ }
497538 description <- extract_description_section(qmd_path )
498539
499540 content <- generate_r_file(fn_name , frontmatter , description , file_hash )
@@ -516,7 +557,33 @@ generate_from_qmd <- function(qmd_path, force = FALSE) {
516557# ' @returns Invisible NULL
517558update_sd_funcs <- function (files = NULL , force = TRUE ) {
518559 if (is.null(files )) {
519- qmd_files <- list.files(docs_dir , pattern = " ^(st|rs)_.*\\ .qmd$" , full.names = TRUE )
560+ qmd_files <- list.files(
561+ docs_dir ,
562+ pattern = " ^(st|rs|s2)_.*\\ .qmd$" ,
563+ full.names = TRUE
564+ )
565+
566+ # Clear old generated files when regenerating all
567+ message(" Clearing old generated files..." )
568+
569+ # Remove R/sd_*.R and R/rs_*.R files
570+ old_sd_files <- list.files(output_dir , pattern = " ^sd_.*\\ .R$" , full.names = TRUE )
571+ old_rs_files <- list.files(output_dir , pattern = " ^rs_.*\\ .R$" , full.names = TRUE )
572+ old_files <- c(old_sd_files , old_rs_files )
573+ if (length(old_files ) > 0 ) {
574+ file.remove(old_files )
575+ message(" Removed " , length(old_files ), " old R files" )
576+ }
577+
578+ # Clear man/ directory
579+ man_dir <- here :: here(" man" )
580+ if (dir.exists(man_dir )) {
581+ man_files <- list.files(man_dir , full.names = TRUE )
582+ if (length(man_files ) > 0 ) {
583+ file.remove(man_files )
584+ message(" Removed " , length(man_files ), " old man files" )
585+ }
586+ }
520587 } else {
521588 qmd_files <- file.path(docs_dir , paste0(files , " .qmd" ))
522589 missing <- ! file.exists(qmd_files )
@@ -545,6 +612,4 @@ update_sd_funcs <- function(files = NULL, force = TRUE) {
545612 message(" - " , f $ fn_name , " : " , f $ error )
546613 }
547614 }
548-
549- invisible (NULL )
550615}
0 commit comments