---
title: "Teaching with livelink"
vignette: >
  %\VignetteIndexEntry{Teaching with livelink}
  %\VignetteEngine{quarto::html}
  %\VignetteEncoding{UTF-8}
format:
  html:
    embed-resources: true
knitr:
  opts_chunk:
    collapse: true
    comment: '#>'
---

```{=html}
<style>
.ll-fig{display:block;margin:1.5rem auto;max-width:100%;height:auto}
.ll-dark{display:none}
@media (prefers-color-scheme:dark){.ll-light{display:none}.ll-dark{display:block}}
[data-bs-theme=light] .ll-light{display:block}
[data-bs-theme=light] .ll-dark{display:none}
[data-bs-theme=dark] .ll-light{display:none}
[data-bs-theme=dark] .ll-dark{display:block}
</style>
```

```{r setup}
#| include: false
library(livelink)
```

The hardest part of teaching R is not R. It is the twenty minutes at the start of a
workshop spent installing R, then RStudio, then a package that fails to compile on
one student's laptop.

livelink sidesteps that. A link opens a working R session in the browser, with your
code already in the editor. Nothing to install, nothing to configure, and it works on
a school Chromebook.

## Exercise and solution pairs

`webr_repl_exercise()` is built for the most common teaching shape: give students a
scaffold with the answer removed, and keep the worked solution behind a second link.

