Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code structure #83

Merged
merged 12 commits into from
Jun 27, 2019
11 changes: 0 additions & 11 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
# Generated by roxygen2: do not edit by hand

export(add_dependencies_to_description)
export(as.package)
export(create_compendium)
export(github_pat)
export(is.package)
export(package_file)
export(parse_deps)
export(use_analysis)
export(use_build_ignore)
export(use_circleci)
export(use_compendium)
export(use_dockerfile)
export(use_git)
export(use_git_hook)
export(use_git_quietly)
export(use_github)
export(use_github_links)
export(use_readme_rmd)
export(use_travis)
import(bookdown)
Expand Down
29 changes: 29 additions & 0 deletions R/core_create_compendium.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#' @name create_compendium
#' @title Quickly create a basic research compendium by combining several rrtools functions into one.
#'
#' @description In one step, this will create an R package, attach the MIT license to it, add the rrtools' README to it, initiate a Git repository and make an initial commit to track files in the package, and create the 'analysis' directory structure, and populate it with an R Markdown file and bib file. This function will not create a GitHub repository for the compendium, a Dockerfile, a Travis config file, or any package tests. Those require some interaction outside of R and are left to the user.
#'
#' @param pkgname location to create new package. The last component of the path will be used as the package name
#' @param data_in_git should git track the files in the data directory? Default is TRUE
#'
#' @importFrom usethis use_mit_license use_git
#' @export

create_compendium <- function(pkgname, data_in_git = TRUE) {

# create new project
rrtools::use_compendium(pkgname)

# move us into the new project
setwd(pkgname)

# initialize the new project with useful features
usethis::use_mit_license(name = usethis::use_git_config()$`user.name`)
rrtools::use_readme_rmd()
use_git_quietly()
rrtools::use_analysis(data_in_git = data_in_git)

# install the package and its dependencies
devtools::install(quiet = TRUE)

}
File renamed without changes.
159 changes: 159 additions & 0 deletions R/core_use_analysis.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#' @name use_analysis
#' @aliases add_analysis
#' @title Adds an analysis directory (and sub-directories), and an Rmd file ready to write
#'
#' @description This will create \file{paper.Rmd}, \file{references.bib}
#' and several others, and add \pkg{bookdown} to the imported packages listed in the DESCRIPTION file.
#'
#' @param pkg defaults to the package in the current working directory
#' @param template the template file to use to create the main analysis document. Defaults to 'paper.Rmd', ready to write R Markdown and knit to MS Word using bookdown
#' @param location the location where the directories and files will be written to. Defaults to a top-level 'analysis' directory. Other options are 'inst' (for the inst/ directory, so that all the contents will be included in the installed package) and 'vignettes' (as in a regular package vignette, all contents will be included in the installed package).
#' @param data forwarded to \code{whisker::whisker.render}
#' @param data_in_git should git track the files in the data directory?
#' @export
use_analysis <- function(pkg = ".", location = "top_level", template = 'paper.Rmd', data = list(), data_in_git = TRUE) {
pkg <- as.package(pkg)
pkg$Rmd <- TRUE
gh <- github_info(pkg$path)

usethis::ui_done("Adding bookdown to Imports\n")
add_desc_package(pkg, "Imports", "bookdown")

location <- ifelse(location == "top_level", "analysis",
ifelse(location == "vignettes", "vignettes",
ifelse(location == "inst", "inst",
stop("invalid 'location' argument"))))

# create file structure...
create_directories(location, pkg)

# add template files for paper.Rmd, .bib, etc. ...
switch(
location,
vignettes = use_vignette_rmd(location,
pkg,
gh,
template),
analysis = {use_paper_rmd(pkg,
location = file.path(location, "paper"),
gh,
template);
use_build_ignore("analysis",
escape = FALSE,
pkg = pkg)
},
inst = use_paper_rmd(pkg,
location = file.path(location, "paper"),
gh,
template)
)

if (!data_in_git) use_git_ignore("*/data/*")

cat(crayon::bold("\nNext, you need to: "), rep(crayon::green(clisymbols::symbol$arrow_down),4), "\n")
usethis::ui_todo("Write your article/report/thesis, start at the paper.Rmd file")
usethis::ui_todo("Add the citation style library file (csl) to replace the default provided here, see {crayon::bgBlue('https://github.com/citation-style-language/')}")
usethis::ui_todo("Add bibliographic details of cited items to the {usethis::ui_value('references.bib')} file")
usethis::ui_todo("For adding captions & cross-referencing in an Rmd, see {crayon::bgBlue('https://bookdown.org/yihui/bookdown/')}")
usethis::ui_todo("For adding citations & reference lists in an Rmd, see {crayon::bgBlue('http://rmarkdown.rstudio.com/authoring_bibliographies_and_citations.html')}")

# message about whether data files are tracked by Git:
cat(crayon::bold("\nNote that:\n"))
if(!data_in_git) {cat(paste0(warning_bullet(), " Your data files ", crayon::red("are not"), " tracked by Git and ", crayon::red("will not"), " be pushed to GitHub \n"))
} else {
cat(paste0(warning_bullet(), " Your data files ", crayon::green("are"), " tracked by Git and ", crayon::green("will"), " be pushed to GitHub \n"))
}


invisible(TRUE)
}



#### directly related helpers ####

