Rprimo documents and notebooks
▶Open Rprimo

Rprimodocuments and notebooks

A document is text to read beside the editor: a worksheet, a chapter of notes, an R Markdown file, a Jupyter notebook, a short course. It opens on a tab of its own, and its code examples run right where they are written, in the same R as your own code. This page is about reading one, writing one, and getting one out again. The handbook covers the rest of the editor.

This page is a document itself. Open it in the editor and every example on it can be run with Run here, which is the quickest way to see what the sections below describe.

If a teacher sent you a document, section 1 is all you need. If you teach, sections 2 to 4 say how an R Markdown or Quarto file, a notebook, or a Markdown file of your own becomes a document, and how to hand it out.

Contents#

  1. 1Reading a document
  2. 2Notebooks, R Markdown and Quarto
  3. 3Writing a document
  4. 4Update outputs, and getting a document out
  5. 5Code in the other language

1Reading a document#

How one arrives#

  • New. The + at the end of the file tabs opens New file. Pick Document, give it a name such as notes.md, and start from a page to fill in or from the example document. The new document opens in the Document tab, where Edit changes its Markdown. Section 3 says what goes in it. The example document, "A year in numbers", is also on the homepage, and opens from this link: the example document.
  • A link. A link whose address ends in #md=… or #mdz=… carries the whole document, pictures and data files included. A link ending in #mdu=/path/notes.md names a Markdown file on the Rprimo site, which the editor fetches; that is how the drawing reference and this page open. Nothing is uploaded either way: the document is in the link, or on the site. Either opens as a project of its own, and the same link again is that project.
  • A file. Drag a .md file onto the editor, or pick one with Open, the folder at the end of the file tabs (or, for a project of its own, From files or a ZIP… in the projects list). An R Markdown file (.Rmd), a Quarto file (.qmd) or an R Jupyter notebook (.ipynb) opens the same way; see section 2. The file joins your project's files as a chapter of its document, in its place by the order of the names; your own files stay as they are, and Undo takes the file out again.
  • A folder. Drag a folder onto the editor. Its files become files of your project, and the Markdown, Quarto, R Markdown and notebook files at its top are the chapters of the document, in the order of their names, with numbers counted as numbers, so 2-loops.md comes before 10-classes.md. Pictures the Markdown shows come with it, and so does everything else in the folder, such as the program an exercise asks you to write: they are among your files as usual.
  • A zip. A zip of such a folder opens as the folder would, and so does a repository downloaded from GitHub as a ZIP: dropped on the project button, as a project of its own, or on a project that is still its empty file. On a project with something in it, a zip is a file, packed, until Unpack on its tab.

The status line under the editor says what was opened. A document is not kept apart from your project: its files are among yours, and everything below about files holds for them.

The document tab#

The document takes the place of the editor, and its tab stands first in the row of file tabs, with the document's title on it: its first # heading; without one, its first heading of any level, or else the file's name. Click a file tab to go to your code, and the document's tab to come back to it. The tab stays for as long as the document is open. The document's files do not appear among your file tabs: they are shown only here. They are listed in the project's tree (the list the project button opens), where you can rename or delete one, and leave it out of the document with its book (open: a chapter; closed: not).

Each # heading starts a chapter, and one chapter is on screen at a time. ☰ at the top left shows or hides the contents: every chapter, and the sections of the one you are reading. Under each chapter, two buttons go to the chapter before and the one after, each with its title. On a narrow screen the contents lie over the text and close again once you pick something.

</> on the tab, beside the pencil, takes the code of every cell that runs off the page, its title bar and buttons with it, and puts it back when pressed again: what is left is the text and what the cells printed and drew. Exercises, and code that is only there to be read, stay. A cell that ends in an error is shown again, with its code. The browser remembers your choice for that document. The chevron at the left of a cell's title bar folds just that cell's code under its title bar, which keeps its buttons.

Printing (Ctrl/Cmd+P) prints the document as you see it, every chapter, without the buttons and without the code you have hidden. With a file open in the editor instead, it prints that file, with its lines numbered and coloured as in the editor.

Running the examples#

Every R example in a document that can run has buttons in its title bar.

  • Run here runs the example where it is. What it prints goes to the Output tab under the editor: lines for the console print below what is already there, each line shown after > as at the prompt, while a program clears the tab first, as Run does. A plot goes to Plots, a plotly chart too (left on a line of its own, print()ed, or from ggplotly()), drawn there as a live chart you can point at and zoom, never under the cell, and interactive output, a DT table or a leaflet map, in a frame of its own; a drawing goes to Draw, a View() to Tables. While it runs, the button turns into Stop.
  • Console, on lines meant for the console, puts them at the console prompt instead, where Enter runs one at a time.
  • Open, on a program, opens it in the editor, where you can record it and step through it. One with notes on what to watch is recorded as it opens. Your own program files go away for the moment, while the document stays, and Undo brings them back.
  • Watch, on a program with notes on what to watch, records it where it is and plays it back under its code: the line it stands on is lit in the frame, and the tape below walks the run. Drag the tape, use Back and Step, or the arrow keys. The note for that moment is above the tape, and under it are the variables, with the ones the step changed marked, and what the program had printed by then. Open on the player takes the example to the editor at that same step, where the call stack and every variable are. Your own files and tabs stay as they are, as with Run here.
  • Copy copies the code.

