<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/automating-roxygen2-package-documentation/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://yonicd.github.io/2017-09-18-sinew/"> Jonathan Sidi's R Blog</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>	Take the mystery out of CRAN level package maintenance – </p>
<p>Thinking of creating a new package? Dread the task of function documentation? Afraid to run <code>devtools::check(build_args = '--as-cran')</code> and get bombarded by Errors, Warnings, and Notes (oh my!) ? Wait…. breathe!</p>
<p><img alt="" src="https://i2.wp.com/media.giphy.com/media/pWYReekqQW72U/giphy.gif?w=456&ssl=1" data-recalc-dims="1"></p>
<p>After feeling all that anxiety and following all of Hadley’s <a rel="nofollow" href="http://r-pkgs.had.co.nz/man.html" target="_blank">directions</a> online, I felt I was doing a lot of manual labour, and that a package should be doing all lot of this for me. So we wrote one – <code>sinew</code> (sin-yu).</p>
<h2>tl;dr: <code>sinew</code> is an automatic roxygen2 documentation creator</h2>
<p>Quick example, run it in R:</p>
<div>
<pre><code><span> </span><span>install.packages</span><span>(</span><span>&quot;sinew&quot;</span><span>)</span><span> </span><span># or devtools::install_github('metrumresearchgroup/sinew')
</span><span> </span><span># simple function
</span><span> </span><span>myFun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>h</span><span>=</span><span>1</span><span>){</span><span>
</span><span>utils</span><span>::</span><span>head</span><span>(</span><span>rnorm</span><span>(</span><span>10</span><span>),</span><span>h</span><span>)</span><span>
</span><span>}</span><span>
</span><span>library</span><span>(</span><span>sinew</span><span>)</span><span>
</span><span>makeOxygen</span><span>(</span><span>myFun</span><span>)</span><span>
</span></code></pre>
</div>
<p>This will produce the following output (which you can then append above your definition of <code>myFun</code>):</p>
<div>
<pre><code><span>makeOxygen</span><span>(</span><span>myFun</span><span>)</span><span>
</span><span>#' @title FUNCTION_TITLE
#' @description FUNCTION_DESCRIPTION
#' @param h PARAM_DESCRIPTION, Default: 1
#' @return OUTPUT_DESCRIPTION
#' @details DETAILS
#' @examples #' \dontrun{
#' if(interactive()){
#' #EXAMPLE1
#' }
#' }
#' @seealso #' \code{\link[utils]{head}}
#' @rdname myFun
#' @export #' @importFrom utils head
</span><span>myFun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>h</span><span>=</span><span>1</span><span>){</span><span>
</span><span>utils</span><span>::</span><span>head</span><span>(</span><span>h</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>or document functions interactively with the shiny gadget:</p>
<p><iframe width="100%" allowfullscreen src="https://www.youtube.com/embed/cabOtf191OQ" height="400"></iframe></p>
<p>For more details read the rest of the post, or skip straight to the gitbook: <a rel="nofollow" href="https://metrumresearchgroup.github.io/sinew/" target="_blank">https://metrumresearchgroup.github.io/sinew/</a>.</p>
<h2>Why sinew?</h2>
<p>Let me explain by example…</p>
<p>The current way to start down the documentation path is to create a function, I’ll use <code>myFun</code> defined above. Next I would use the skeleton provided by RStudio (In the toolbar Code=>Insert Roxygen Skeleton).</p>
<div>
<pre><code><span>#' Title
#'
#' @param h #'
#' @return
#' @export
#'
#' @examples
</span><span>myFun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>h</span><span>=</span><span>1</span><span>){</span><span>
</span><span>utils</span><span>::</span><span>head</span><span>(</span><span>h</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>This gets me on my way, but there is information nested within the function itself that can be useful to document and manage the namespace</p>
<ul>
<li>the default value of <code>h</code></li>
<li>the function <code>head</code> needs to be imported from the package <code>utils</code></li>
</ul>
<p>I could just add that manually but this is just a toy example, actual functions have many parameters and you can import many functions from a number of different packages.</p>
<p>Trying to do the documentation bookkeeping as you develop the function will make you lose your train of thought, and make you forget that great idea you just had. Or you could write the full function and then at the end try to figure out what functions you need to import what packages they are from, should they get a seealso field, what parameters you used and so on…</p>
<p>Sinew will do this for you. It will parse your full function for relevant information that can fill in the blanks in the roxygen2 documentation and manage your import fields for you.<br>
Think of it as connecting the meat of your function to the Roxygen2 skeleton – or just the <a rel="nofollow" href="https://en.wikipedia.org/wiki/Tendon" target="_blank">definition</a> of the term sinew (again sin-yu). Added bonus it will help keep your package CRAN ready as you develop.</p>
<p>So how would that skeleton look after running it with sinew?</p>
<p>The workhorse of sinew is <code>makeOxygen</code>, it takes functions and returns Roxygen2 headers.</p>
<div>
<pre><code><span>makeOxygen</span><span>(</span><span>myFun</span><span>)</span><span>
</span><span>#' @title FUNCTION_TITLE
#' @description FUNCTION_DESCRIPTION
#' @param h PARAM_DESCRIPTION, Default: 1
#' @return OUTPUT_DESCRIPTION
#' @details DETAILS
#' @examples #' \dontrun{
#' if(interactive()){
#' #EXAMPLE1
#' }
#' }
#' @seealso #' \code{\link[utils]{head}}
#' @rdname myFun
#' @export #' @importFrom utils head
</span><span>myFun</span><span> </span><span>&lt;-</span><span> </span><span>function</span><span>(</span><span>h</span><span>=</span><span>1</span><span>){</span><span>
</span><span>utils</span><span>::</span><span>head</span><span>(</span><span>h</span><span>)</span><span>
</span><span>}</span><span>
</span></code></pre>
</div>
<p>That little function had a lot of information embbeded in it to make your documentation well rounded.</p>
<ul>
<li>Each field has it’s own <em>placeholder</em> that will guide you to what is expected.</li>
<li><strong>param</strong> has the default value built in.</li>
<li><strong>examples</strong> is populated with a more current layout to support htmlwidget and shiny examples.</li>
<li><code>utils</code> was found and was added to <strong>importFrom</strong> automatically as was it’s <strong>seealso</strong> counterpart.</li>
<li><strong>rdname</strong> was added with the name of the function.</li>
</ul>
<p>Now lets take a real function – <code>lm</code></p>
<div>
<pre><code><span>makeOxygen</span><span>(</span><span>lm</span><span>)</span><span>
</span><span>#' @title FUNCTION_TITLE
#' @description FUNCTION_DESCRIPTION
#' @param formula PARAM_DESCRIPTION
#' @param data PARAM_DESCRIPTION
#' @param subset PARAM_DESCRIPTION
#' @param weights PARAM_DESCRIPTION
#' @param na.action PARAM_DESCRIPTION
#' @param method PARAM_DESCRIPTION, Default: 'qr'
#' @param model PARAM_DESCRIPTION, Default: TRUE
#' @param x PARAM_DESCRIPTION, Default: FALSE
#' @param y PARAM_DESCRIPTION, Default: FALSE
#' @param qr PARAM_DESCRIPTION, Default: TRUE
#' @param singular.ok PARAM_DESCRIPTION, Default: TRUE
#' @param contrasts PARAM_DESCRIPTION, Default: NULL
#' @param offset PARAM_DESCRIPTION
#' @param ... PARAM_DESCRIPTION
#' @return OUTPUT_DESCRIPTION
#' @details DETAILS
#' @examples #' \dontrun{
#' if(interactive()){
#' #EXAMPLE1
#' }
#' }
#' @seealso #' \code{\link[stats]{model.frame}}
#' @rdname lm
#' @export #' @importFrom stats model.frame
</span><span>lm</span><span>
</span></code></pre>
</div>
<p>That would of been a pain to do by hand, all that is left to do is replace the placeholders with relevant information and you’re done. Also notice the layout is consistent so other people (and you) can easily navigate the help across the package functions.</p>
<h2>A few features and use cases:</h2>
<ul>
<li>
<p>Setting package options persistent during a session is done using <code>sinew_opts</code> (much like <code>knitr::opts_chunk</code>).</p>
</li>
<li>
<p>For keeping settings persistent across sessions during package development sinew reads from the working directory on load a file named <code>_sinewconfig.yml</code>.</p>
</li>
<li>
<p>To run <code>makeOxygen</code> in batch mode (like a whole <code>./R</code> package subdirectory) use the function <code>makeOxyFile</code>.</p>
</li>
<li>
<p>To convert a long single file with multiple functions interwoven with a body script into multiple single function files, and keeping the script body intact, use <code>untangle</code>. If a function within the long file already has roxygen2 headers then they will be carried over to the new file.</p>
</li>
<li>
<p>To quickly run through a whole package and create the DESCRIPTION file <code>Imports:</code> field use <code>makeImport('./R',format='description')</code></p>
</li>
<li>
<p>After updating a function the documentation gets out of synch and needs updating. <code>moga</code> (make oxygen great again!) will cross check the current documentation of an R script and the current function script itself and update/add any parameters/defaults/imports discrepancies.</p>
</li>
<li>
<p>Setting <code>cut</code> to an integer value in <code>makeOxygen</code> to return <strong>import package</strong> instead of <strong>importFrom package function1 [function2 …]</strong> for packages that call more than the value assigned to <code>cut</code>.</p>
</li>
</ul>
<h2>Interactive Documentation</h2>
<p>A Shiny gadget was built to combine all this into an easy to use interface. Highlight text (preferably a function) in source editor of RStudio and then deploy the addin from the addins menu.</p>
<p>The gadget can read in almost any source you have the function in: unsourced functions, functions in the global environment, in a loaded package, in an installed package that you didn’t load yet.</p>
<p><iframe width="100%" allowfullscreen src="https://www.youtube.com/embed/S8dAOwrvoDw" height="400"></iframe></p>
<p>The gadget will allow you to preview the roxygen header, add and remove roxygen2 fields with checkboxes and control the level of <code>cut</code>. When you’re ready insert what you see in the preview pane into the editor. When you’re done with one function highlight another one and continue to work, if you need to move to another file tab… that’s ok too!</p>
<p>If there is already documentation move into <strong>update mode</strong>, and touch up any changes that need to be made through <code>moga</code>.</p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://yonicd.github.io/2017-09-18-sinew/"> Jonathan Sidi's R Blog</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/sqz9qNkyikc" height="1"></a></div>