mrgsolve icon indicating copy to clipboard operation
mrgsolve copied to clipboard

[DOC] How to annotate blocks with Rmd?

Open billdenney opened this issue 6 years ago • 4 comments

I love the new ability to use Rmd files!

One thing that wasn't clear from the info available is how to add modifiers like @annotated to the block. After a bit of playing, I found that I can just add it to the first line of the block like the following. Can you please add that to the manual?

```{cmt}
@annotated
CENT : Central (mg)
P1   : Peripheral compartment (mg)
```

My first attempt was to add it to the header like:

```{cmt, annotated=TRUE}

or

```{cmt @annotated}

billdenney avatar Jul 21 '19 17:07 billdenney

Thanks, Bill. I will add it to the documentation.

I did spend some time fiddling around with (better) ways to specify the block options, including what you did in the second example. I ended up ditching the approach and keeping the simple formulation. But hoping to work it out in the future and just pass all the block options in as chunk options.

KTB

kylebaron avatar Jul 21 '19 19:07 kylebaron

How about this?

modelparse_rmd <- function(txt, split=FALSE, drop_blank=TRUE, 
                           comment_re = "//") {
  
  if(split) txt <- strsplit(txt,"\n",perl=TRUE)[[1]]
  
  if(drop_blank) txt <- txt[!grepl("^\\s*$",txt)]
  
  for(comment in comment_re) {
    m <- as.integer(regexpr(comment,txt,fixed=TRUE))
    w <- m > 0
    txt[w] <- substr(txt[w], 1, m[w]-1)
  }
  start_re <- "^```\\{.*\\}\\s*"
  end_re <- "^\\s*```\\s*$"
  start <- grep(start_re, txt)
  end <- grep(end_re, txt)
  ans <- vector("list", length(start))
  for(i in seq_along(start)) {
    ans[[i]] <- txt[seq(start[i], end[i])]
    ans[[i]] <- gsub("^```\\{\\s*(r|c) +", "\\{", ans[[i]])
    ans[[i]] <- sub("^```\\{", "\\{", ans[[i]])
    ans[[i]] <- sub("```", "", ans[[i]])
  }
  chunk <- sapply(ans, "[[", 1)
  lab <- trimws(gsub("\\{|\\}", "", chunk))
  # Split by any combination of space, comma, space where at least one of those
  # is required, but the rest are not required.
  sp <- strsplit(lab, "(\\s+|,\\s+|\\s+,|\\s+,\\s+)")
  label <- sapply(sp, "[", 1L)
  label <- strsplit(label, "-", fixed = TRUE)
  label <- sapply(label, "[", 1L)
  # Find the options and reconnect them with a space
  opts <- sapply(X=lapply(sp, "[", -1L), FUN=paste, collapse=" ")
  for(i in seq_along(label)) {
    # Drop the start and ending markers
    ans[[i]] <- ans[[i]][-c(1, length(ans[[i]]))]
    # Add the options (if present)
    if (opts[i] != "") {
      ans[[i]] <- c(opts[i], ans[[i]])
    }
  }
  names(ans) <- toupper(label)
  dropR <- names(ans)=="R"
  if(any(dropR)) {
    ans <- ans[!dropR]  
  }
  return(ans)
}

It extracts everything puts the options together with a single space between them, and then puts that as the first row. (I'm happy to make a PR if it is what you're looking for.)

billdenney avatar Jul 21 '19 19:07 billdenney

Thanks, BIll. That's more or less the code that I had developed to tuck block options into the chunk. The sticky part is what happens after that. There is some nuance that needs to be addressed and I just want to think through some more.

kylebaron avatar Jul 23 '19 13:07 kylebaron

Fair enough, I did see that you had something very close to that in the code. Let me know if I can help.

billdenney avatar Jul 23 '19 13:07 billdenney