There are two kinds of example. Lines for the console are the cells of a notebook, or the chunks of an R Markdown file: they run in the console's names, so what one defines, the next can use, and you can look at all of it at the prompt. Here are two:

r>Console
prices <- c(4.50, 2.20, 3.80)
r>Console
total <- sum(prices)
cat(sprintf("Total: %.2f\n", total))
output
Total: 10.50

The box under the second, captioned output, is what that cell printed when the document was written. It stays as it is: when you run the cell, its output goes to the Output tab, not under the cell.

A program is a whole program, main.R and any files that come with it. Run here runs it as Run would run your own, among your files, with the example's files laid over them, and leaves your tabs as they are. Afterwards its variables are the console's, in place of the ones you had made there, as after a Run.

Cells catch up#

Press Run here on the second cell above before running the first, and it still works. A cell first runs every cell above it that has not run yet, in the order they stand, and then itself. In the Output tab a thin line sets off what the cells above printed from what the one you pressed printed; hold the pointer on a line to see which is which.

This goes back to the start of the file the cell is in, to a program example, or to a cell marked fresh by its author, whichever comes first; a program example or a fresh cell there runs too, if it has not run yet. It never goes into another file: each file of a document runs on its own, as each page of a Jupyter Book does, so a chapter file that needs an import or some data sets them up itself. The chapters of one file, its # headings, run as one. A cell that has run wears a small dot beside its buttons; one that ended in an error wears a red one. When a cell above ends in an error, the cells below it do not run, and the status line says which one it was. The dots go when the console's names go: after your own Run, after a program example, or after %reset at the console, every cell counts as not run again.

Stopping#

Stop stops an example where it stands, as the Run button's Stop does, and what it had worked out so far stays in the console's names. Run here on another example, or a line of the document, stops the one that is running first. A loop that does not stop at once is waited for; if it does not react to Stop at all, the status line offers Restart R, which loses the console's names, and with them the dots.

Changing an example#

Click into an example and you can change its code, there in the document. Ctrl/Cmd+Enter runs it. Enter makes a new line, as in the editor; Shift+Enter runs the line the caret is on: in console lines it then goes on to the next, as Enter at the prompt does, and in a program it runs the line at the console and in your project's folder, where the example's own extra files are not. Escape leaves the code. A changed example is a draft: it says edited, lifts off the page with a shadow, and is kept with your project, so it survives a reload, but it is not in the document's file yet. The tick in its title bar takes the draft into the file, then runs that cell and every cell after it again, in order (cells above that have not run run first), and saves each one's output under it as it is made, so the document never shows an output its code did not make. Discard drops the draft and brings the document's code back; Undo puts it back. A cell that ends in an error stops the run there with the error saved under it; the cells after it show Out of date in place of their old output, with a tick of their own that runs them again. Stop stops the run the same way. A cell further down that holds a draft of its own runs that draft, which is not in the file, so it keeps Out of date until its own tick. A tab that only shows the project cannot change cells. If the cell's place in its file cannot be found again, the tick is off and its title says why.

The document's files#

The document is the top-level Markdown, Quarto, R Markdown and notebook files of your project: .md, .markdown, .qmd, .Rmd and .ipynb, not in a folder and not starting with . or _. Together they are one document, a chapter for each # heading, in the order of the files' names (numbers as numbers; index.qmd and index.Rmd first). A file without a # heading is one chapter, titled from its name. The pictures and data a document carries, the helpers.R a notebook sources and the data/scores.csv its cells read, are files of the project too, in the tabs, in a download, in a link and in a folder like any file. Dropping another Markdown file adds a chapter. A link that carries a document opens it as a project of its own, so its files never meet yours; the same link again is the same project, and Start over puts the document back as the site has it now.

Edit, Done and ×#