![One call returns two links. They differ by a single flag: the solution carries `a` for autorun and computes the answer on arrival, while the exercise waits.](../man/figures/exercise-light.svg){.ll-fig .ll-light}
![](../man/figures/exercise-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

```{r}
exercise <- "
# Exercise: what is the mean mpg of the cars in mtcars?
# Replace the 0 below with your answer.

mean_mpg <- 0
print(mean_mpg)
"

solution <- "
# Solution
mean_mpg <- mean(mtcars$mpg)
print(mean_mpg)
"

links <- webr_repl_exercise(exercise, solution, "mean_mpg")
links
```

These are written as plain strings on purpose. An exercise is mostly its instructions,
and those live in comments, so a braced `{ }` expression would drop them the moment
these notes are knitted. [Links inside
documents](links-in-documents.html#why-not-a-braced-expression) explains why.

The two links differ in one deliberate way: the solution **autoruns** and the exercise
does not. Students landing on the exercise see the code sitting there waiting for
them. Students landing on the solution see the answer already computed.

```{r}
links$exercise$autorun
links$solution$autorun
```

Hand out the exercise link in class, and hold the solution link back until afterwards, or
put it behind a collapsed callout in your notes.

```{r}
repl_urls(links)
```

## Choosing what students see

A full webR session shows an editor, a plot pane, a file browser, and a terminal. For
a first-year class that is a lot of surface area, and the terminal in particular
invites students to wander off.

`panels` controls which of them appear.

![webR has four panels. `panels` names the ones you want, and the rest never appear.](../man/figures/panels-light.svg){.ll-fig .ll-light}
![](../man/figures/panels-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

```{r}
# A focused exercise: just write code and see the plot
webr_repl_link("plot(1:10)", panels = c("editor", "plot"))
```

```{r}
#| eval: false
# The full environment, for a project week
webr_repl_link(code, panels = c("editor", "plot", "files", "terminal"))
```

For a lecture demo, where students should see the *result* and not the machinery,
combine `autorun` with a plot-only view:

```{r}
webr_repl_link(
  "hist(rnorm(1000), col = 'steelblue', main = 'The central limit theorem, again')",
  autorun = TRUE,
  panels  = "plot"
)
```

Only `.R` files can autorun. Ask for it on something else and livelink tells you
rather than quietly producing a link that does nothing:

```{r}
#| error: true
webr_repl_link("some data", filename = "data.csv", autorun = TRUE)
```

## A whole folder of scripts

Course material tends to live as a directory of scripts, and livelink gives you two
ways to turn that folder into links. Which you want comes down to a single question:
are the scripts **independent**, or **parts of one thing**?

`webr_repl_directory()` gives each script *its own* link. That is the right call for a
folder of standalone exercises: one link per file, each opening just that script.

![Each script becomes its own link, named after the file. That is the mirror image of `webr_repl_project()`, which bundles a whole folder into one link.](../man/figures/course-light.svg){.ll-fig .ll-light}
![](../man/figures/course-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

```{r}
# A small course directory
course <- file.path(tempdir(), "course")
dir.create(course, showWarnings = FALSE)
writeLines("plot(1:10)",           file.path(course, "01-plotting.R"))
writeLines("mean(mtcars$mpg)",     file.path(course, "02-summaries.R"))
writeLines("lm(mpg ~ wt, mtcars)", file.path(course, "03-models.R"))

links <- webr_repl_directory(course, panels = c("editor", "plot"))
links
```

The result is named by file, so it drops straight into a table of contents:

```{r}
urls <- repl_urls(links)
cat(sprintf("- [%s](%s)", names(urls), urls), sep = "\n")
```

Use `pattern` to pick out a subset, say the exercises but not the solutions:

```{r}
webr_repl_directory(course, pattern = "^0[12]")
```

### One link per file, or one link for the folder?

`webr_repl_project()` is the other half of the pair. It packs several files into a
*single* link, so a script that `source()`s its neighbour still finds it once webR
unpacks them side by side. Reach for it when the files belong together rather than
standing alone.

The two are mirror images, and the table says which to reach for:

| You want | Call |
|---|---|
| each script openable on its own | `webr_repl_directory(dir)` |
| the whole folder bundled into one link | `webr_repl_directory(dir, single_link = TRUE)` |
| a hand-picked set of files bundled into one link | `webr_repl_project(files)` |

`single_link = TRUE` is the bridge between them: point it at a folder and it bundles
the lot into one link, exactly as `webr_repl_project()` would, without your having to
list the files by hand.

```{r}
# the same course folder, as one bundled link instead of three
webr_repl_directory(course, single_link = TRUE, panels = c("editor", "plot"))
```

## Embedding links in your notes

If you write course notes in Quarto or R Markdown, you do not have to build the link
in one chunk and paste the URL into another. livelink plugs into knitr, so a chunk can
carry its own link.

![A `livelink` chunk renders as the code plus a link that runs it, comments and all. A braced expression cannot manage that in a knitted document.](../man/figures/engine-light.svg){.ll-fig .ll-light}
![](../man/figures/engine-dark.svg){.ll-fig .ll-dark aria-hidden="true"}

Add `livelink: true` to an ordinary `r` chunk. It runs as it always did, the plot
appears in your notes, and a link is added underneath. Here it is, running in this
very vignette:

```{r}
#| livelink: true
#| autorun: true
#| panels: ["editor", "plot"]
# Load the data
data(mtcars)
plot(mtcars$mpg, mtcars$wt)   # a comment students will actually see
```

Students read the result *and* get to go and poke at it. Follow the link: the comments
are still there, which they would not be had you written `webr_repl_link({ ... })`.

For a folder of course notes, set it once and let every chunk carry a link:

```{r}
#| eval: false
knitr::opts_chunk$set(livelink = TRUE, autorun = TRUE)
```

[Links inside documents](links-in-documents.html) covers the rest: the engine, for code
your notes should not run, every chunk option, and why `echo` is not what stands between
you and a link.

## Collecting work back in

Students send you links. `decode_webr_link()` accepts a vector of them and writes each
into its own directory, so a stack of submissions becomes a folder you can grade.

```{r}
submissions <- c(
  as.character(webr_repl_link("mean(mtcars$mpg)",   filename = "student_a.R")),
  as.character(webr_repl_link("median(mtcars$mpg)", filename = "student_b.R"))
)

decode_webr_link(submissions, output_dir = file.path(tempdir(), "submissions"))
```

If you would rather read the code than write it to disk, `preview_webr_link()` shows
you a submission without touching your filesystem at all, which is the safer default
when the code came from someone else.
