ctags-lang-r(7)

πŸ“¦
version 6.2.1 Β· 3 versions
, in ubuntu resolute, ubuntu stonking

πŸŽ€ NAME πŸŽ€

ctags-lang-r β€” Random notes about tagging R source code with Universal Ctags πŸ’–

Okay so bestie, welcome to ctags-lang-r(7) from the Universal Ctags fam. This is literally the scrapbook page where we keep all the random lore about how the R parser does its thing. No cap, it's giving niche but iconic ✨


✨ SYNOPSIS ✨

Three little ways to get ctags looking at your R files, pick your fighter πŸ’…

ctags ... --languages=+R ...
ctags ... --language-force=R ...
ctags ... --map-R=+.r ...

πŸ¦‹ DESCRIPTION πŸ¦‹

This man page gathers random notes about tagging R source code with Universal Ctags. That's the whole vibe β€” it's a notes dump, not a novel, and we love her for it 🫢


πŸ‘‘ KINDS πŸ‘‘

Here's the tea, bestie. If a variable gets a value returned from a well-known constructor and the variable appears for the first time in the current input file, the R parser makes a tag for that variable and attaches a kind associated with the constructor to the tag β€” and it does this regardless of whether the variable appears in the top-level context or inside a function. Obsessed, honestly 🌸

Well-known constructor and kind mapping:

  • function() β†’ kind function
  • c() β†’ kind vector
  • list() β†’ kind list
  • data.frame() β†’ kind dataframe

But if a variable doesn't get a value returned from one of the well-known constructors? Then the R parser attaches the globalVar or functionVar kind to the tag for the variable, depending on the context. It's giving ✨context-dependent✨ and honestly? Slay.

Here's an example demonstrating the usage of the kinds:

"input.r"

G <- 1
v <- c(1, 2)
l <- list(3, 4)
d <- data.frame(n = v)
f <- function(a) {
        g <- function (b) a + b
        w <- c(1, 2)
        m <- list (3, 4)
        e <- data.frame(n = w)
        L <- 2
}

"output.tags" with --options=NONE --sort=no --fields=+KZ -o - input.r

G       input.r /^G <- 1$/;"    globalVar
v       input.r /^v <- c(1, 2)$/;"      vector
l       input.r /^l <- list(3, 4)$/;"   list
d       input.r /^d <- data.frame(n = v)$/;"    dataframe
n       input.r /^d <- data.frame(n = v)$/;"    nameattr        scope:dataframe:d
f       input.r /^f <- function(a) {$/;"        function
g       input.r /^      g <- function (b) a + b$/;"     function        scope:function:f
w       input.r /^      w <- c(1, 2)$/;"        vector  scope:function:f
m       input.r /^      m <- list (3, 4)$/;"    list    scope:function:f
e       input.r /^      e <- data.frame(n = w)$/;"      dataframe       scope:function:f
n       input.r /^      e <- data.frame(n = w)$/;"      nameattr        scope:dataframe:f.e
L       input.r /^      L <- 2$/;"      functionVar     scope:function:f

Look at those scopes doing their little nested thing, scope:function:f and scope:dataframe:f.e β€” the way that the R parser keeps track of which function a variable lives inside is genuinely main character energy 😭πŸ”₯


πŸ’œ SEE ALSO πŸ’œ


That's the whole page, bestie. Go tag some R code and feel iconic doing it. This was ctags-lang-r(7), from Universal Ctags, version 6.2.1 β€” mwah, bye, take care of yourself πŸ’…πŸ¦‹πŸ’–

πŸ“¦ where this page comes from