The pencil on the document's tab opens the Markdown of the file the chapter you are reading is in, for editing, at that chapter (a Quarto, R Markdown or MyST file opens at its top). Change anything; a draft you have in an example stays a draft, and finds its cell again afterwards. The pencil stays pressed while you edit; pressing it again, or Ctrl/Cmd+Enter, shows the document again with your changes, which are in the file: the file in your project has the same text, and Undo takes the whole editing back as one step. On a chapter that comes from a notebook the pencil shows the notebook as MyST text, as Jupyter Book reads it: its Markdown cells as they are, each code cell a {code-cell} r block with its tags under its first line (:tags: [remove-input]), and a line +++ before each Markdown cell that follows another cell. Whatever you change there, a cell changed, added, split or removed, is written back into the notebook, which stays a notebook: a ```r block you type in a Markdown cell is its text, a {code-cell} block typed after it is a new cell, a +++ splits a Markdown cell in two and taking one out between two Markdown cells joins them, and a cell moved elsewhere in the text is the same cell. Outputs stay with code that is unchanged; a code cell whose code you changed reads Out of date until it runs again. A code cell can also be changed in place, in its frame, as a draft with its tick. While you edit, the tab also offers Update outputs (the chip), described in section 4.

The arrow at the top left of the document, with the contents' button and the switch that hides the code, downloads the document as a Jupyter notebook (.ipynb): its text as Markdown cells, its cells as code cells with what they printed and drew as their outputs, the pictures inside the file, so the notebook is one file that opens anywhere Jupyter does. It is the document as you see it, so the outputs a Quarto, R Markdown or MyST file shows after Update outputs, which that file does not keep, are in the notebook.

× on the tab closes the document, and nothing is deleted: its files stay in the project, and a click on one of them in the projects list shows it again, as opening or adding a document does.

Reloading and sharing#

A document stays open across a reload, at the chapter you were reading and where you were in it. That is kept with the project, as which tab you were on is; reading chapters is no change to your files.

A lesson from the site, opened by a link that names its address, is fetched again whenever its project opens, as long as you have not changed its file and none of its examples holds a draft: a mistake the teacher has fixed reaches you without your doing anything. Once you change the file, it is yours, and Start over is the way to the site's version.

Link to this project, in the projects list the project button opens, copies a link that carries the files that are included, the document's among them; a lesson from the site that you have not changed goes in as its address, which keeps the link short. Whoever opens it gets them in the tabs and the document beside them.

2Notebooks, R Markdown and Quarto#

R Markdown and Quarto#

