--- a
+++ b/R/api_xq.R
@@ -0,0 +1,108 @@
+# FUN: Create API functions from .xq files
+
+#' Convert camel case to snake case
+#'
+#' @param name a character vector
+#'
+#' @return same length as `name` but with snake case
+#' @export
+#'
+#' @examples
+#' to_snake("sparseDataRange")
+to_snake <- function(name) {
+  s <- sub("(.)([A-Z][a-z]+)", "\\1_\\2", name)
+  s <- gsub("([a-z0-9])([A-Z])", "\\1_\\2", s)
+  tolower(s)
+}
+
+.rm_extension <- function(filepath) {
+  sub(
+    pattern = "(.*)\\..*$", replacement = "\\1",
+    basename(filepath)
+  )
+}
+
+.marshall_param <- function(p) {
+  stopifnot(is.atomic(p) | is.list(p))
+
+  # If input is a list, use .arrayfmt, this fix single gene/sample query
+  if (is.list(p)) {
+    p <- as.character(p)
+    return(.arrayfmt(p))
+  } else if (length(p) == 1) {
+    return(.quote(p))
+  } else if (length(p) > 1) {
+    return(.arrayfmt(p))
+  } else {
+    return("nil")
+  }
+}
+
+.call <- function(query, params) {
+  sprintf(
+    "(%s %s)", query,
+    paste(sapply(params, .marshall_param),
+      collapse = " "
+    )
+  )
+}
+
+.make_fun <- function(fun, body, args) {
+  eval(parse(text = paste(fun,
+    "<- function(",
+    args,
+    ") {\n",
+    body,
+    "\n}",
+    sep = ""
+  )),
+  envir = as.environment("package:UCSCXenaTools")
+  )
+  # as.call(c(as.name("{"), e)) -> body(ff)
+  # parse(text="y=\"1\"; return(y)")
+}
+
+
+.init_api <- function() {
+  # .api_generator
+  xq_files <- list.files(
+    system.file("queries", package = "UCSCXenaTools"),
+    pattern = "xq",
+    full.names = TRUE
+  )
+
+  if (length(xq_files) == 0) {
+    stop("No xq file find!")
+  }
+
+
+  for (f in xq_files) {
+    fn <- .rm_extension(f)
+    fun <- to_snake(fn)
+    query <- readr::read_file(f)
+    params <- sub(
+      "^[^[]+[[]([^]]*)[]].*$",
+      "\\1",
+      query
+    )
+    params <- unlist(strsplit(params, split = " "))
+    all_params <- c("host", params)
+
+    params <- paste(params, collapse = ", ")
+    all_params <- paste(all_params, collapse = ", ")
+    # Create hidden variable for storing xquery
+    xquery <- paste0(".xq_", fun)
+    assign(xquery, query,
+      envir = as.environment("package:UCSCXenaTools")
+    )
+    body <- sprintf(
+      "xquery=get(\".xq_%s\", as.environment(\"package:UCSCXenaTools\")) \nUCSCXenaTools:::.xena_post(host, UCSCXenaTools:::.call(xquery, list(%s)), simplifyVector = TRUE)",
+      fun,
+      params
+    )
+
+    # Create hidden functions
+    fun <- paste0(".p_", fun)
+    .make_fun(fun, body, all_params)
+  }
+}