create_directories <- function(location, pkg){

if (location %in% c("analysis", "vignettes", "inst")) {
usethis::ui_done("Creating {usethis::ui_value(location)} directory and contents")
use_directory(location, pkg = pkg)
use_directory(paste0(location, "/paper"), pkg = pkg)
use_directory(paste0(location, "/figures"), pkg = pkg)
use_directory(paste0(location, "/templates"), pkg = pkg)
use_directory(paste0(location, "/data"), pkg = pkg)
use_directory(paste0(location, "/data/raw_data"), pkg = pkg)
use_directory(paste0(location, "/data/derived_data"), pkg = pkg)

# create a file that inform of best practices
invisible(file.create(paste0(pkg$path, "/", location, "/data/DO-NOT-EDIT-ANY-FILES-IN-HERE-BY-HAND")))

# move templates for MS Word output
invisible(file.copy(from = list.files(system.file("templates/word_templates/",
package = "rrtools",
mustWork = TRUE),
full.names = TRUE),
to = paste0(pkg$path, "/", location, "/templates"),
recursive = TRUE))

# move csl file
invisible(file.copy(from = system.file("templates/journal-of-archaeological-science.csl",
package = "rrtools",
mustWork = TRUE),
to = paste0(pkg$path, "/", location, "/templates"),
recursive = TRUE))


# move bib file in there also
use_template("references.bib", pkg = pkg, data = gh,
out_path = file.path(location, "paper"))

} else # else do this..
{
# BM: I think we want to let the user have some more control
# over this, and leave thesis/book out of here?
# message("* Creating ", location, "/ directory and contents")
# use_directory(location, pkg = pkg)
# invisible(file.copy(from = system.file("templates/thesis_template/.",
# package = "rrtools",
# mustWork = TRUE),
# to = paste0(location),
# recursive = TRUE))


}
}

use_paper_rmd <- function(pkg, location, gh, template){

use_template("paper.Rmd", pkg = pkg, data = list(gh),
out_path = location)

# in case we want to inject some text in the Rmd, we can do that here
rmd <- readLines(file.path(pkg$path, location, "paper.Rmd"))
# use_template doesn't seem to work for this...
writeLines(rmd, file.path(pkg$path, location, "paper.Rmd"))
closeAllConnections()
}

use_vignette_rmd <- function(location, pkg, gh, template, vignette_yml = "vignette-yaml"){

pkg <- as.package(pkg)
check_suggested("rmarkdown")
add_desc_package(pkg, "Suggests", "knitr")
add_desc_package(pkg, "Suggests", "rmarkdown")
add_desc_package(pkg, "VignetteBuilder", "knitr")
use_directory("vignettes", pkg = pkg)
use_git_ignore("inst/doc", pkg = pkg)

template_path <- template_path_fn(template)
rmd <- readLines(template_path)
vignette_yml <- readLines(template_path_fn(vignette_yml))

# we inject a bit of vignette yml in our main paper.Rmd template:
rmd <- c(rmd[1:18], vignette_yml, rmd[19:32], paste0("\nlibrary(", pkg$package, ")"), rmd[33:length(rmd)])
# use_template doesn't seem to work for this...
writeLines(rmd, file(paste0(location, "/paper/paper.Rmd")))
closeAllConnections()

open_in_rstudio(paste0(location, "/paper/paper.Rmd"))
}
69 changes: 69 additions & 0 deletions R/core_use_circleci.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#' @name use_circleci
#' @aliases use_circleci
#' @title Add a circleci config file
#'
#' @description This will build the Docker container on the Circle-CI service.
#' The advantage of Circle-CI over Travis is that Circle-CI will freely work with
#' private GitHub repositories. Only the paid service from Travis will work
#' with private GitHub repositories. Before using this function you need
#' to create an account with Circle-CI, using your GitHub account. If you want
#' Circle-CI to run on a private GitHub repo, make sure you give Circle-CI
#' access to 'all repos' when you log in with your GitHub credentials.
#'
#' @param pkg defaults to the package in the current working directory
#' @param browse open a browser window to enable Circle-CI builds for the package automatically
#' @param docker_hub should circleci push to Docker Hub after a successful build?
#'
#' @importFrom curl has_internet
#' @importFrom utils browseURL
#' @export
use_circleci <- function(pkg = ".", browse = interactive(), docker_hub = TRUE) {
pkg <- as.package(pkg)

gh <- github_info(pkg$path)
circleci_url <- file.path("https://circleci.com/gh/", gh$username)

if(docker_hub){

use_template("circle.yml-with-docker-hub",
"circle.yml",
ignore = TRUE,
pkg = pkg,
data = gh,
out_path = "")

} else {

use_template("circle.yml-without-docker-hub",
"circle.yml",
ignore = TRUE,
pkg = pkg,
data = gh,
out_path = "")

}


message("Next: \n",
" * Add a circleci shield to your README.Rmd:\n",
"[![Circle-CI Build Status]",
"(https://circleci.com/gh/", gh$fullname, ".svg?style=shield&circle-token=:circle-token)]",
"(https://circleci.com/gh/", gh$fullname, ")\n",
" * Turn on circleci for your repo at ", circleci_url, "\n",
" and add your environment variables: DOCKER_EMAIL, ", "\n",
" DOCKER_USER, DOCKER_PASS.", "\n",
ifelse(docker_hub,
paste0(" * Your Docker container will be pushed to the Docker Hub", "\n",
" if the build completes successfully", "\n" ),
paste0(" * Your Docker container will be kept private and NOT be pushed to the Docker Hub", "\n" )))

if (browse) {
if(curl::has_internet()) {
utils::browseURL(circleci_url)
} else {
message("No internet connection. Can't open ", circleci_url)
}
}

invisible(TRUE)
}
Loading