An .Rmd or .qmd file opens as a document. Each R chunk, written ```{r}, becomes lines for the console, and the chunks share their names, as they do when knitr knits the file in one R session. The {webr} and {webr-r} chunks of quarto-webr are R chunks too. The chunk options are read as knitr reads them: from the chunk's header, as in {r setup, include=FALSE}, from the #| lines at the top of a chunk, which win where both say one, and from the defaults in the front matter's execute: or knitr: opts_chunk::

OptionWhat it does here
include=FALSERuns when a cell below catches up, but is not shown. If it fails, it is shown with its code
echo=FALSEOnly Run here is shown, not the code
#\| code-fold: trueThe chunk starts with its code hidden, which its chevron shows (Quarto's option). In the front matter, on its own or under format: html:, it is so for every chunk
eval=FALSEThe code is shown and never run
error=TRUEAn error in the chunk does not stop the cells below
fig.width=8, fig.height=5Its plots are drawn that size, in inches, and shown smaller where the page is narrower; fig.asp=0.6 gives the height as a part of the width. Quarto's #\| fig-width: 8 is the same. In the front matter, on its own, under format: html: or in knitr: opts_chunk:, it is so for every chunk. A side not given is repr.plot.width or repr.plot.height where the program set them, else Rprimo's 6.2 by 3.7

A knitr::opts_chunk$set(echo = FALSE) line in a chunk changes the defaults from the next chunk on, as it does when knitting, and is taken out of the code, since there is no knitr here for it to set. It is read only when every value in it is written out. So is an option: echo=solution, a value that comes from a variable, is not guessed at, and the default stands. Chunk labels go.

A chunk in another language, such as {python} or {bash}, is shown as code and not run. A plain ```r fence without braces is shown and not run, as knitr leaves it. Inline code, such as `r x`, stays as it is written. child=, file=, code= and ref.label= are not followed. A callout's ::: lines and a heading's {#id .class} go, and what they held stays.

The front matter's title: becomes the document's title when the text has no # heading of its own. Its params: become a hidden cell that runs before the first chunk, built from their default values, a whole number as R's integer:

r
params <- list(
  region = "north",
  year = 2024L
)

A value R cannot be given the way rmarkdown would read it, such as an R expression, a date, or a list of mixed kinds, is left out rather than guessed at. In a .qmd file, yes, no, on and off are the strings they look like, as Quarto reads them, and only true and false are TRUE and FALSE; in an .Rmd file all of them are TRUE or FALSE, as R Markdown reads them.

A quarto-live file, with format: live-html or format: live-revealjs, is read the same way, its {webr} chunks R chunks, and quarto-live's own chunk options are read too:

OptionWhat it does here
setup: trueRuns when a cell below catches up, but is not shown, as include=FALSE
exercise: ex1Lines for the console with a blank ______ to fill in. Catching up passes over the exercise while a blank is left in it, and Run here asks for it to be filled in first
hint: true, solution: trueShown and not run, or left out when the front matter's live: says show-hints: false or show-solutions: false, as is a ::: {.hint exercise="ex1"} or ::: {.solution exercise="ex1"} block
check: trueLeft out: nothing grades an exercise here

The front matter's webr: packages: become library() lines at the top of the hidden first cell, so the packages are installed and attached before the first chunk runs, as quarto-live does, and its webr: cell-options: are the defaults of the {webr} chunks. The {{< include >}} of quarto-live's _knitr.qmd goes; another include is not followed. A slide deck, format: revealjs or live-revealjs, is read as one document, its slides the sections under their ## headings; the . . . pauses and the speaker notes, ::: {.notes} and all that is in them, go.

In a folder, index.Rmd or index.qmd comes first. A README.Rmd or README.qmd is the folder's note. An X.md beside an X.Rmd is what knitting it wrote, and so a file rather than a chapter. Each file of several starts afresh, as each is knit in an R session of its own: catching up in one never runs the chunks of the file before. With an R Markdown or Quarto chapter, the rest of the folder comes along, the data its code reads and the scripts it sources, and becomes tabs among your files when the document opens.

Jupyter notebooks#

An R notebook (.ipynb), as IRkernel, Colab or xeus-r write one, opens as a document. Its markdown cells are the text, as they are. Each code cell becomes lines for the console, so the cells share their names, as they do in Jupyter. What the notebook saved under a cell is shown under it as saved output: text in an output box, a plot as a picture, and a plotly chart as the live chart it was, which you can point at and zoom. That chart is drawn by the plotly you install in R; until you have, it says so, with a button Install plotly that installs it for you. HTML it saved, such as a data frame's table, is drawn with the same few tags the document's own HTML may use; HTML that would show nothing without its scripts is shown as its text instead. Interactive output is the exception: a whole page an htmlwidget saved, or one Rprimo saved, is shown under its cell as a line saying it is interactive output saved in this document, with a button Show, and runs only when you click it (see Saved output).

A cell's tags change how it is shown, in the words Jupyter Book and nbconvert use:

TagWhat it does here
remove-cellThe cell runs when a cell below catches up, but is not shown and has no output. If it fails, it is shown with its code
remove-inputOnly the cell's Run here is shown, not its code
hide-inputThe cell starts with its code hidden, which its chevron shows. A cell that Jupyter shows folded (Collapse selected code) counts as tagged so
remove-outputThe saved output is left out
raises-exceptionThe cell ends in an error on purpose; the cells below still run
skip-executionThe code is shown and never run
freshCatching up from below stops at this cell
console-onlyOnly the cell's Console button, no Run here: for lines that wait for you at every step. Console first runs the cells above that have not run yet; catching up and Update outputs pass the cell by

A cell saved with an error as its output is taken as raises-exception too: the notebook shows the error was there when it was saved, so the cells below still run past it.

To give a cell a tag, open its chapter with the pencil and write the tag under the cell's first line, after :tags:, or behind the language on that line itself. The two are the same tag, and the next time the pencil opens the notebook, the tag stands under the line. This cell, which ends in an error on purpose:

text
```{code-cell} r raises-exception
stop("on purpose")
```

is the same cell as:

text
```{code-cell} r
:tags: [raises-exception]
stop("on purpose")
```

Several tags are separated by commas, :tags: [remove-input, raises-exception], or by spaces behind the language. Taking a tag out of the line takes it off the cell.

A document's own Markdown takes the same tags, behind its fence's language: ```r console raises-exception (see Words for code that is not run as it stands). A notebook made from the document carries them as its cells' tags, and a notebook read as a document gives them back on its fences.

Several notebooks, picked or dropped together, or a folder of them, make one document with a chapter each, in the order of their names. Each chapter is headed by the notebook's own first # heading, or its file name, and its other # headings become sections. Each notebook's cells catch up only within that notebook, as each had its own kernel in Jupyter, and as every file of a document does. A folder can also hold .md, .Rmd and .qmd chapter files beside the notebooks; they all go in, in one order.

The other files in the folder, the scripts the notebooks source and the data they read, come with the document and become tabs among your files when it opens. A Python notebook is not run here; see section 5.

MyST notebooks#

A .md file that is a notebook in MyST text, as jupytext --to myst writes one and Jupyter Book reads it, opens as a document like a notebook. It is one when its front matter has jupytext: or kernelspec:, or it has a ```{code-cell} block. Its Markdown is the text, and each {code-cell} becomes lines for the console, with its :tags: doing what a notebook cell's tags do (the table above). A cell in another language, and a {raw-cell}, are shown and not run, and so is a plain ```r fence. The +++ lines between cells go. The file keeps no outputs: Update outputs runs its cells, and the status line says the file keeps none. The pencil shows it as the text it is. jupytext --to myst notebook.ipynb makes one of a notebook. An X.md dropped beside an X.ipynb, as jupytext pairs them, is a file rather than a second chapter of the same notebook; its chapter toggle in the projects list is off.

Changes go back in the file's own form#

The tick on a changed cell (section 1) writes the code back into its own file, in that file's syntax, and writes outputs only where the format keeps them. A Markdown file gets the fence's lines and the text output fence under it. A notebook gets the cell's source and outputs (text as a stream, a plot as a picture), its execution_count left empty, a cell whose output is out of date marked in its metadata, and the rest of the JSON as it was, with the indent it had. A .qmd or .Rmd file gets the chunk's code lines between its header and its #| lines and its closing fence, and a MyST notebook the {code-cell}'s code lines under its options, and neither gets output, since rendering makes that. A fence that names a file with src= writes that file. No file is turned into another format. A notebook cell that carries a program's other files in its metadata cannot be changed this way.

3Writing a document#

A document is a Markdown file: headings, paragraphs, lists, tables, links, pictures and fenced code. What Rprimo adds is a few words on the line that opens a fence. They are the same words the handbook's pages are built from, so one Markdown file makes a page on the site and a document in the editor.

Lines for the console#

A fence marked console holds lines to type at the prompt. Each line, or each block such as a for loop, runs as if typed, and a value shows itself, so words on its own line prints the vector:

markdown
```r console fresh
words <- c("tea", "bread", "apples")
```

That is the fence of this cell:

r>Console
words <- c("tea", "bread", "apples")
r>Console
words <- sort(words)
words

The word fresh makes the first cell a starting point: running the second cell catches up as far as the first and no further, so nothing from section 1 runs again. Use it where a new part of a document starts afresh. It bounds what catches up; it does not clear any names. A transcript, lines beginning with R's > prompt, is lines for the console too, without being marked.

A program, with its files#

A fence marked r, with no console, is a program, main.R. A fence right under it that names a file with file= is another tab of the same example, a script it sources or a data file:

markdown
```r
scores <- as.numeric(readLines("scores.txt"))
cat("Best:", max(scores), fill = TRUE)
```
```text file=scores.txt lines=4
72
88
```

Here is a full one. lines=4 keeps the data file's box about four lines tall; the rest scrolls inside it.

main.ROpen
scores <- as.numeric(readLines("scores.txt"))
cat("Best:", max(scores), fill = TRUE)
cat("Average:", mean(scores), fill = TRUE)
scores.txt
72
88
95
61
80
78

Output:

text
Best: 95
Average: 79

A program that asks with readline() gets its answers from a stdin fence under it, one answer per line. Without one, it asks in the Output tab.

rOpen
name <- readline("Your name? ")
cat("Hello,", name, fill = TRUE)
input, prepared
Ada

Output:

text
Your name? Ada
Hello, Ada

More words for a program's fence:

  • file=R/helpers.R names the tab; a fence that names one joins the example above it.
  • pip=stringr,glue names packages to install when the example is run or opened. A package the code loads with library() needs no naming; the editor reads those out of the code.
  • src=data.csv fills the fence from a file beside the Markdown, which is how a file that is not text, such as a spreadsheet, comes along: text file=book.xlsx src=book.xlsx` with the fence left empty. On a page of the site this names a file beside the page's Markdown; in a link the file travels in the link.
  • A quiz fence under an example carries questions for the tutor, with a Start quiz button; the handbook's section on quizzes says how to write one.

Exercises with a check#

A check fence under a program makes it an exercise. The reader fills in the code in its frame and presses Check, which runs the code as it now stands with the check fence's code after it, as one program. Each stopifnot() in the fence, and each testthat expect_ call, is a check of its own: one that fails doesn't stop the ones after it. The fence's other lines, such as one that sets up a variable, run in order between them. A fence with no check in it is one check: all of it, which passes when it runs without an error. The document doesn't show the check, and the handbook's pages and links leave it out.

markdown
```r
square <- function(x) {
  # your code
}
```
```check
stopifnot("square(3) should be 9" = identical(square(3), 9))
stopifnot("square(-2) should be 4" = identical(square(-2), 4))
```

Here is that exercise, ready to check in the editor's document:

rOpen
square <- function(x) {
  # your code
}

Under the code, the card beside Check says how the last check went: "All 2 checks pass", or how many passed and what the first failing check says, such as "Not yet: 0 of 2 checks pass. square(3) should be 9". Each failing check gets a line on the Output tab. An error in the reader's own code ends the program before the checks, and the card shows its message, with the whole error on the Output tab, as after a Run. Write a check with identical() or isTRUE(): stopifnot(square(3) == 9) passes while square() still returns NULL, as NULL == 9 is empty and stopifnot() lets an empty check through. The checks run in the project's R like any example, so their names are at the console afterwards.

A time limit on the fence makes an exercise weigh an algorithm as well as test it: with timelimit=200ms (or timelimit=2s), each check must finish within that time, and one that takes longer fails even when its result is right.

markdown
```check timelimit=200ms
x <- sample(1e5)
stopifnot("my_sort() should sort 100,000 numbers" = identical(my_sort(x), sort(x)))
```

A sort that compares every pair fails that check with "stopifnot(…) took 41.20 s, more than the 200 ms allowed". With a limit, the Output tab also says what each passing check took, to the millisecond, and the card says "All 2 checks pass, each within 200 ms". Without one, nothing is timed. A slow check isn't stopped when it runs over: it runs to its end, or until Stop. Only the checks are timed, not the fence's other lines or the reader's own code before them.

The check is hidden, not secret: it is in the Markdown, where Edit shows it. An exercise's code isn't folded away, and Open and Run here take the code without the check.

What to watch in a recording#

A watch fence under a program says what to look for while stepping through its recording. The document shows its notes under the example, as plain text. With one, the example gets a Watch button, which records it and plays it back right there, and Open records it as it opens: the editor, the execution tape, the call stack and the variables take the screen. Either way, each note appears above the tape while the tape stands on its line.

rOpen
total <- 0
for (s in c(72, 88, 95)) {
  total <- total + s
}
print(total)
What to watch
  • Nothing has run yet. The next line makes total.
  • The first pass: s is 72, and total is about to become 72.
  • Another pass: total grows by s.
  • The last pass. What will print show?
  • The loop is over, and s still holds the last score.

Each line of the fence starts with the line of code it is about, then a colon and the note. In square brackets after the line number, indexes and slices pick the times that line runs. They are written as in Python, counted from 0:

  • 3 is every time line 3 runs.
  • 3[0] is the first time, 3[1] the second, and 3[-1] the last.
  • 3[1:] is every time after the first, 3[:2] the first two, and 3[::2] every other one.
  • helpers.R:3[0] is about a line of another tab of the example.

A line of the fence that starts with no line number goes on with the note above it, and a word in backticks is shown as code. vars= names the variables to watch: they come first and are marked, in Watch's player and in the Variables pane. The player always shows the global variables, but not functions, classes and modules unless vars= names them, as square in vars=total,n,square. A function's local variable is named with its function, as in vars=total,n,square.x, and shows while that function runs. The bars with a note get a mark on top of the tape, so you can find them. A note is about the line the tape stands on, which is the line about to run.

The notes hold for the example as it is written: once its code is changed, line 3 may be another line, and the notes are no longer shown. A program fence marked record, such as r record`, gets Watch too, and is recorded when it is opened, with no notes.

Words for code that is not run as it stands#

These are the tags of a notebook's cells (the table under the notebooks above), written behind the fence's language. A Quarto or R Markdown file's chunk options become them too:

On the fence lineWhat the reader gets
r console remove-cellNothing on screen. The lines run when a cell below catches up, and appear with their code only if they fail. Good for library() calls and setup
r console remove-inputOnly Run here, with the caption code hidden
r console hide-inputThe cell with its code hidden at first: its title bar, with its buttons, and a chevron that shows the code
r skip-executionThe code, with no button that runs it, and catching up passes it by
r console console-onlyLines for the console only: the Console button runs the cells above that have not run yet and puts the lines there, and there is no Run here. Catching up and Update outputs pass them by
r console raises-exceptionLines that end in an error on purpose. Catching up counts them as run and goes on

The shorter words earlier documents used, hidden, nocode, norun and error, still work and mean the same.

A skip-execution fence, for code that must not run here:

r
repeat print("for ever")

A raises-exception cell, which catching up goes past:

r>Console
log("seven")

And a remove-input cell, which shows only its button:

r · code hidden>Console

Saved output#

What a cell printed can be kept under it, as a notebook keeps it: its text in a fence marked text output, and each plot or drawing as a picture named out-N.png on a line of its own, where N counts the document's cells that run, program examples included, from the top. Here the cell is the document's third:

markdown
```r console
6 * 7
```

```text output
[1] 42
```

![Output](out-3.png)

A plotly chart is kept the same way, as the chart itself in a file named out-N.plotly.json, ![Output](out-3.plotly.json), and the document draws it again as a live chart, as a notebook's saved chart is (see Jupyter notebooks). Other readers of the Markdown, such as GitHub, show only the word Output there.

Interactive output, a DT table or a leaflet map, is kept as its whole page in a file named out-N.widget.html, ![Output](out-3.widget.html). It is not run when the document opens: under its cell is a line saying it is interactive output saved in this document, and Show runs it, in a frame shut off from the editor, your files and the internet. A document from someone else can carry such a page, which is why it waits for your click. Other readers of the Markdown show only the word Output there.

HTML a cell showed, such as a table, is kept in a fence marked html output. The document draws it with the same few tags its Markdown may use (see Headings, links and pictures), a table's cells right-aligned, as Jupyter draws them; what a <style> or <script> holds is left out, and so are its classes and styles. A notebook made from the document keeps it as text/html.

Only what stands directly under a cell in exactly this form, with blank lines between, counts as its output. A plain text fence of your own, or a picture of another name, is left alone. You need not write saved output by hand: Update outputs writes it, see the next section.

Each # heading starts a chapter; each ## heading is a section, listed under its chapter in the contents. ### and below are not listed. Every heading has an anchor, its text in lower case with spaces as - and punctuation left out, as on GitHub: ## 3. Writing a document is #3-writing-a-document. A link to it, [Writing](#3-writing-a-document), goes to it in whichever chapter it stands. A link that opens a document at a heading adds &ch= and the anchor: #mdu=/handbook/documents.md&ch=saved-output.

  • A link to another .md file beside a document of the site, such as [the drawing reference](./draw.md), opens that document on the tab; on a page of the site it goes to the page built from it: the drawing reference. Any other page of the site opens in a new browser tab.
  • In a folder of chapters, a link to another chapter file, [next](02-loops.md#while), goes to that chapter.
  • A link to a web page opens in a new tab, with the name of its site written after it, so you can see where it goes.
  • A picture shows when it travels with the document, or is a file of the site beside a document of the site. A picture on another server is not fetched, since fetching it would tell that server who is reading.
  • A picture of an SVG, ![Diagram](diagram.svg), is a still picture. To have one that moves and answers the mouse, write it in a fence marked svg live, or a whole web page in one marked html live, or name the file with src= and leave the fence empty: html live src=demo.html`. In the document tab it runs by itself once you scroll near it, in a frame of its own, as tall as it is, with its scripts, hovers and animations, and nothing in it can reach the editor, your projects or your browser's storage, or fetch anything from the web. The pages of the site show its source.
  • In the document tab, $x^2$ is a formula, and $$…$$ on lines of their own a formula set apart. As in R Markdown and Jupyter, \begin{…}…\end{…} and \[…\] on lines of their own are one too. The pages of the site do not render them.
  • In the document tab, the HTML that notebooks use for text is drawn: <b>, <i>, <u>, <sub>, <sup>, <br>, <hr>, <center>, <p> and <div> aligned, <details> with its <summary>, tables with their cells aligned and spanned, <font> with a colour and size, a <span> with a colour, links (<a href>) and anchors to link to (<a id>), and pictures (<img>) aligned and sized, the links and pictures by the same rules as Markdown's. Any other attribute is left out, any other HTML is shown as text, and comments are not shown. Markdown and formulas in the lines right under a tag that stands on a line of its own are shown as written; leave a blank line after the tag to have them drawn.

4Update outputs, and getting a document out#

Update outputs#

Open the document with the pencil on its tab, and Update outputs, a chip, appears beside it. Pressed, it takes the drafts in your cells into the files, as the tick would (the outputs from the first changed cell on read Out of date until the update reaches them), and writes the saved output of every cell of the file you are editing afresh, the file of the chapter on show:

  1. It clears the console's names, as Run does.
  2. It runs every cell of that file from its top, in order: console lines, hidden cells and program examples alike. Each one's output appears in the tabs below as it runs, and while it runs, the chip is a square, Stop.
  3. Under each cell it writes what that cell printed, as a text output fence, without the > and + of the lines it typed, and its plots and drawings as pictures named <file>_files/out-N.svg among your files (out-N.png for a drawing, for a plot too big to be an SVG and for one you asked to be a PNG) (a plotly chart as <file>_files/out-N.plotly.json, interactive output as <file>_files/out-N.widget.html), in place of what was saved there before. A Markdown file keeps outputs under its cells and a notebook in its cells' outputs, a plotly chart as application/vnd.plotly.v1+json, as Jupyter keeps it, and interactive output in a notebook as text/html, the whole page; the cells of a Quarto, R Markdown or MyST file run all the same, and since such a file keeps no outputs (rendering it makes them), they are shown under its cells without being written into it, to read the document with its results or print it from the browser; they stay until the file changes, the page is reloaded or you update again, and the status line says so. The document's other files are neither run nor written; update each on its own. Undo takes the whole update back.

A program example gets a text output fence too. An Output: line with a plain text fence of your own under a program stays as it is, so in a document you mean to update, leave it out, or the output is there twice. A hidden cell runs, but gets no output written, and anything saved under it goes. A transcript keeps the output it was written with. A skip-execution fence is no cell at all. Very long output is cut after 2000 lines or 100,000 characters, with a line saying so.

When a cell ends in an error, the update stops there and the status line names the cell; its error is written as its output, with the outputs of the cells above it. A cell marked raises-exception is the exception: its error is its output, and the update goes on. Stop stops the update too, and keeps what the cells before it wrote. The document is then kept as an edit is: Undo brings back the one before while the tab stays open, and a reload or a link carries the new outputs, pictures included.

Remove outputs#

Beside the chip, while you edit, is the same chip struck through: Remove outputs. It takes the saved output of every cell of the same file out of it: the text output fences and pictures under its cells (a picture that the text shows elsewhere stays), the Out of date marks, and in a notebook its cells' outputs. The code and the text stay as they were. The file gets smaller, and so does a link to the project; whoever opens it runs the cells to see their output again. Undo brings the outputs back. A Quarto, R Markdown or MyST file keeps no outputs, so there are none to take out.

Outputs made again on opening#

In the projects list's Included column, a Markdown file's or a notebook's row has a second button after its tick box: a code cell over a chart, while Download and the link take the file's outputs as they are. Click it and the chart gives way to an arrow from the code cell round to an empty chart: Download and the link then leave that file's outputs out, with the pictures only they showed, which keeps the link short. They also say that the outputs are to be made again. Whoever opens the link, or drops the ZIP onto the editor, has that file's cells run as soon as the language is up, as Update outputs runs them, and their outputs saved; a project made from a link still counts as unchanged. The setting stays with the project, and travels with it.

Download#

Download, over the files' tick boxes in the projects list, saves the files that are included in a ZIP, the document's among them; drag that ZIP onto the editor and the project comes back, document and all. A document file whose book is closed is still a file of the project, still in the ZIP, and is no chapter. Chosen with From files or a ZIP… in the projects list, the ZIP comes back as a project of its own.

The quickest way is the editor itself: open the notebook, file or folder, then Link to this project in the projects list. That link carries every file that is included, so untick the ones your students should not get before you copy it.

A teacher who has rprimo_link.py, the script Rprimo's own pages are built with, can make the link at a shell instead, without a browser:

bash
python3 rprimo_link.py --doc notes.md
python3 rprimo_link.py --doc course/
python3 rprimo_link.py --doc lesson.Rmd
python3 rprimo_link.py --doc lesson.qmd
python3 rprimo_link.py --doc lesson.ipynb
python3 rprimo_link.py --doc course.zip
python3 rprimo_link.py --doc notes.md --attach helpers.R --attach data/

--doc takes one Markdown, R Markdown, Quarto or notebook file, or a folder or zip of them, and reads it exactly as a drop on the editor would, except a MyST notebook, which it reads as plain Markdown and says so; a ZIP of that folder reads back as the document it was. --attach adds a file or a folder that the Markdown does not name but its code needs; a link.json beside the Markdown can list them instead, as {"attach": ["helpers.R", "data/"]}. --chapter opens the link at a heading, by its anchor. --base says where the editor lives, if not at https://rprimo.com/ide/. The tool prints the link, and says at the shell what it left out, such as a params: value it could not read.

A link holds at most 400,000 characters and carries at most 100 files. What it unpacks to may be far more, since text that repeats packs small, and it opens whole. A link past those limits is an error, said at the shell, rather than a link that opens short. A notebook over 4 MB, or a zip that unpacks to more, is not read, as a drop does not read it, and a file over 400 KB in a folder of notebooks is left out, as a drop leaves it out; the tool says so. For anything larger, put the Markdown on a site and link to it, or hand out the ZIP.

5Code in the other language#

Rprimo runs R. Its sister, primopy, is the same editor for Python, in the browser the same way. Drop a Python notebook, a .qmd or .Rmd file whose chunks are all Python, .py files with no .R beside them, or a folder or zip of those on Rprimo, and nothing is added. A dialog says what it is and offers it to primopy instead:

  • Open in primopy opens it there in a new browser tab, with a link that carries it. Nothing here changes.
  • Copy link copies that link, to send or to open later.
  • Cancel leaves everything as it was.

When it is too big for a link, the dialog offers Download ZIP instead: drop the ZIP on primopy's project button to open it there. Where R and Python come together, as in a .qmd with chunks of both, the drop opens here as usual, and the Python chunks are shown as code. primopy does the same the other way round, offering R to Rprimo.