An Introduction to rasciidoc

2019-02-09, 23:09:57

What is rasciidoc?

Inspired by Karl Broman`s reader on using knitr with asciidoc (http://kbroman.org/knitr_knutshell/pages/asciidoc.html), this is a wrapper to and a slight modification of knitr.

Knitting

A Minimal Example

Suppose, you have a file that reads

file_name <- system.file("files", "minimal", "knit.Rasciidoc",
                         package = "rasciidoc")
cat(readLines(file_name), sep = "\n")
= Some Title
Your Name
:toc2:
:numbered:
:data-uri:
:duration: 120

== A Section

=== A Subsection

* A list with a https://en.wikipedia.org/wiki/Hyperlink[link].
* Yet another entry in the list.

== Code
//begin.rcode
a  <- c(2, 3, 4, 10) # <1>
value <- 0 # <2>
for (a_i in a) { # <3>
    value <- value + a_i  # <4>
}
print(value) # <5>
//end.rcode


== A new section

//begin.rcode
my_sum <- function(x) {
    value <- 0
    for (x_i in x) {
        value <- value + x_i 
    }
    return(value)
}
//end.rcode

If you run render on this file (we use a temporary directory here)

withr::with_dir(tempdir(), {
                    file.copy(file_name, ".")
                    rasciidoc::render(basename(file_name))
})
## Warning in run_knit(file_name, knit = knit, envir = envir): Setting option
## knit to TRUE based on the file contents!
## Due to the CRAN policy of not writing "anywhere else on the file system apart from the R session's temporary directory" we work on a temporary copy of /tmp/RtmpMDfyTG/knit.Rasciidoc.
## Thus all internal sourcing and internal links will be broken and any output is written to /tmp/RtmpMDfyTG. Set the option "write_to_disk" to TRUE (using
##  options("write_to_disk" = TRUE)
## ) to bypass this. You may want to include the above line into your ~/.Rprofile.
## processing file: /tmp/RtmpMDfyTG/knit.Rasciidoc
## output file: /tmp/RtmpMDfyTG/knit.asciidoc
## [1] 0

you will create an HTML file that is identical to this file and that you could browse using browseURL(file.path(tempdir(), paste0(sub("\\..*$", "", basename(file_name)), ".html"))) from your current R session (vignettes like this are not allowed to start external programs like browsers, so you’ll have to do it yourself).

A Simple Example

Suppose you changed your file to be less minimalistic:

file_name <- system.file("files", "simple", "knit.Rasciidoc",
                         package = "rasciidoc")
cat(readLines(file_name), sep = "\n")
= Some Title
Your Name
:toc2:
:numbered:
:data-uri:
:duration: 120

== What is this About?


=== Some simple asciidoc

* A list with a https://en.wikipedia.org/wiki/Hyperlink[link].
* Yet another entry in the list.

== Including Code
Do not use the _include_ macro provided by asciidoc! 
//begin.rcode, code = readLines("src/sum.R")
//end.rcode


== A new section

//begin.rcode, code = readLines("src/my_sum.R")
//end.rcode
=== A subsection
//begin.rcode
print(value)
//end.rcode

//begin.rcode
print(my_sum(1:3))
//end.rcode

Some inline code: Object +value+ has value +r value+.


=== Second subsection

This file obviously reads code from files in a subdirectory called “src/”, so if you had that subdirectory and its files, too:

my_directory <- file.path(tempdir(), "simple")
dir.create(my_directory)
withr::with_dir(my_directory, {
                    file.copy(file_name, ".")
                    file.copy(file.path(dirname(file_name), "src"), ".",
                              recursive = TRUE)
})
## [1] TRUE
dir(my_directory, recursive = TRUE, full.names = TRUE)
## [1] "/tmp/RtmpMDfyTG/simple/knit.Rasciidoc"
## [2] "/tmp/RtmpMDfyTG/simple/src/my_sum.R"  
## [3] "/tmp/RtmpMDfyTG/simple/src/sum.R"

you could render the file

rasciidoc::render(file.path(my_directory, basename(file_name)))
## Warning in run_knit(file_name, knit = knit, envir = envir): Setting option
## knit to TRUE based on the file contents!
## Due to the CRAN policy of not writing "anywhere else on the file system apart from the R session's temporary directory" we work on a temporary copy of /tmp/RtmpMDfyTG/simple/knit.Rasciidoc.
## Thus all internal sourcing and internal links will be broken and any output is written to /tmp/RtmpMDfyTG. Set the option "write_to_disk" to TRUE (using
##  options("write_to_disk" = TRUE)
## ) to bypass this. You may want to include the above line into your ~/.Rprofile.
## processing file: /tmp/RtmpMDfyTG/simple/knit.Rasciidoc
## output file: /tmp/RtmpMDfyTG/knit.asciidoc
## [1] 0

and create an HTML file that is identical to this file and that you could browse using browseURL(file.path(tempdir(), paste0(sub("\\..*$", "", basename(file_name)), ".html"))) from your current R session .

Spinnig

You can also use a spinnig file for input:

file_name <- system.file("files", "simple", "spin.R_nolint",
                         package = "rasciidoc")
cat(readLines(file_name), sep = "\n")
#' = Some Title
#' Your Name
#' :toc2:
#' :numbered:
#' :data-uri:
#' :duration: 120
#' 
#' == What is this About?
#' 
#' //begin_no_slide
#' This will not show up on slides.
#' //end_no_slide
#' 
#' === Some simple asciidoc
#' 
#' * A list with a https://en.wikipedia.org/wiki/Hyperlink[link].
#' * Yet another entry in the list.
#' 
#' == Including Code
#' Do not use the _include_ macro provided by asciidoc!
#' Instead prefix all source statements with 
#' ----
#' #+ code = readLines("file_to_be_sourced")
#' #+ include = FALSE
#' ----
#' It est use
#' ----
#' #+ code = readLines("src/sum.R")
#' #+ include = FALSE
#' source("src/sum.R")
#' ----
#' to produce
#+ code = readLines("src/sum.R")
#+ include = FALSE
source("src/sum.R")
#' 
#' 
message("A message, probably different output hooks.")
#' == A new section
#' 
#+ code = readLines("src/my_sum.R")
#' === A subsection
print(value)
#' 
print(my_sum(1:3))
#' 
#' Inline code does not work: Object +value+ has value +r value+.
#' 

You run render on it:

withr::with_dir(tempdir(), {
                    file.copy(file_name, ".", overwrite = TRUE)
                    file.copy(file.path(dirname(file_name), "src"), ".",
                              recursive = TRUE)
                    rasciidoc::render(basename(file_name))
})
## Due to the CRAN policy of not writing "anywhere else on the file system apart from the R session's temporary directory" we work on a temporary copy of /tmp/RtmpMDfyTG/spin.R_nolint.
## Thus all internal sourcing and internal links will be broken and any output is written to /tmp/RtmpMDfyTG. Set the option "write_to_disk" to TRUE (using
##  options("write_to_disk" = TRUE)
## ) to bypass this. You may want to include the above line into your ~/.Rprofile.
## [1] 0

The Option “write_to_disk”

You may have noticed that output is written to tempdir(), instead to the subdirectories below it. This is due to the CRAN policy of not writing “anywhere else on the file system apart from the R session’s temporary directory”. Set the option “write_to_disk” to TRUE (using options(write_to_disk = TRUE) to bypass this. You may want to include the above line into your ~/.Rprofile.

Knitr Hooks

I change the way knitr translates (see here), as it renders messages, warnings and errors to [NOTE|WARNING|ERROR]-blocks in asciidoc, which is … not my choice. To restore knitr`s behaviour, set hooks or replacement to NULL.

rasciidoc::render(file.path(tempdir(), basename(file_name)), hooks = NULL)
## Due to the CRAN policy of not writing "anywhere else on the file system apart from the R session's temporary directory" we work on a temporary copy of /tmp/RtmpMDfyTG/spin.R_nolint.
## Thus all internal sourcing and internal links will be broken and any output is written to /tmp/RtmpMDfyTG. Set the option "write_to_disk" to TRUE (using
##  options("write_to_disk" = TRUE)
## ) to bypass this. You may want to include the above line into your ~/.Rprofile.
## [1] 0