diff --git a/NEWS.md b/NEWS.md index b94c3b38..1052227b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# pegboard 0.6.1 (2023-08-31) +# pegboard 0.6.1 (2023-09-06) NEW FEATURES ------------ diff --git a/README.Rmd b/README.Rmd index 9ac8b8ba..84977c14 100644 --- a/README.Rmd +++ b/README.Rmd @@ -8,6 +8,7 @@ output: github_document ```{r, include = FALSE} +options(width = 300) knitr::opts_chunk$set( collapse = TRUE, comment = "#|", @@ -31,16 +32,60 @@ knitr::opts_chunk$set( > > https://en.wikipedia.org/wiki/Pegboard -The {pegboard} package is a way to explore the Carpentries' lessons via their -XML representation. This package makes heavy use of rOpenSci's -[{tinkr}](https://docs.ropensci.org/tinkr/) and -[{xml2}](https://cran.r-project.org/package=xml2). +The {pegboard} package is part of [The Carpentries +Workbench](https://carpentries.github.io/workbench/) and it's main +functionality is to parse Markdown and R Markdown documents into XML +representations (via [{tinkr}](https://docs.ropensci.org/tinkr/)). By using XML, +we are able to easily arrange and parse the elements of the lessons which makes +two things possible: + + - parse and validate the lessons for structural markdown elements + - translate markdown syntax of Carpentries-style materials from the + [styles lesson infrastructure + (Jekyll-based)](https://github.com/carpentries/styles) to The Workbench + (Pandoc-based) (see the [lesson transition + tool](https://github.com/carpentries/lesson-transition#readme) for details) There are two [{R6}](https://cran.r-project.org/package=R6) objects in the package: - - Episode: stores the xml content of a single episode - - Lesson: stores all Episodes within a lesson + - Episode: stores the xml content of a single Markdown or R Markdown file. + This extends the the [`tinkr::yarn` + class](https://docs.ropensci.org/tinkr/reference/yarn.html). + - Lesson: stores all publishable markdown content as `Episodes` within a + lesson + +One simple usage is getting a summary of the content of an episode. Let's +investigate the contents of [the "Episode Structure" +episode](https://carpentries.github.io/sandpaper-docs/episodes.html) of the +Workbench documentation: + +```{r} +library("pegboard") +library("withr") +# Download the file we need ------------------------------------ +src <- "https://raw.githubusercontent.com/carpentries/sandpaper-docs/main/episodes/episodes.Rmd" +tmp <- local_tempfile(fileext = ".Rmd") +download.file(src, tmp) + +# Load episode +ep <- Episode$new(tmp) +# Summary ------------------------------------------------------------- +# confirm that we are using sandpaper and get a summary of the contents +ep$confirm_sandpaper()$summary() + +# Validation ---------------------------------------------------------- +# NOTE: a lot of invalid links because files do not exist outside of +# the lesson context +lnk <- ep$validate_links() +str(lnk, max.level = 1) +hdg <- ep$validate_headings() +str(hdg, max.level = 1) +div <- ep$validate_divs() +str(div, max.level = 1) +``` + + ## Installation @@ -58,74 +103,62 @@ install.packages("pegboard") ## Example -The first way to get started is to use the `get_lesson()` function, which will -use [{gert}](https://r-lib.github.io/gert/) to clone a lesson +To use {pegboard} in the context of The Workbench, you will need to have a +lesson handy. If you don't have one, you can use the `get_lesson()` function, +which will use [{gert}](https://r-lib.github.io/gert/) to clone a lesson repository to your computer. +(NOTE: this file was last run on `r Sys.time()`) + ```{r example, message = FALSE} -library(pegboard) -library(purrr) -library(xml2) -library(fs) +library("pegboard") +library("purrr") +library("xml2") +library("fs") d <- fs::file_temp(pattern = "PBREADME") -rng <- get_lesson("swcarpentry/r-novice-gapminder", path = d) +rng <- get_lesson("swcarpentry/r-novice-gapminder", path = d, jekyll = FALSE) rng -# Find all challenges -head(rng$challenges()) - -# Find all solutions -head(rng$solutions()) - -# Find all discussion blocks -head(rng$blocks(".discussion")) -``` - -## Manipulation - -At the moment, you can manipulate each episode in various ways. One of the ways -that will become useful in the future is translating the episode from using the -old and busted Jekyll syntax (e.g. using nested block quotes to create -specialized sections and writing questions/keypoints/objectives in the YAML) to -using a more intuitive system (currently being evaluated). For example, let's -say we wanted to transform an episode from Jekyll to using -[{sandpaper}](https://github.com/zkamvar/sandpaper#readme). This would involve -the following steps: - -1. transforming the block quotes to native or fenced div tags (or dovetail blocks) -1. converting code block decorators (`{: .language-r}`) and modify setup chunk -1. moving questions, objectives, and keypoints to the body of the document - -Doing this by hand would be a nightmare, but we've written {pegboard} in such a -way that will streamline this process +# Get a summary of all the elements in each episode +rng$summary() -First, let's inspect how the file looks at the moment: - -```{r inspect the file} -fun <- rng$episodes$`10-functions.Rmd` -fun$head(70) +# Validate lesson elements +rng$validate_links() +rng$validate_divs() +rng$validate_headings() # this is not run by default in sandpaper lessons ``` -Now, we can apply the transformation chain in the order we specifed: - -```{r chain} -fun$ - unblock()$ # transform block quotes - use_sandpaper()$ # convert code block decorators and modify setup chunk - move_questions()$ # ... - move_objectives()$ - move_keypoints()$ - head(70) +### Manipulation + +The XML contents of the lesson are contained within the `$body` element of the +Episode object and anything you do to that XML document is retained within the +object itself (see the [{tinkr} documentation](https://docs.ropensci.org/tinkr) +for more details): + +```{r} +ep1 <- rng$episodes[[1]] +ep1$body +ep1$head(20) # show the first 20 lines of the file +new_content <- r"{ + +#### NEW CONTENT + +Hello! This is **new markdown content** generated via the +[{pegboard}](https://carpentries.github.io/pegboard) package that will +appear above the objectives block! + +}" +ep1$add_md(new_content, where = 0L) +ep1$head(20) # the new content has been added to the top +ep1$headings[[1]] # the first heading is level 4. Let's change that using {xml2} +xml2::xml_set_attr(ep1$headings[[1]], "level", "2") +ep1$head(20) +ep1$headings[[1]] # the first heading is now level 2 +# write the file +ep1$write(fs::path_dir(ep1$path), format = "Rmd") +readLines(ep1$path, 20) ``` -## Reset -All changes can be reset to the initial state with the `$reset()` method: - -```{r reset} -fun$ - reset()$ - head(70) -``` diff --git a/README.md b/README.md index 2ec3b9ad..4670a017 100644 --- a/README.md +++ b/README.md @@ -23,16 +23,126 @@ status](https://github.com/carpentries/pegboard/workflows/R-CMD-check/badge.svg) > > -The {pegboard} package is a way to explore the Carpentries’ lessons via -their XML representation. This package makes heavy use of rOpenSci’s -[{tinkr}](https://docs.ropensci.org/tinkr/) and -[{xml2}](https://cran.r-project.org/package=xml2). +The {pegboard} package is part of [The Carpentries +Workbench](https://carpentries.github.io/workbench/) and it’s main +functionality is to parse Markdown and R Markdown documents into XML +representations (via [{tinkr}](https://docs.ropensci.org/tinkr/)). By +using XML, we are able to easily arrange and parse the elements of the +lessons which makes two things possible: + +- parse and validate the lessons for structural markdown elements +- translate markdown syntax of Carpentries-style materials from the + [styles lesson infrastructure + (Jekyll-based)](https://github.com/carpentries/styles) to The + Workbench (Pandoc-based) (see the [lesson transition + tool](https://github.com/carpentries/lesson-transition#readme) for + details) There are two [{R6}](https://cran.r-project.org/package=R6) objects in the package: -- Episode: stores the xml content of a single episode -- Lesson: stores all Episodes within a lesson +- Episode: stores the xml content of a single Markdown or R Markdown + file. This extends the the [`tinkr::yarn` + class](https://docs.ropensci.org/tinkr/reference/yarn.html). +- Lesson: stores all publishable markdown content as `Episodes` within a + lesson + +One simple usage is getting a summary of the content of an episode. +Let’s investigate the contents of [the “Episode Structure” +episode](https://carpentries.github.io/sandpaper-docs/episodes.html) of +the Workbench documentation: + +``` r +library("pegboard") +library("withr") +# Download the file we need ------------------------------------ +src <- "https://raw.githubusercontent.com/carpentries/sandpaper-docs/main/episodes/episodes.Rmd" +tmp <- local_tempfile(fileext = ".Rmd") +download.file(src, tmp) + +# Load episode +ep <- Episode$new(tmp) +# Summary ------------------------------------------------------------- +# confirm that we are using sandpaper and get a summary of the contents +ep$confirm_sandpaper()$summary() +#| sections headings callouts challenges solutions code output warning error images links +#| 16 33 29 7 7 35 1 0 0 4 21 + +# Validation ---------------------------------------------------------- +# NOTE: a lot of invalid links because files do not exist outside of +# the lesson context +lnk <- ep$validate_links() +#| ! There were errors in 12/23 links +#| ◌ Some linked internal files do not exist +#| +#| file9c2d53b7cd66.Rmd:38 [missing file]: [next episode](editing.md) +#| file9c2d53b7cd66.Rmd:51 [missing file]: [the Introduction](introduction.md) +#| file9c2d53b7cd66.Rmd:203 [missing file]: [The Workbench Component Guide](component-guide.md) +#| file9c2d53b7cd66.Rmd:780 [missing file]: [the setup page](../learners/setup.md) +#| file9c2d53b7cd66.Rmd:796 [missing file]: [another episode (e.g. introduction)](introduction.md) +#| file9c2d53b7cd66.Rmd:797 [missing file]: [the home page](../index.md) +#| file9c2d53b7cd66.Rmd:798 [missing file]: [the setup page](../learners/setup.md) +#| file9c2d53b7cd66.Rmd:799 [missing file]: [the "line length" section in the style guide](../learners/style.md#line-length) +#| file9c2d53b7cd66.Rmd:805 [missing file]: [the style guide](../learners/style.md) +#| file9c2d53b7cd66.Rmd:825 [missing file]: [internal links](../episodes/episodes.Rmd#internal-links) +#| file9c2d53b7cd66.Rmd:860 [missing file]: [Hex sticker for The Carpentries](fig/carpentries-hex-blue.svg) +#| file9c2d53b7cd66.Rmd:902 [missing file]: [Example of Wrapped Alt Text (with apologies to William Carlos Williams)](fig/freezer.png) +str(lnk, max.level = 1) +#| 'data.frame': 25 obs. of 26 variables: +#| $ scheme : chr "" "" "" "" ... +#| $ server : chr "" "" "" "" ... +#| $ port : int NA NA NA NA NA NA NA NA NA NA ... +#| $ user : chr "" "" "" "" ... +#| $ path : chr "editing.md" "introduction.md" "" "component-guide.md" ... +#| $ query : chr "" "" "" "" ... +#| $ fragment : chr "" "" "callout-blocks" "" ... +#| $ orig : chr "editing.md" "introduction.md" "#callout-blocks" "component-guide.md" ... +#| $ text : chr "next episode" "the Introduction" "the next section" "The Workbench Component Guide" ... +#| $ alt : chr NA NA NA NA ... +#| $ title : chr "" "" "" "" ... +#| $ type : chr "link" "link" "link" "link" ... +#| $ rel : chr NA NA NA NA ... +#| $ anchor : logi FALSE FALSE FALSE FALSE FALSE FALSE ... +#| $ sourcepos : int 38 51 168 203 318 327 468 545 550 630 ... +#| $ filepath : chr "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" ... +#| $ node :List of 25 +#| ..- attr(*, "class")= chr "AsIs" +#| $ known_protocol : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ enforce_https : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ internal_anchor : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ internal_file : logi FALSE FALSE TRUE FALSE TRUE TRUE ... +#| $ internal_well_formed: logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ all_reachable : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ img_alt_text : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ descriptive : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ link_length : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +hdg <- ep$validate_headings() +str(hdg, max.level = 1) +#| 'data.frame': 33 obs. of 10 variables: +#| $ heading : chr "Introduction" "Buoyant Barnacle" "Creating A New Episode" "What is the .Rmd extension?" ... +#| $ level : int 2 3 2 3 2 3 3 3 2 3 ... +#| $ pos : int 29 48 63 80 117 126 143 156 196 200 ... +#| $ node :List of 33 +#| ..- attr(*, "class")= chr "AsIs" +#| $ first_heading_is_second_level: logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ greater_than_first_level : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ are_sequential : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ have_names : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ are_unique : logi TRUE TRUE TRUE TRUE TRUE TRUE ... +#| $ path : chr "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" ... +div <- ep$validate_divs() +#| ! There were errors in 1/29 fenced divs +#| ◌ The Carpentries Workbench knows the following div types callout, objectives, questions, challenge, prereq, checklist, solution, hint, discussion, testimonial, keypoints, instructor, spoiler +#| +#| file9c2d53b7cd66.Rmd:457 [unknown div] empty-div +str(div, max.level = 1) +#| 'data.frame': 29 obs. of 5 variables: +#| $ path : chr "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" "file9c2d53b7cd66.Rmd" ... +#| $ div : chr "questions" "objectives" "prereq" "callout" ... +#| $ pb_label: chr "div-1-questions" "div-2-objectives" "div-3-prereq" "div-4-callout" ... +#| $ pos : int 9 20 46 78 141 198 226 243 253 272 ... +#| $ is_known: logi TRUE TRUE TRUE TRUE TRUE TRUE ... +``` ## Installation @@ -50,18 +160,21 @@ install.packages("pegboard") ## Example -The first way to get started is to use the `get_lesson()` function, -which will use [{gert}](https://r-lib.github.io/gert/) to clone a lesson -repository to your computer. +To use {pegboard} in the context of The Workbench, you will need to have +a lesson handy. If you don’t have one, you can use the `get_lesson()` +function, which will use [{gert}](https://r-lib.github.io/gert/) to +clone a lesson repository to your computer. + +(NOTE: this file was last run on 2023-09-06 08:45:54.227933) ``` r -library(pegboard) -library(purrr) -library(xml2) -library(fs) +library("pegboard") +library("purrr") +library("xml2") +library("fs") d <- fs::file_temp(pattern = "PBREADME") -rng <- get_lesson("swcarpentry/r-novice-gapminder", path = d) +rng <- get_lesson("swcarpentry/r-novice-gapminder", path = d, jekyll = FALSE) rng #| #| Public: @@ -70,7 +183,7 @@ rng #| challenges: function (path = FALSE, graph = FALSE, recurse = TRUE) #| clone: function (deep = FALSE) #| episodes: list -#| extra: NULL +#| extra: list #| files: active binding #| get: function (element = NULL, collection = "episodes") #| handout: function (path = NULL, solution = FALSE) @@ -78,10 +191,11 @@ rng #| isolate_blocks: function () #| load_built: function () #| n_problems: active binding -#| path: /tmp/RtmpUQWpSD/PBREADME1b72117285a2e/swcarpentry--r-nov ... +#| overview: FALSE +#| path: /tmp/RtmpBNM7Jl/PBREADME9c2d5fd860a1/swcarpentry--r-novi ... #| reset: function () -#| rmd: TRUE -#| sandpaper: FALSE +#| rmd: FALSE +#| sandpaper: TRUE #| show_problems: active binding #| solutions: function (path = FALSE) #| summary: function (collection = "episodes") @@ -92,386 +206,237 @@ rng #| Private: #| deep_clone: function (name, value) -# Find all challenges -head(rng$challenges()) -#| $`01-rstudio-intro.Rmd` -#| {xml_nodeset (5)} -#| [1] \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n +#| 1 01-rstudio-intro.Rmd 28 28 19 5 5 47 1 0 0 2 6 +#| 2 02-project-intro.Rmd 12 19 12 5 1 4 0 0 0 1 3 +#| 3 03-seeking-help.Rmd 15 15 11 3 3 12 0 0 0 0 7 +#| 4 04-data-structures-part1.Rmd 2 50 31 9 15 77 0 0 0 0 1 +#| 5 05-data-structures-part2.Rmd 15 15 12 4 4 33 0 0 0 0 3 +#| 6 06-data-subsetting.Rmd 33 34 26 8 8 76 0 0 0 2 0 +#| 7 07-control-flow.Rmd 15 15 17 5 5 36 0 0 0 0 0 +#| 8 08-plot-ggplot2.Rmd 20 20 18 6 6 23 0 0 0 0 12 +#| 9 09-vectorization.Rmd 11 11 14 4 4 24 0 0 0 0 1 +#| 10 10-functions.Rmd 20 21 19 5 5 28 0 0 0 0 12 +#| 11 11-writing-data.Rmd 6 6 7 2 2 11 0 0 0 0 0 +#| 12 12-plyr.Rmd 8 8 10 3 3 17 0 0 0 2 1 +#| 13 13-dplyr.Rmd 18 18 11 3 3 30 0 0 0 3 6 +#| 14 14-tidyr.Rmd 10 10 9 3 3 16 0 0 0 4 5 +#| 15 15-knitr-markdown.Rmd 22 22 13 4 4 9 0 0 0 2 18 +#| 16 16-wrap-up.Rmd 9 9 4 0 0 1 0 0 0 0 1 -# Find all solutions -head(rng$solutions()) -#| $`01-rstudio-intro.Rmd` -#| {xml_nodeset (5)} -#| [1] \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n +#| [1] +#| [2] \n ::::::::::::::::::::::::::::::::::::::: objectives\n +#| [3] \n \n \n Describe the purpose and use of each pane in the RStudio IDE\n \n \n \n ::::::::::::::::::::::::::::::::::::::::::::::::::\n +#| [5] +#| [6] +#| [7] \n :::::::::::::::::::::::::::::::::::::::: questions\n +#| [8] \n \n \n How to find your way around RStudio?\n \n \n \ ... +#| [9] \n ::::::::::::::::::::::::::::::::::::::::::::::::::\n +#| [10] +#| [11] +#| [12] \n Motivation\n +#| [13] \n Science is a multi-step process: once you've designed an experiment and collected\n \n data, the real fun begins! This lesson will te ... +#| [14] \n Before Starting The Workshop\n +#| [15] \n Please ensure you have the latest version of R and RStudio installed on your machine. This is important, as some packages used in the workshop may not install correctly (or at all) if R is not up to dat ... +#| [16] \n \n \n \n Download and inst ... +#| [17] \n Introduction to RStudio\n +#| [18] \n Welcome to the R portion of the Software Carpentry workshop.\n +#| [19] \n Throughout this lesson, we're going to teach you some of the fundamentals of\n \n the R language as well as some best practices for o ... +#| [20] \n We'll be using RStudio: a free, open-source R Integrated Development\n \n Environment (IDE). It provides a built-in editor, works on ... +#| ... +ep1$head(20) # show the first 20 lines of the file #| --- -#| title: Functions Explained +#| title: Introduction to R and RStudio #| teaching: 45 -#| exercises: 15 -#| questions: -#| - "How can I write a new function in R?" -#| objectives: -#| - "Define a function that takes arguments." -#| - "Return a value from a function." -#| - "Check argument conditions with `stopifnot()` in functions." -#| - "Test a function." -#| - "Set default values for function arguments." -#| - "Explain why we should divide programs into small, single-purpose functions." -#| keypoints: -#| - "Use `function` to define a new function in R." -#| - "Use parameters to pass values into functions." -#| - "Use `stopifnot()` to flexibly check function arguments in R." -#| - "Load functions into programs using `source()`." +#| exercises: 10 #| source: Rmd #| --- #| -#| ```{r, include=FALSE} -#| source("../bin/chunk-options.R") -#| knitr_fig_path("10-") -#| # Silently load in the data so the rest of the lesson works -#| gapminder <- read.csv("data/gapminder_data.csv", header=TRUE) -#| ``` -#| -#| If we only had one data set to analyze, it would probably be faster to load the -#| file into a spreadsheet and use that to plot simple statistics. However, the -#| gapminder data is updated periodically, and we may want to pull in that new -#| information later and re-run our analysis again. We may also obtain similar data -#| from a different source in the future. -#| -#| In this lesson, we'll learn how to write a function so that we can repeat -#| several operations with a single command. -#| -#| > ## What is a function? -#| > -#| > Functions gather a sequence of operations into a whole, preserving it for -#| > ongoing use. Functions provide: -#| > -#| > - a name we can remember and invoke it by -#| > - relief from the need to remember the individual operations -#| > - a defined set of inputs and expected outputs -#| > - rich connections to the larger programming environment -#| > -#| > As the basic building block of most programming languages, user-defined -#| > functions constitute "programming" as much as any single abstraction can. If -#| > you have written a function, you are a computer programmer. -#| > -#| {: .callout} -#| -#| ## Defining a function -#| -#| Let's open a new R script file in the `functions/` directory and call it -#| functions-lesson.R. -#| -#| The general structure of a function is: +#| ::::::::::::::::::::::::::::::::::::::: objectives #| -#| ```{r} -#| my_function <- function(parameters) { -#| # perform action -#| # return value -#| } -#| ``` +#| - Describe the purpose and use of each pane in the RStudio IDE +#| - Locate buttons and options in the RStudio IDE +#| - Define a variable +#| - Assign data to a variable +#| - Manage a workspace in an interactive R session +#| - Use mathematical and comparison operators +#| - Call functions +#| - Manage packages #| -#| Let's define a function `fahr_to_kelvin()` that converts temperatures from -#| Fahrenheit to Kelvin: -``` +#| :::::::::::::::::::::::::::::::::::::::::::::::::: +new_content <- r"{ -Now, we can apply the transformation chain in the order we specifed: +#### NEW CONTENT -``` r -fun$ - unblock()$ # transform block quotes - use_sandpaper()$ # convert code block decorators and modify setup chunk - move_questions()$ # ... - move_objectives()$ - move_keypoints()$ - head(70) +Hello! This is **new markdown content** generated via the +[{pegboard}](https://carpentries.github.io/pegboard) package that will +appear above the objectives block! + +}" +ep1$add_md(new_content, where = 0L) +ep1$head(20) # the new content has been added to the top #| --- -#| title: Functions Explained +#| title: Introduction to R and RStudio #| teaching: 45 -#| exercises: 15 +#| exercises: 10 #| source: Rmd #| --- #| -#| ```{r, include=FALSE} -#| gapminder <- read.csv("data/gapminder_data.csv", header = TRUE) -#| ``` -#| -#| ::::::::::::::::::::::::::::::::::::::: objectives -#| -#| - Define a function that takes arguments. -#| - Return a value from a function. -#| - Check argument conditions with `stopifnot()` in functions. -#| - Test a function. -#| - Set default values for function arguments. -#| - Explain why we should divide programs into small, single-purpose functions. -#| -#| :::::::::::::::::::::::::::::::::::::::::::::::::: -#| -#| :::::::::::::::::::::::::::::::::::::::: questions -#| -#| - How can I write a new function in R? -#| -#| :::::::::::::::::::::::::::::::::::::::::::::::::: -#| -#| If we only had one data set to analyze, it would probably be faster to load the -#| file into a spreadsheet and use that to plot simple statistics. However, the -#| gapminder data is updated periodically, and we may want to pull in that new -#| information later and re-run our analysis again. We may also obtain similar data -#| from a different source in the future. -#| -#| In this lesson, we'll learn how to write a function so that we can repeat -#| several operations with a single command. -#| -#| ::::::::::::::::::::::::::::::::::::::::: callout -#| -#| ## What is a function? -#| -#| Functions gather a sequence of operations into a whole, preserving it for -#| ongoing use. Functions provide: -#| -#| - a name we can remember and invoke it by -#| - relief from the need to remember the individual operations -#| - a defined set of inputs and expected outputs -#| - rich connections to the larger programming environment +#| #### NEW CONTENT #| -#| As the basic building block of most programming languages, user-defined -#| functions constitute "programming" as much as any single abstraction can. If -#| you have written a function, you are a computer programmer. +#| Hello! This is **new markdown content** generated via the +#| [{pegboard}](https://carpentries.github.io/pegboard) package that will +#| appear above the objectives block! #| +#| ::::::::::::::::::::::::::::::::::::::: objectives #| -#| :::::::::::::::::::::::::::::::::::::::::::::::::: -#| -#| ## Defining a function -#| -#| Let's open a new R script file in the `functions/` directory and call it -#| functions-lesson.R. -#| -#| The general structure of a function is: -#| -#| ```{r} -#| my_function <- function(parameters) { -#| # perform action -#| # return value -#| } -#| ``` -``` - -## Reset - -All changes can be reset to the initial state with the `$reset()` -method: - -``` r -fun$ - reset()$ - head(70) +#| - Describe the purpose and use of each pane in the RStudio IDE +#| - Locate buttons and options in the RStudio IDE +#| - Define a variable +#| - Assign data to a variable +#| - Manage a workspace in an interactive R session +ep1$headings[[1]] # the first heading is level 4. Let's change that using {xml2} +#| {xml_node} +#| +#| [1] NEW CONTENT +xml2::xml_set_attr(ep1$headings[[1]], "level", "2") +ep1$head(20) #| --- -#| title: Functions Explained +#| title: Introduction to R and RStudio #| teaching: 45 -#| exercises: 15 -#| questions: -#| - "How can I write a new function in R?" -#| objectives: -#| - "Define a function that takes arguments." -#| - "Return a value from a function." -#| - "Check argument conditions with `stopifnot()` in functions." -#| - "Test a function." -#| - "Set default values for function arguments." -#| - "Explain why we should divide programs into small, single-purpose functions." -#| keypoints: -#| - "Use `function` to define a new function in R." -#| - "Use parameters to pass values into functions." -#| - "Use `stopifnot()` to flexibly check function arguments in R." -#| - "Load functions into programs using `source()`." +#| exercises: 10 #| source: Rmd #| --- #| -#| ```{r, include=FALSE} -#| source("../bin/chunk-options.R") -#| knitr_fig_path("10-") -#| # Silently load in the data so the rest of the lesson works -#| gapminder <- read.csv("data/gapminder_data.csv", header=TRUE) -#| ``` -#| -#| If we only had one data set to analyze, it would probably be faster to load the -#| file into a spreadsheet and use that to plot simple statistics. However, the -#| gapminder data is updated periodically, and we may want to pull in that new -#| information later and re-run our analysis again. We may also obtain similar data -#| from a different source in the future. -#| -#| In this lesson, we'll learn how to write a function so that we can repeat -#| several operations with a single command. +#| ## NEW CONTENT #| -#| > ## What is a function? -#| > -#| > Functions gather a sequence of operations into a whole, preserving it for -#| > ongoing use. Functions provide: -#| > -#| > - a name we can remember and invoke it by -#| > - relief from the need to remember the individual operations -#| > - a defined set of inputs and expected outputs -#| > - rich connections to the larger programming environment -#| > -#| > As the basic building block of most programming languages, user-defined -#| > functions constitute "programming" as much as any single abstraction can. If -#| > you have written a function, you are a computer programmer. -#| > -#| {: .callout} +#| Hello! This is **new markdown content** generated via the +#| [{pegboard}](https://carpentries.github.io/pegboard) package that will +#| appear above the objectives block! #| -#| ## Defining a function -#| -#| Let's open a new R script file in the `functions/` directory and call it -#| functions-lesson.R. -#| -#| The general structure of a function is: -#| -#| ```{r} -#| my_function <- function(parameters) { -#| # perform action -#| # return value -#| } -#| ``` +#| ::::::::::::::::::::::::::::::::::::::: objectives #| -#| Let's define a function `fahr_to_kelvin()` that converts temperatures from -#| Fahrenheit to Kelvin: +#| - Describe the purpose and use of each pane in the RStudio IDE +#| - Locate buttons and options in the RStudio IDE +#| - Define a variable +#| - Assign data to a variable +#| - Manage a workspace in an interactive R session +ep1$headings[[1]] # the first heading is now level 2 +#| {xml_node} +#| +#| [1] NEW CONTENT +# write the file +ep1$write(fs::path_dir(ep1$path), format = "Rmd") +readLines(ep1$path, 20) +#| [1] "---" "title: Introduction to R and RStudio" "teaching: 45" "exercises: 10" +#| [5] "source: Rmd" "---" "" "## NEW CONTENT" +#| [9] "" "Hello! This is **new markdown content** generated via the" "[{pegboard}](https://carpentries.github.io/pegboard) package that will" "appear above the objectives block!" +#| [13] "" "::::::::::::::::::::::::::::::::::::::: objectives" "" "- Describe the purpose and use of each pane in the RStudio IDE" +#| [17] "- Locate buttons and options in the RStudio IDE" "- Define a variable" "- Assign data to a variable" "- Manage a workspace in an interactive R session" ```