Rprimo
Rprimo is a place to learn R in your web browser. There is nothing to install, no account to create, and nothing to set up. You open the page, you write a few lines, you press a button, and you see what happens.
Most tools only show you what your program printed. Rprimo also shows you what it did: every step of a run lands on the execution tape, with every variable on screen, and you can travel the tape forwards and backwards, line by line. If you have never programmed before, that is the feature to get to know first.
There is more around it. A tutor sits beside the editor; it sees your code, your output and the step you are on, and it answers with a question rather than the solution. Teachers can hand out a whole project as a single link, and put quiz questions inside it for the tutor to ask. Plots and drawings appear next to the code, and a guided tour shows you the whole thing the first time you open it.
Contents#
- 1Your first five minutes
- 2Primo, the guided tour
- 3What's in the header
- 4The examples
- 5Writing code in the editor
- 6Running your program
- 7Stepping through your program
- 8Output, plots and drawings
- 9Programs that ask questions:
readline() - 10Working with several files
- 11Package management
- 12The R console, a calculator for trying things
- 13Code completion
- 14Undo
- 15The tutor
- 16Quizzes
- 17Documents and notebooks
- 18Is my work saved?
- 19Changing the layout, theme and language
- 20Keyboard shortcuts
- 21Things Rprimo can't do
- 22When something goes wrong
1Your first five minutes#
Open the page. In the tab row under the editor you'll see Downloading R… for a few seconds, then Ready. Now Run and Record, at the top left, work.
Try this:
- Open the Examples menu in the header and pick 6 · Find the bug.
- Switch Record on, then press Run.
- The tape opens at line 5, where the example has put a red dot for you. Press Step a few times. Watch the Variables box on the right: it shows every variable and its current value, and highlights the ones that just changed.
- Went one step too far? Press Back.
That program calculates an average, and gets it wrong. Instead of staring at the code trying to work out why, you can simply watch the numbers change until you spot the moment things go astray. This is how you'll want to look at your own programs too.
2Primo, the guided tour#
The snake in the logo, curled into an R, is Primo. The first time you open Rprimo he uncoils, crawls across the screen and stops at each part of the interface to explain it. Press Next (or Enter, or →) to send him on; pressed while he is still typing or pressing buttons, he finishes at once. Back (or ←) takes him to the stop before, shown as it was when he had finished there: the program he typed, the run and the drawing are back as they were. Enter always sends him on, after Back too: the keyboard is on Next again. Skip or Escape ends the tour.
The tour uses two small example projects and an empty file to have something to show: it does a sum at the console, runs example 1, types a sun in an orange sky into an empty file to show off completion and the drawing, then loads example 5 and records it, to travel through the run step by step, forth and back; before it says goodbye, it points at the project button beside the logo, whose list is where a project is shared by link, downloaded as a ZIP, or, in Chrome and Edge, saved to a folder. Don't worry about your own work: the tour never touches your project, and when it is over, your files come back exactly as you left them. Nor does it run anything in R: the console's answers, the runs it shows, and what completion lists, were recorded beforehand and are played back, so the variables you had at the console are still there when the tour is over. Only the console runs your own code meanwhile: Run on anything but the tour's examples, Shift+Enter and the document's runs wait until the tour is over, and the button with the project's name does nothing.
You can call Primo back any time by clicking the logo or pressing the Tour button in the header.
3What's in the header#
The header reads left to right: first the two buttons that start your program, then everything you do to a project, and at the right the things you ask for help.
| Control | What it does |
|---|---|
| Rprimo logo | Click to start the tour. Hover to see the version, which R this is, and whether your work is being saved |
| Project name | The project you are in, beside a briefcase. Click for the list of your projects: open another, rename it, delete it, download it as a ZIP or copy a link to it, or start a new one, empty (New project), from files or a ZIP (From files or a ZIP…) or, in Chromium browsers (Chrome, Edge, Brave, Opera), from a folder on your computer (From a folder…). The project you are in shows its files as a tree (each with a tick box, a document file with its chapter book as its icon); over the files sit New file, Open files and Run (which file Run starts), on the line of Files the project's folder (Save to a folder…, in Chromium browsers), and over their tick boxes, after with:, Link to this project (a chain link) and, below it, Download; the project's row has Rename and Delete. A small drive after the name means the project is linked to a folder on your computer: green while it saves there, yellow while it waits for Reconnect |
| Run | Runs your program. It wears the same yellow mark as the file tab it starts from |
| Record | A switch. While it is on, Run records every step, and the button turns yellow and its mark becomes a record dot |
| Examples | Opens a ready-made example program as a project of its own |
| Undo | Takes back your last change. When that change would bring files back, it turns dark blue and reads Restore 2 files |
| ◐ / ☀ / ☾ | Switches the look: follow the system, light, dark |
| Globe | Picks the editor's language: English, Deutsch, Français or Italiano |
| Tour | Starts the guided tour |
| Handbook | Opens this handbook in a new tab |
| Tutor | Shows or hides the tutor chat |
On a narrow window some of these move into the ☰ menu at the right end of the header.
The status (Downloading R → Ready → Running → Finished, or a short error message) is not in the header. It sits in the tab row under the editor, right of Output / Plots / Draw, next to what it is talking about.
4The examples#
The examples are short, complete programs, each about one idea. They're the best way to learn what Rprimo and R can do. Pick one, read it, run it, step through it, then change something and run it again.
| # | What it shows |
|---|---|
| 1 | Variables, <- and print |
| 2 | Drawing shapes on a canvas |
| 3 | Vectors and loops: adding up numbers, building a new vector |
| 4 | Drawing a pattern with a loop |
| 5 | Functions, and how one function calls another |
| 6 | Finding a real bug by stepping through the program |
| 7 | Drawing a whole scene |
| 8 | A program that asks the user a question with readline() |
| 9 | A program split over two files, joined with source() |
| 10 | A whole vector at once, and a plot with plot() |
| 11 | Reading a text file and writing a new one |
| 12 | Reading a table from a CSV file and writing a report |
| 13 | Conway's Game of Life, drawn cell by cell |
| 14 | Catch the dot: a game loop that reads the keyboard |
| 15 | Using a package: stringr |
An example opens as a project of its own, and your project stays as it was: the button beside the logo names the project you are in and takes you back to any other (see Is my work saved?). Where the browser keeps only one project, an example replaces the files in it instead, and Undo brings your files straight back if you didn't mean to; it says Restore 2 files when that is what it would do.
The last menu entry, · new project ·, starts a project with one empty file; nothing is deleted. In a browser that keeps only one project (see Is my work saved?), examples replace that project as described, and the last entry reads · clear saved work ·: it deletes everything you've saved (after asking) and leaves you an empty file.
5Writing code in the editor#
The big text area in the middle is where you write your program. It colours R code to make it easier to read and helps with a few tedious things:
- Enter starts the new line at the same indentation as the one above, and indents one level further after a line that ends in an open
{,(or[, or in a comma. - Tab inserts two spaces, the usual R indentation. If you're in the middle of typing a name, Tab completes it instead (see Code completion). With several lines selected, Tab indents all of them.
- Shift+Tab removes one level of indentation.
- Click a line number to select the whole line; Shift+click selects every line up to that one.
- Click just left of a line number to place a red dot, a breakpoint. With Record off, your program stops when it reaches that line and waits for you (see Stopping at a breakpoint). With Record on, it runs to the end, the tape opens at the first dot it passed, and Continue jumps from one dot to the next. Handy for skipping straight to the interesting part.
If you edit the code after recording a run, the recording is thrown away: it no longer matches what's on screen. Just record again.
Folding a block away#
In an R file, a small triangle ▾ appears to the right of the line number wherever a line opens a bracket that closes further down: a function's {, the body of a loop or an if, or a call spread over several lines. The triangles are faint until you move the pointer over the line numbers. Click one and the block folds into its first line, with a ⋯ at the end to show that something is hidden; the triangle turns into ▸. Click the triangle or the ⋯ to unfold it again.
Folding only changes what you see. The code is still there and runs exactly as before. If your program stops on a line inside a folded block, at a breakpoint or while you step through a recording, the block unfolds by itself so you can see the line.
From the keyboard, with the cursor on a block's first line (the one with the function, the for or the if): Cmd+Option+[ folds the block and Cmd+Option+] unfolds it on a Mac; elsewhere it's Ctrl+Shift+[ and Ctrl+Shift+]. Ctrl+Alt+[ (Ctrl+Option+[ on a Mac) folds every block in the file at once, and Ctrl+Alt+] unfolds them all.
Finding and replacing#
With the cursor in the editor, press Ctrl/Cmd+F and a search bar opens under the code. Type what you're looking for: every match lights up, and Enter jumps to the next one (Shift+Enter to the previous one). next and previous do the same, and so do F3 or Ctrl/Cmd+G, with Shift to go backwards. Escape or × closes the bar.
Three boxes make the search pickier:
- match case:
Totalno longer findstotal. - by word:
xfinds the variablex, but not thexinsidemaxornext. - regexp: the search text is a regular expression, for the times you know what that is.
The second field is for replacing. Type the new text, then press replace (or Enter in that field) to replace the current match and move on to the next one, or replace all to change every match in the file at once. Ctrl/Cmd+Z takes a replacement back; a replace all comes back in one step.
The search looks through the file that's open in the editor, not the other files of the project. Ctrl/Cmd+F only opens this search bar while you're typing in the editor; anywhere else on the page, it's the browser's own search.
6Running your program#
There is one button that starts your program, Run, and a switch next to it that decides what kind of run it is.
Record off (the switch is grey): Run simply runs your program and shows what it prints. Fast, with no limits. Use this when you just want the result.
Record on (the switch is yellow): Run does the same thing, but writes down everything the program does on the way, so you can walk through it step by step (next section). Slower, and it stops after 5,000 steps, so an accidental endless loop gives you a message rather than running for ever.
You can see which one you are about to get without reading the switch: while Record is on, the Run button itself turns yellow and its play mark becomes a record dot.
Every Run starts from a clean slate, the way a fresh R session would: the variables of the last run are cleared first. Your program runs from top to bottom, one statement at a time, and a line that is only a value, like mean(x) on its own, prints that value, just as it would when you type it at R's prompt. Warnings and message() lines appear in the output where they happened, not saved up for the end.
What your program prints appears as it is printed. A program that counts to ten slowly shows each line as it arrives, and one that draws shows each shape as it is drawn: you are watching it work, not waiting for it to finish. The page stays yours while it runs: you can keep reading, scrolling and typing.
While a program is running, the Run button becomes Stop, and its play mark becomes a square. Press it and the program stops where it is, even one that would never have ended on its own, and even one sitting in the middle of a long Sys.sleep(). Nothing is lost: your files stay as they are, and everything the run had worked out is still there for the console to look at. If it does not react, which a long computation inside R's own C code can do, the status line says so and offers Restart R: it starts R again from scratch, losing what the run had worked out, and nothing restarts until you press it.
There is a limit to how much the page will keep: about a million characters. A program that prints without end reaches it, the status line says so, and Stop is the way out.
If your program loads a package with library(stringr), Rprimo fetches it before your first line runs. The status in the tab row tells you what it's getting and how far along it is, as in Fetching ggplot2, 40 of 97 (a package needs others, and those come too), and then it stays available. See Package management.
If something goes wrong, the error is shown in red at the end of the output, naming the file and line, and the editor marks that line and scrolls to it. For a typing mistake (a syntax error), the program does not start at all, and the message says where R got stuck.
Running one line at a time#
You don't have to run the whole file. Put the cursor on a line and press Shift+Enter: that line runs, and the cursor moves on to the next one, skipping blank lines and comments. Keep pressing and you walk through the file a line at a time. Select several lines and Shift+Enter runs those.
Rprimo runs whole statements, so you never cut one in half:
- On a line that starts a block (
for,if,while,repeat, orf <- function(...) {), the whole block runs. - A statement written over several lines, like a long call to
c()orplot(), runs as a whole wherever the cursor is in it. - A line inside a function runs on its own. The function's own arguments and variables don't exist out here, so an error saying
object 'x' not foundis what you'd expect. - Select part of a line, like
x * 2, and you get just its value.
What the lines print goes to the Output tab, below what's already there, set off by a thin line (hold the pointer on it to see which lines printed it). A line that has a value, the way 3 * 7 does at the console, prints it there too, as [1] 21. An error is shown in red under it, and the editor marks the line. Plots and drawings go to their tabs as usual, and readline() asks in the Output tab, as in a Run. Stop stops a line that doesn't end, like repeat {}.
You can also use the mouse. The number of the cursor's line (or of the first selected line) turns into a ▶: click it to run. So clicking a line number once selects that line, and clicking it again runs it. Hold the pointer over the ▶ and the lines it would run light up. While a recording is up, the button is a › instead and takes the tape to that line rather than running anything (see Jumping to a line).
The lines share their variables with the console: x <- 5 run from the editor can be looked at in the console, and the other way round. They stay until the next Run, which starts fresh: it forgets them, and clears what the lines printed. After that the program's own variables are there to build on, as usual. The console notes each piece with a line like ▸ ran main.R:5–6; click it to go back to those lines.
Lines run this way are never recorded, even with Record on: to step through them, record the whole program.
Stopping at a breakpoint#
Click just left of a line number to mark it with a red dot, and a plain Run stops when it gets there. (A Record does not stop: it runs to the end and opens its tape at the dot, where you can step backwards too.) It is not finished, only waiting: the status line says Paused at line 5 in average(), the editor points at the line, and Variables and Call stack show what the program has in hand at that very moment. Click a function in the call stack to see its variables.
While it waits, the Run button reads Continue and a Stop button appears beside it:
- Continue (or Ctrl/Cmd+Enter) lets the program go on to the next breakpoint, or the end.
- Step, Over and Out under the editor move it one line at a time, exactly as they do on a recording. A line that calls a function of yours is one step for Over and a walk inside for Step.
- Stop ends the run where it stands.
The red dots can be changed while the program waits. Click one away and it no longer stops there; click a new one and the next Continue stops at it.
A stopped program can also be talked to. Open the console tab and it offers Attach: from then on what you type runs inside the function the program stopped in, reading and changing its variables, as described in The R console.
Breakpoints stop the program only in the file that runs. A dot in a file your program reads with source() does not stop it, and the output says so when you run.
The one place breakpoints don't work at all is a page that is not allowed to wait for you, the same setup that makes readline() fall back to running the program again; hover the logo to check. There the dots only guide Continue through a recording.
7Stepping through your program#
After a run with Record on, a strip called the tape appears under the editor, together with the step buttons.
The tape#
Each tiny bar is one step of your program: one line, or one call into a function, or one return from it. Taller bars mean the program was inside a function (deeper still means a function inside a function). Red bars are the error that ended the run, or breakpoints. The yellow line is where you currently are.
Drag along the tape to move through the whole run, like scrubbing through a video.
Jumping to a line#
Put the cursor on a line and its number turns into a ›. Click it, or press Shift+Enter, and the tape jumps to the next time that line runs, counting from where you are: from the start, that is the first time. Press again and it goes to the time after that, and round to the first again after the last: a quick way to watch one line of a loop turn by turn, or one line of a function on each call. A line above the one the tape is on works the other way round, since what you are asking about has already happened: the jump goes to the last time it ran before here, and each further press one time further back. The status line counts along, like Line 6, visit 2 of 3. On a line the program never reached, such as the body of an if that was false, the › is grey and the status line says so.
Nothing runs when you press it, and the recording stays. To run a line on its own while a recording is up, first close the recording with Stop or a new Run, or switch Record off; then the number is a ▶ again.
The buttons#
| Button | Goes to |
|---|---|
| Start | The very beginning |
| Back | One step back |
| Step | One step forward |
| Over | Forward, but treating a function call as a single step |
| Out | Forward until the current function has finished |
| Continue | Forward to the next breakpoint, or the end |
The counter next to them reads something like step 24/181 · main.R:6, and adds entering when the step walks into a function, returns with the value when it hands one back, and the error when one was raised.
While a program is stopped at a breakpoint, the four forward buttons drive the program itself rather than a recording, and the others wait until there is a recording to walk. The counter then reads paused · main.R:5 · in average().
The steps are whole lines. R does not let Rprimo see inside a line without changing how your code behaves, so a line like total <- total + numbers[i] is one step, and you see its effect on total in the step after it.
You can also use the ← and → keys, as long as you're not typing in a text box.
What you see at each step#
Every step shows you the complete state of the program at that moment:
- The editor highlights the line about to run.
- Variables lists every variable with its type and current value, the way R would print it. Anything that changed in the last step gets a yellow marker, the quickest way to understand what a line actually does. The top of the program is the frame called
global. - Call stack shows which functions are currently running, the innermost at the top. Click one to see its variables.
- Output shows only what had been printed up to that step, so text appears exactly as you step past the
print()orcat()that produced it. - Plots and drawings behave the same way: go back before the line that made them and they disappear again.
Only the file that runs is recorded step by step. A file your program reads with source() runs, and its functions work, but their insides are not on the tape.
8Output, plots and drawings#
The area below the editor has tabs:
- Output: everything your program printed, errors in red.
- Plots: charts made with R's own graphics,
plot(),hist(),barplot()and the rest (see example 10), or with plotly, one card for each finished picture; an interactive table or map gets a card too (see Interactive tables and maps). Up to twelve per run. - Tables: a data frame or a matrix to look through, row by row, opened with
View()(see example 12). - Draw: a canvas your program can draw on, with
drawfrom the built-inRprimopackage.
Where the row is too narrow for every tab, Plots and Tables stay out of it until they have something to show.
Plots#
Anything drawn on R's graphics device lands in the Plots tab once the picture is finished. There is nothing to install and nothing to open first:
heights <- c(152, 160, 171, 158, 180, 165, 174, 169)
cat("tallest:", max(heights), fill = TRUE)
hist(heights, col = "gold", main = "Heights in the class", xlab = "cm")
abline(v = mean(heights), lwd = 3)Output:
tallest: 180abline() adds to the picture hist() started, so this is one card, not two. A plot made at the console lands in the Plots tab too. Packages that draw on the same device work the same way: with library(ggplot2) in the program, a ggplot() on a line of its own lands here as a card. Plots replay when you step: record a run, and each card appears at the moment your program finished it.
A card is drawn as SVG, the plot's lines, points and letters as shapes, so it stays sharp when you zoom the page, in a document read on another screen and in a saved picture. A plot with very many points (tens of thousands) would make an SVG of megabytes that the browser is slow to draw, and stays a PNG instead; so does a plot while your program is still drawing it and waits, at a readline() say. To choose the format yourself, set it before the plot is drawn:
options(primo.plot_format = "png") # or "svg", the default"png" keeps every plot a PNG. Like any option it holds for the rest of the session, console included, until you set it again. There is no WebP: R cannot write one, the browser writes only a lossy one, and R's PNG of a plot is already several times smaller than that.
A plot is 6.2 by 3.7 inches, its text 12 points, and shown 595 pixels wide, its true size: a CSS inch is 96 pixels. A plot made for a slide wants more room: set its size in inches, and the size of its text if you like, as in a Jupyter notebook for R, before the plot is drawn:
options(repr.plot.width = 11, repr.plot.height = 6) # and repr.plot.pointsize = 12The plot is then drawn that large, its text no bigger than before, so that a title made for 11 inches fits, and shown smaller where the page is narrower. It holds until you set it again; set it before the first plot of a run, as a run's plots are all drawn at the size its first one was.
Plots with plotly#
A plotly chart goes to the Plots tab too, among the other plots in the order your program showed them, and stays a live chart there: point at it to read the values, drag to zoom, double-click to zoom back out, and use the buttons over its top right corner to pan or save it as a PNG. Install it once with install.packages("plotly") in the console, which brings ggplot2 with it. There is nothing to set up after that: a plotly chart left on a line of its own, print()ed, or made from a ggplot() with ggplotly() lands on the Plots tab, at the console as well, where R would open a browser window. The chart is drawn by the copy of plotly.js that came with the plotly you installed, so nothing more is fetched for it, and it keeps plotly's own white background in the dark theme, as the other plots do.
A chart from a cell of a document goes to the Plots tab as well. Update outputs keeps it with the document as a saved chart under its cell, and a notebook's saved plotly chart, as Jupyter writes it, is drawn under its cell as a live chart (see Documents and notebooks).
library(plotly)
plot_ly(x = c("a", "b", "c"), y = c(3, 5, 2), type = "bar") |>
layout(title = "Three bars")Interactive tables and maps#
Packages that make interactive output for a web page, the htmlwidgets such as DT for tables, leaflet for maps, dygraphs, visNetwork, highcharter and reactable, and gt tables, show it on the Plots tab where R would open a browser window: in order with the other plots, as a live page you can sort, page through, zoom and pan. It sits in a frame with a thin border of its own, shut off from the editor and from the internet. It cannot read your project, fetches nothing, and a link in it goes nowhere. The one exception is the map pictures from OpenStreetMap, CARTO, Esri and OpenTopoMap, so addTiles() and addProviderTiles() with those work as they are; tiles from any other server stay blank. Install the package once in the console, install.packages("leaflet").
A cell of a document that makes one sends it to the Plots tab too, and Update outputs keeps it with the document under its cell, where it runs only when you click Show (see Documents and notebooks).
library(leaflet)
leaflet() |> addTiles() |> addMarkers(lng = 8.54, lat = 47.38, popup = "Zürich")Tables#
View() opens a data frame or a matrix in the Tables tab, as it opens a window in RStudio:
View(mtcars) # a table of cars that comes with R
thrifty <- mtcars[order(mtcars$mpg, decreasing = TRUE), ]
View(head(thrifty, 5)) # the five that go furthest on a gallonEach View() gets a tab of its own, named after what you wrote between the brackets, and the size of the table shows at the right. Click a column's name to sort by it, ascending, and again for descending; click #, over the row numbers, for the order the table really has. Sorting only changes what you see, never the table. A table of hundreds of thousands of rows opens just as quickly: the rows come from R as you scroll to them.
Under Variables, a data frame can be clicked too, and opens the same way. Typing at the console to change it updates the view.
View() shows the table as it was at that line. Record a run and step away from that line, and a yellow strip says so, and takes you back there when clicked. A new Run keeps the old tabs, dimmed, with the rows they had already loaded; close a tab with its ×.
Draw#
library(Rprimo) gives your program draw, the canvas itself:
library(Rprimo)
s <- draw$size()
draw$clear("skyblue")
draw$fillStyle <- "gold"
draw$fillCircle(s$width / 2, s$height / 2, 60)
draw$write(20, 20, "hello", size = 24)Quiz: Where things land on the canvas · 3 questionsStart quiz
the canvas coordinates of Rprimo's draw object: (0, 0), the direction of y, and sizes · first programs; variables, arithmetic and function calls only, no loops yet
- Where on the canvas is the point (0, 0), and which way does y grow?
- What would you change in this program to draw the circle in the bottom-right corner? There is more than one good answer.
- Draw a second, smaller circle so that it just touches the first one from the right. Work it out on the canvas, predicting before each run.
The point (0, 0) is the top-left corner; x grows to the right and y grows downwards (this trips everyone up once). draw is a drawing context, the browser's canvas in R: what the canvas documentation calls fillRect is draw$fillRect here, and fillStyle is draw$fillStyle, so anyone who can read those pages can use them as they are. Styles are set by assignment (draw$fillStyle <- "gold", draw$lineWidth <- 4), and draw$color(c) sets the fill and the outline colour at once. Every shape call says in its name whether it fills or strokes: fillRect / strokeRect and fillText / strokeText come from the canvas, and fillCircle / strokeCircle, fillEllipse / strokeEllipse, fillPolygon / strokePolygon, line and write (text) are shortcuts for what the canvas makes you build as a path first; the path calls (beginPath, moveTo, lineTo, arc, fill, stroke, and the rest) are there too. Angles are in degrees, not radians. Drawing calls travel to the page in batches, and Sys.sleep() and every key or mouse read send what is waiting, so a loop that draws and sleeps needs nothing more; draw$flush() shows the picture right now, for the moment before a long calculation. Colours are the CSS ones, by name, "#rrggbb" code or "rgb(r, g, b)"; a mistyped name gives a friendly error. Beside the keyboard (draw$key(), draw$pressed()) there is the mouse: draw$mouse(), draw$mouseDown() and draw$click(), and on a touch screen a finger is the mouse.
Rprimo is a package that exists only here, and its draw has its own page with the full reference and more examples: the drawing page. The small mark on the Draw tab opens it too.
The canvas is as big as the Draw tab, so make the area taller and run again for a bigger picture. Drawings work with stepping too: record a run and watch the picture build up shape by shape.
9Programs that ask questions: readline()#
Example 8 uses readline() to ask the user something. The question appears in the Output tab while the program runs, with a box to type in, and the status line says Waiting for your answer…. Type your answer, press Enter, and the program continues. Escape stops it.
name <- readline("What is your name? ")
times <- as.integer(readline("How many times? "))
for (i in seq_len(times)) {
cat(i, "hello,", name, "\n")
}The program really does wait for you: it stops at the question, and carries on from exactly there once you press Enter. Nothing before the question happens twice, so programs that use random numbers or the clock behave just as they would anywhere else. readline() always hands back text, so a number has to be turned into one, as as.integer() does here.
readLines(stdin()) and scan() read what you type in the same way, one line each time they ask.
On your own computer, readline() only waits in an interactive R session; run the same file with Rscript and it answers with an empty string at once. Here it always asks.
10Working with several files#
The row of tabs above the editor lists the files in your project. At the start there is just main.R. You'll want more files when your program grows (example 9) or when it should read data (examples 11 and 12).
+(a square with a plus, after the tabs) adds a file. Use.Rfor R code, and.txt,.csvor.jsonfor data. A name liketools/helpers.Rputs the file in a folder, and a name typed without an extension gets.R. Two files cannot have names that differ only in capitals,main.RandMain.R, since a Mac or Windows takes them for one file (unzipping a download there would write the one over the other), and a file and a folder cannot share a name, asmain.Randmain.R/x.Rwould; nor can a name start with a dot (.env, or.Ralone), since a folder linked to the project leaves such hidden files out. A file that comes in under such a name, from your computer, a ZIP or a link, gets a number instead (Main-2.R), or lands at the top when its folder cannot be.- Open (the folder beside it) adds files from your computer to the project; see Files from your computer.
- Click a tab to open that file.
- Double-click a tab to rename it. A new name typed without an extension keeps the file's own, so
data.csvrenamedtablebecomestable.csv. - × at the end of a tab closes it; the file stays in the project. Click its name in the project's tree, in the list the project button opens, to open its tab again, at the end of the row; the buttons in its row there rename or delete it. The last tab cannot be closed, so it has no ×.
- Drag a tab along the row with the mouse to put it somewhere else (on a touch screen the row scrolls instead). With the keyboard, Alt+← and Alt+→ on a tab's play mark or its × move it one place. Which tabs are open, and in what order, is kept with the project, and so is where each file's cursor or selection is and how far it is scrolled: a reload, or coming back from another project, finds every file as you left it.
- The play mark at the left of each R tab says which file Run starts with: a plain grey triangle on the others, a yellow one on the file that runs. Normally the file that runs is simply the R tab you are on. Click a mark to pin that file, so that Run starts from it whichever tab is open: its triangle is then punched out of a filled yellow coin. Click it again to unpin. The same mark stands beside the file in the project's tree in the projects list, and a click there does the same. Only
.Rfiles can be started.
Data files are shown in green.
One R file reads another with source("shapes.R"): everything the other file defines is then there, as if you had typed it. Example 9 works that way.
Reading and writing files from your program#
Your program sees the tabs as files in its folder, so this works just as on a normal computer:
scores <- read.csv("scores.csv") # reads the tab called scores.csv
print(scores)
best <- scores$name[which.max(scores$score)]
cat("best:", best, fill = TRUE)
report <- paste(scores$name, "scored", scores$score)
writeLines(report, "report.txt") # creates a new tab called report.txtname,score
ada,91
grace,88
alan,72Quiz: Reading a CSV file · 3 questionsStart quiz
read.csv(), data frames and their columns, writeLines() to a file · a few weeks in; vectors and loops are known, nothing about factors or the tidyverse
- What kind of thing is
scores, and what doesscores$scoregive you? - What happens to report.txt if you run the program twice?
- Change the program so that report.txt also has a last line with the average score. Work it out step by step.
Output:
name score
1 ada 91
2 grace 88
3 alan 72
best: adaA file your program creates shows up as a new tab marked ◦ and stays for the next run. A Markdown, Quarto or notebook file it writes at the top of the project is the exception: that becomes a chapter of the document, not a tab.
Files from your computer#
Open, the folder at the end of the file tabs, lets you pick files from disk and adds them to the project you are in; you can also just drag files onto the editor. A ZIP goes in as it is, packed, a file like any other, for your program to read; Unpack, beside Download on its tab, puts its files in instead, as the folder it packs would come if you dragged it in, and Undo takes them out again. Dropped on a project that is still its one empty file, a ZIP is unpacked into it, and the project takes the ZIP's name unless you named it yourself; dropped on the project button, it is a new project, as with From files or a ZIP… below. A ZIP that Rprimo downloaded is always that project again, as a project of its own. Where a ZIP is unpacked, one that unpacks to over 512 MB, or one packed in a way the page cannot read (Deflate64, which Windows uses for big files, bzip2, a password) is not, and the status line says why; unpack it on your computer and drag the folder in instead. Files are not uploaded anywhere; they stay in your browser. Very large files (over 25 MB) are refused.
To make a new project of them instead, drop them on the project button, or open the projects list with it and choose From files or a ZIP…: the new project is named after the ZIP or the one file you chose, and holds just what you picked. A ZIP that Rprimo downloaded brings that project back as it was, the file that runs and your breakpoints with it; any other ZIP gives its files: when they all sit in one folder, as the Mac's Compress and Windows' Send to → Compressed folder pack them, without that folder, as a folder dragged in comes, and without the __MACOSX folder and ._ files a Mac adds beside them. Undo in the new project starts with what you picked; it does not take you back to an empty project. When nothing you picked can go in (every file too big, say, a ZIP that is empty or cannot be read, or Python code, which Rprimo offers to open in primopy), no project is made and the list stays as it was; the status line says why.
A file that is not text — an image, a PDF, a spreadsheet — comes in too. There is nothing to edit in one, so its tab shows the file itself instead of the editor: images are displayed, a PDF opens in the browser's own viewer (with Print, and Open in a new tab for a phone that shows only its first page, beside Download), sound and video play, everything else gets its name and size, and either way there is a Download button to save it back out. Your program can read it with readBin() like any other file, or with a package that knows the format, and a binary file your program writes turns up as a tab of its own. An SVG file is text, but its tab shows the picture too, drawn on white, and a web page (.html) shows itself; the pencil on the tab puts its source in the editor, and pressed again shows the picture or the page as the source now draws it. Either is drawn live, in a frame of its own: its scripts run, a hover answers and an animation plays, but nothing in it can reach the editor, your projects or anything stored in your browser, and it fetches nothing from the web, so a page that loads a library from elsewhere must carry it inside. An SVG can use only the fonts on your computer: a font it names that is not there is replaced by one of its kind (sans-serif, serif or monospace), not by the browser's serif. The fonts R has are the exception: a drawing ggsave() wrote through svglite names Noto Sans, the font R measured its text with, and the tab takes it from R and shows the picture in it, once R is free (during a run, after it). Elsewhere, a downloaded SVG shows Noto only where Noto is installed; ggsave("plot.svg", device = svg) draws the letters as shapes instead, which look the same everywhere. Download saves the file as it is. Opened again, the tab shows the picture. Printing such a tab prints the picture, and a web page's tab its source; a PDF prints itself with Print, or with Ctrl+P (Cmd+P on a Mac) while its tab is open. A share link carries these files too: a link holding one is a zip, with the files in it exactly as they are. Roughly 300 KB of such files fit in one; past that the link is refused and Download in the projects list is the way.
Reading from the web#
Your program can read from an address with readLines(), read.csv(), url() or download.file():
d <- read.csv("https://raw.githubusercontent.com/tidyverse/readr/main/inst/extdata/mtcars.csv")
head(d)Rprimo asks you first: a dialog shows what the program wants to fetch, and nothing goes out until you click Allow. Tick Allow … without asking and that site is let through until you close the page. Nothing of yours goes with the request: no cookies, no sign-in, not even which page asked.
Many sites do not let other web pages read them, and then the browser keeps the answer from your program, whoever asks. The dialog says so, and you can fetch it yourself: Open the address in a window opens it beside Rprimo (on a phone or tablet, in a tab); select all of it there, copy it, and paste it into the box (or drag its text, or a file you saved from it, onto the box); look it over, and Hand it over gives it to your program, which carries on with that.
Tick Also save the answer to the project as and the answer becomes a tab, which your program can read like any other file. With it comes From now on, answer this request from that file, ticked unless you untick it: the request and the file go into web-replies.json, and from then on the program gets the saved answer without asking and without the internet, in a shared copy of the project too. Take the request out of web-replies.json, or delete the file, and it is fetched again. In the projects list, web-replies.json has a globe and says how many saved replies it holds; point at it to see which requests.
A folder on your computer#
In a Chromium browser, which is Chrome, Edge, Brave, Opera and Chromium itself, the editor can work in a folder on your computer directly, the way a desktop editor does. Firefox, Safari and phones cannot hand a page a folder, so there the folder buttons are not shown and everything else works as before.
From a folder…, in the list the project button opens, asks you for a folder. Its files become a new project, named after the folder (the project you were in stays as it was; Undo there starts with the folder's files), and from then on every change you make is written to the folder about half a second after you make it, the same moment it is saved in the browser. A file your program writes lands there too. Left out are hidden files and folders (.git, .Rproj.user, .RData, .Rhistory and the like), the package libraries renv and packrat keep, node_modules, files over 25 MB, and everything past the first 200 files; the status line says what was skipped. Line endings stay as the file had them.
While a project is linked to a folder, a small drive follows its name on the project button, green while it saves there, and the drive over its files in the projects list shows the folder's name. Edit a file with another program, and the editor picks up the change when you come back to the window or press Run: silently if you had not touched that tab, and with a question if you had. Renaming a tab renames the file; closing a tab leaves the file in the folder. Click the folder's name there to stop: the files stay in both places.
A folder belongs to the project it was opened in or saved from: another project has no folder of its own until you give it one, and a project you delete takes its folder link with it until you bring it back with Undo. If you choose a folder that another project already saves to, the editor says so and offers to open that project or to move the folder over to the new one. When a project is open in two tabs, only the tab you can type in writes to the folder; the other shows its name.
The browser forgets its permission when the page closes. On your next visit the drive on the project button turns yellow, the status line offers reconnect, and the drive over its files in the list says Reconnect, in yellow; one click, and the browser asks once whether the page may use the folder again. Until then your files are on screen from the browser's own copy, and nothing you type is lost: it is written to the folder as soon as you reconnect. If you install Rprimo as an app, the browser can remember the permission for good.
Save to a folder…, the drive at the end of the line of Files in the projects list, is the same thing the other way round: the project stays the one you are in, its tabs stay, and you choose a folder for them to land in. Files the folder already has join the tabs. If both sides have a file of the same name with different contents, or one of a name that differs only in capitals (your main.R, the folder's Main.R), a dialog lists them and asks. Keep both, the default, renames your tab, so main.R becomes main-2.R and the folder's main.R comes in beside it. Open as a new project opens the folder as From a folder… does, in a project of its own, and leaves the one you were in as it was. Cancel leaves everything as it was. A file in the folder is never written over by a tab, and the folder's files never replace your tabs.
Nothing is uploaded either way: the folder is on your computer, the page reads and writes it there, and the copy in the browser stays as a fallback.
The project button beside the logo opens the list of projects, with the project you are in showing its files as a tree: folders and files, each with an icon for what it is (a file, a document file, a folder), and each with a box. Run, beside Open files over the files, says which file Run starts: The open tab (naming the file that is), which follows the tab you are on, or one file, which runs whichever tab you are on. It chooses what the play mark on a file's tab chooses: the yellow triangle follows the tab, the yellow coin is a file pinned; click a tab's mark to pin its file, and again to let Run follow the tab again. The project's quiz and conversations are listed under the files, with the quiz button's and the tutor button's icons. Click a file's name to open it; a file whose tab you closed gets it back, at the end of the row. A file with no tab stays in the project, and a run that meets it does not give it one. A document file (a Markdown, Quarto, R Markdown or notebook file at the top of the project) never has a tab, since the document shows it: click its name to read it in the document. Its icon is a book, open while the file is a chapter of the document and closed while it is not: click the book to leave the file out of the document, or to take it in again. Under the files come the project's quiz and conversations; a click on the quiz's name opens the quiz, as the quiz button does. The buttons in a file's row rename or delete it, a file with a tab too: the × on a tab only closes it. The tick box says whether the project's download and link take the file; you choose, the editor does not guess which files a program reads. That is why Link to this project and Download sit at the top of the column of tick boxes, with with: under them, on a faint band that runs down it: point at either and the band lights up and what it would leave out fades. A folder's box switches every file below it, and shows a dash when only some are included. Drag a file or a folder onto a folder to move it, or onto the heading to bring it to the top; the four-arrow button (Move to…) does the same, which is what a touch screen and the keyboard use. Which tabs are open, which files are chapters and which are included is saved with the project and is never a change to it: it does not make a download look old. Another project's files open with the arrow beside its name, to read; open that project to change them. A click on one of its files' names, or on its quiz's name, opens that project and then the file or the quiz.
Download, at the top of the column of tick boxes, downloads the files that are included in one archive named after the project, My project.zip say, useful for handing in work, moving to another computer, or keeping a backup. (A project of a single file comes down as that file.) To come back later, drag the zip itself onto the editor, or choose it with Open or with From files or a ZIP… in the projects list: the whole project returns, the file that runs and your breakpoints with it, as a project of its own named after the zip, beside the one you are in, which stays as it was. That is what the hidden .rprimo.json in the archive is for, and it is the only thing in there you did not write. Unzipping first and dragging the files in works too, and gets you the files without the rest.
The talks you have had with the tutor are kept with the project and listed under its files, each with a tick box that starts off. Switch one on and Download takes it as a text file in a chats folder of the ZIP, one per conversation, named by the day and by the question it started with, and the link carries the conversation that is open. History lists the project's own talks. Nothing goes back in from a ZIP: a conversation is reopened from History, which is where it lives.
Link to this project copies a link to your clipboard and opens a small panel under the button: Link copied (or, where the browser would not copy it, that you can copy it from the field), the link in a field, already selected (with Copy beside it to try again when the browser would not copy it), and one line on what it carries, such as 2 files and the document. Escape, a click elsewhere or the button again close it; the list stays open. For a moment after a copy the button wears a tick. Paste the link into a message and whoever opens it sees your project exactly as you left it: every tab, the file that runs, the caret where you had it, and your breakpoints. The project travels inside the link itself: nothing is uploaded, so there is nothing to sign up for and nothing to delete afterwards. Very large projects don't fit in a link; use Download for those. A link that lost its end on the way, as a mail or a chat program may do to a long one, opens nothing: the status line says That link could not be read: it may have been cut short, and your own project stays on screen (an example, in a browser that has none yet). Ask for the link again, or for the project as a download. Files your program wrote and you never edited are left out, since running the program makes them again. The packages your project uses travel too, and opening the link installs them there: the project is on screen straight away and the packages arrive a moment later. Opening a link never replaces what is on screen: a link that carries a project opens as a project of its own, and the one you were in stays as it was, in the list behind the button beside the logo. Open the same link again and you are back in that project, with your changes; the status line then says Continuing where you left off and offers Start over, which puts the link's files back after asking (Undo brings yours back while the tab stays open). A link that carries only a document opens as a project of its own too, named after the document, with an empty file beside it for your own code; open the same link again and you are back in that project. A lesson the teacher has fixed on the site is fetched again when you open it, as long as you have not changed that file, and Start over fetches the new one. The link leaves a lesson you have not changed out and names its address instead, which keeps the link short. In a browser that keeps only one project a document is added to it as a file, one chapter more.
11Package management#
A package is R code someone else has written that your program can attach with library(). R already comes with a great deal of it — stats, utils, graphics, grDevices, tools — and those need nothing from you: median() and plot() simply work. This section is about the rest.
The packages tab, the small icon to the left of the console tab, is where they live. It is quiet most of the time: a lone icon when there is nothing to say, a number once there is something to count, and the word packages in red if something failed.
Packages come from the webR package repository at repo.r-wasm.org, which holds CRAN packages rebuilt to run inside a browser. Only packages built there can be installed here.
Most of the time you do nothing#
Running your program installs what it names. Write library(stringr) and press Run, and stringr is fetched before your first line executes. You do not have to ask for it, and you do not have to know it was missing. require(stringr), requireNamespace("stringr") and stringr::str_length(...) count as asking too. That is safe to do unasked because nobody can put a package on CRAN under a name of their choosing overnight: each one is looked at before it is let in, and the webR repository only rebuilds what CRAN has. Nor can a misspelt library() reach for a file of your own, which comes in with source("helpers.R").
library(stringr)
words <- c("apple", "banana", "cherry")
print(str_to_upper(words))
print(str_detect(words, "an"))Output:
[1] "APPLE" "BANANA" "CHERRY"
[1] FALSE TRUE FALSEThe packages tab is for the times you want to look, or to decide: to see what your project is actually using, to take something out again, or to add a package before you have written the line that attaches it.
At the console, install.packages("stringr") works as you know it, and does the same thing as the tab: what it installs shows up there. In a program it works too: Run fetches the package before the program starts, as it does for library(stringr), and a name the program only works out as it goes is fetched when the line runs.
Adding one#
Type a name into the field at the top and press Install or Enter. As you type, the line underneath tells you what will happen:
- "Not built in. Installing it fetches it from the package repo, once." It is downloaded the first time and then belongs to your project.
- "ggplot2 is already in this project." There is nothing to do; the same goes for the packages that come with R.
Package names are case-sensitive: stringr, not StringR.
Versions#
The webR repository keeps one build of each package for this version of R, so there is no version to choose: each installed package shows the version it has. A version typed after a name, like ggplot2==3.0, is left out, and the line under the field says so.
Dependencies#
Packages need other packages. Installing ggplot2 quietly brings a couple of dozen more, and none of those are your doing. They are folded away behind the Dependencies button, which tells you how many there are and shows them if you want to look. Each says what pulled it in.
Taking one out#
The bin at the end of a row removes a package. A row that only waits to be installed, with Install on it, has its bin just before that button, and it takes the name off the project's list without fetching the package first; a package your code names has none, since deleting the library() line is how it goes. Two things are worth knowing:
- Anything your program has already attached keeps working until R restarts. A running R cannot forget a package it has loaded. The row says so and stays on screen until you restart, rather than pretending the package has vanished.
- A package your program names comes back when you run it. Removing
stringrwhilelibrary(stringr)is still in your code asks for two opposite things, and the run wins. Delete thelibrary()line first.
Restart#
Restart, at the top right of the panel, starts R again from scratch: variables, attached packages and anything half-removed are all cleared. Your packages are fetched back afterwards, so restarting does not cost you the list. Your files are untouched — this restarts R, not Rprimo.
The list, and packages.txt#
Your packages are remembered with your project. Reload the page and they are still listed, and fetched again when your program needs them; open the project from a share link and they arrive there too.
If you want the list as a file, the button under the list writes it: Write package list into an explicit packages.txt. It appears as an ordinary tab you can read and edit by hand, one package name per line, with # starting a comment. From then on Rprimo keeps it up to date, and a Run installs everything it names. You never need this file to use Rprimo; it is for seeing the whole list at once, and for handing your project to someone who wants to know what it needs.
What will not install#
A package the webR repository has not got cannot be installed here, and the panel says so on its row:
There is no package called rJava in the R repository for the browser. Worth checking the spelling, and the capitals: R package names are case-sensitive.
Often that is a typo. But it is also what you see for a real CRAN package that has not been built for the browser, usually because it needs something a browser does not have: Java, as rJava does, a database server, or a system library. That is a real limit rather than something to work around. Most of what a course uses is there — ggplot2, dplyr, stringr, lubridate, jsonlite and many more — because it was built for the browser in advance.
arrow is one of those, and as it is often what a course uses for Parquet files, its row says what to use instead: nanoparquet, whose read_parquet() gives an ordinary data frame. dplyr works on that just as on arrow, only without collect().
12The R console#
The console tab at the right of the file tabs turns the editor into an interactive R prompt. You type one line, it answers immediately. It's a calculator for trying out ideas without writing a whole program:
> 3 * 7
[1] 21
> round(2.675, 2)
[1] 2.67
> toupper("hello")
[1] "HELLO"
> x <- c(4, 8, 15)
> mean(x)
[1] 9
> x * 2
[1] 8 16 30- You don't need
print()here; the value is shown automatically. ?roundexplains what a function does, straight from R's own help. Try it on anything you're unsure about.??mediansearches the help for a word, when you don't know the name.- ↑ / ↓ bring back earlier lines.
- After you've run your program, all its variables are available in the console. Run example 12, then type
scoresto look at the data frame it read. This is a great way to poke at your results. - While your program is stopped at a breakpoint, the console can step inside it. A bar at the top says where it stopped; press Attach and the prompt changes to the function's name, like
average() >. Nowtotal + 1uses thetotalof that function at that moment,print()goes to the console rather than the program's output, andtotal <- 100really changestotal: press Continue and the program carries on with the new value. Packages can't be installed while the program waits. Shift+Enter in the editor then runs its line in there too. - Lines run from the editor with Shift+Enter share the console's variables (see Running one line at a time). The console shows a line like
▸ ran main.R:5–6for each; click it to go back to those lines. - Things written over several lines, like a
forloop or a function, work: while the braces are still open the prompt turns into+, and the closing}finishes it. Shift+Enter adds a line without running anything; Escape abandons an unfinished block. - Clear wipes the screen (your variables remain).
readline()typed here asks right here: a box appears in the console, and your answer goes in with Enter..Last.valueis the value of the last line, as in any R session.install.packages("stringr")fetches a package from the webR repository. It does the same thing as the packages tab, and what it installs shows up there.- A few lines from notebooks work here too:
%time sum(xs)runs the expression once and says how long it took;%timeit sum(xs)runs it many times and reports how long one run takes (-n 100fixes the number of loops,-r 3the number of runs);%run main.Rruns a file of your project in the console, so that its variables are there to look at afterwards. Words after the file name are handed to it as arguments, which the file reads withcommandArgs(trailingOnly = TRUE);Rscript main.R one two, written the way a terminal takes it, does the same. %wholists the console's variables, and%whoslists them with a glimpse of each value (%who numericshows only the numbers).%resetforgets them all and leaves the screen alone, the opposite of Clear.%historyprints the lines you have typed, oldest first, ready to copy into a file (-n 10for the last ten). A%on its own lists what the console answers.%watch total square.xputstotal, andxwhilesquareruns, first in the Variables pane, marked, while you step through a recording or stop at a breakpoint. A global goes by its name, a function's local by the function's name, a dot and its own. Inside a function, a watched global still shows, marked global.%watchalone lists the names,%unwatch xdrops one and%unwatchall of them. The eye at the right of the Variables heading does the same without the console: it opens a field for the names, and a watched row has a × that drops it. The list is not saved and goes in no link: it lasts until you reload the page or open another project.
13Code completion#
While typing a name, press Tab (or Ctrl/Cmd+Space) and a list of matching names pops up. Typing a $ after a name, like draw$, opens the list automatically, showing what's inside; so does :: after a package name, like stringr::.
Move with ↑ / ↓, accept with Tab or Enter, close with Escape. When available, a one-line description of the chosen item is shown underneath.
Completion works out its answers in the same R that runs your programs, so while a program is running it has to wait its turn. Ask for the list then and it will say so instead of opening; it comes back by itself as soon as the run ends.
14Undo#
Ctrl/Cmd+Z undoes your typing, just like in any text editor, and Ctrl/Cmd+Shift+Z redoes it. Each file remembers its own history, even if you switch between files.
The Undo button in the header goes further: it also takes back things like deleting or renaming a file, replacing your files with an example (where the browser keeps only one project), or clearing your saved work. When the next press would bring files back, the button turns dark blue and says so: Restore 2 files. So if you ever replace your files with an example and see them vanish, the button is already telling you the way back. An example opened from the menu is a project of its own and replaces nothing: yours is in the list behind the button beside the logo. Hover it to see exactly what the next press will undo.
Adding a chapter to the document, editing it, updating its outputs and closing it are steps like those for any file: the document is files of your project. The only thing that can't be undone is a file that your own program overwrote. Moving a file or a folder in the list of projects is a step like renaming one; the boxes there (Run's choice, the tick boxes, a document file's chapter), like which tabs are open, are how the project is looked at, not what it holds, so Undo leaves them as you set them.
Undo belongs to the tab you are in. When another tab takes over the project (see Is my work saved?), this tab's Undo history is cleared, and a tab that only shows the project has nothing to undo. Going to another project and back keeps the steps of the project you left, as long as no other tab changed it meanwhile.
A file you delete outlasts that history: the project keeps it for a day, so a reload, a closed tab or another tab taking over does not lose it. Once the button has nothing else left to undo, it reads Restore 1 file and brings back the files deleted lately whose names are still free. It keeps the last ten, up to 1 MB in all; a larger file comes back only while the tab you deleted it in stays open.
15The tutor#
Tutor opens a chat with an AI tutor in the bottom right. It's set up to teach rather than to hand over answers: expect questions back, hints, and nudges in the right direction. It's a good place to ask "why is this wrong?" or "what does this line do?"
It is a language model, not an oracle. Ask the same thing twice and the wording will differ; sometimes it will answer straight out instead of asking back, and sometimes it will simply be wrong. When what it says and what your program does disagree, your program is right. Run it and step through it.
The tutor runs on Rprimo's own servers, so it asks you to Sign in with your university account the first time. Everything else on the page works without one.
Type your question and press Enter (Shift+Enter for a new line). While the tutor is answering, Ask turns into Stop.
Two checkboxes under the input:
- send my code (on by default): sends the tutor your files, where your cursor is, your last output or error, the last few lines you typed in the console with what they printed, and, if you're stepping through a recording, the current line and its variables. With this on, "why is this wrong?" is a complete question.
- thinking: lets you see the tutor's reasoning, shown dimmed above its answer.
Link to this project also carries the conversation that is open, once you have ticked its box in the list: a way to show someone what you asked and what came back, without a screenshot. Only what was said travels: nothing is uploaded, but do read the conversation before you send the link on, the same as you would a screenshot.
New starts a fresh conversation, and History brings back an earlier one of this project, since conversations are kept with the project they were had in: nothing you asked is thrown away when you start again. Download in the projects list takes the conversations you have switched on, as text files. Quiz, between them, is for a project that comes with questions; that is section 16. Your tutor messages are the one thing that leaves your browser; they go to the tutor server, where they are used to write the answer and then dropped. Nothing you type is filed away, no record of how you are doing follows you from one day to the next, and nothing you ask is passed to your teacher. Everything else stays on your computer.
The tutor needs the page to be served from a web server; it doesn't work if you opened the page as a file from your disk.
A link can also carry a quiz for the tutor to ask you about the project. That is the next section.
16Quizzes#
A quiz is a set of questions a teacher has written about a project, and a link carries it the same way it carries the files. Open such a link and the tutor's pane opens with the quiz waiting in it: Start quiz, beside New at the top of the pane, lit gold until you press it. Nothing is asked until you do. The tutor knows the questions, and where the teacher wrote one, it knows the reference answer too.
Press it and the first question is there in the conversation, where your answer goes under it. Answer in your own words in the chat, or write code in the editor and say so; the tutor sees your files as always. It helps you along rather than marking you: it says whether you are close, gives a hint when you ask for one with Give me a hint, and keeps the reference answer to itself until you press I'm done, check my answer, when it compares what you said with what the teacher wrote, or I give up, show me the answer. Some questions are meant to be worked out rather than answered, and for those the tutor is meant to give you the next step instead of the finished thing, even when you give up. Nothing is scored and nothing is reported to anyone: the quiz is for you.
One question at a time. Next question → appears above the box once the tutor finds your answer right or nearly so, or once you have said you are done with the question or given it up. Its reply then has a green edge where your answer holds, and a yellow one where something is still missing; that colour is all there is of a mark, and it stays on your screen. Beside the question you are on, ‹ Back goes to the one before and Skip › to the one after, so a question you are stuck on never holds you; one you went past without a word is not left behind in the conversation. The questions stay in the conversation as you go, with your answers between them, to scroll back through. On the last question, once you are done with it, Finish: how did I do? asks the tutor to sum up: what held up, and what to go back to.
Some quizzes have no fixed questions at all, only a topic and a level. The tutor then makes them up as it goes, one per turn, and asks the first as soon as you start; Next question → asks for the next, once you are done with the one you have, and Skip › asks for it at any time.
Taking a quiz is a conversation like any other, so it is left the way any conversation is left: New starts an ordinary one, and History keeps the quiz, marked there with the quiz's own icon. Open it there and you are back in the quiz where you left off, as long as the project still holds the same questions; if it no longer does, the conversation is still there to read, but not to go on with: the box under it is shut, because an answer typed there would be about the project you have now. New opens one you can ask in. Restart quiz — the same button, while you are in one — begins again at the first question, and what you did before stays in History. An example from the menu or another link opens a project of its own, and the quiz stays with the project it came with: go back to that project and it is there, with its conversation. Replacing the files here with an example takes the quiz away with them, and the run you were in stays on the pane the same way: readable, and closed to further questions. A quiz survives a reload. A link that carries files and a quiz opens as a project of its own, so your previous project is still in the list, quiz and all.
Try one here. This quiz has no files of its own, so the editor opens with an empty main.R to try things in:
Quiz: Loops, one at a time · the tutor asksStart quiz
for loops over seq_len() and over vectors; while loops · first weeks of R, before functions; no apply family
Writing a quiz#
Anybody can write a quiz and share it with others. The pencil beside the quiz button, at the top of the tutor's pane, opens a sheet over the pane where you write the quiz as plain text, one line per thing. The editor stays beside it, so you can look at the code you are asking about while you write the questions:
Title: Reading a file
Topic: reading text files with readLines() and writing them with writeLines()
Depth: second week; readLines(), nchar(), trimws(); nothing about encodings
Note: Question 3 is to be worked out with the student; never hand over the finished loop.
Q: What does readLines("list.txt") give you, exactly?
A: A character vector with one string per line of the file, without the line endings.
Hint: Print it and count the quotes.
Q: Why does readLines() warn about an "incomplete final line"?
Q: Write a loop that prints only the lines longer than five characters. Work it out step by step.- Title, Topic, Depth and Note each take a line, or several: a line without a key continues the one above it.
- Each Q: is a question. An A: under it is the reference answer, and a Hint: is what the tutor should say first when asked for one. Both are optional: without a reference the tutor assesses with what it knows, and a question with several good answers is treated as one.
- A question can run over several lines, so it can be a piece of code with gaps in it: write
for (i in ____(10)) {and the blanks are what the student supplies. Mark a gap however you like. The code around it is given, and the tutor neither fills a gap in early nor rewrites the lines you wrote. - Topic and Depth are in your own words: what the questions are about, and what the student can be assumed to know or must not be asked for. Depth is a ceiling as well as a floor: "before functions" means the tutor will neither ask for one nor explain with one. Depth can also say which way the student learns: "theory first" has the tutor go from the rule to an example, in its questions, hints and explanations alike, and "applied" or "from examples" from an example to the rule.
- Note is for the tutor alone: the class, what to insist on, which questions are to be worked out rather than answered.
- A quiz with only a Topic and a Depth is complete. The tutor then asks its own questions.
Return keeps the quiz with the project; there is nothing else to press, and Esc does the same. The button at the top of the pane then reads Start quiz, a reload keeps it, and every link made from the project carries it — including a link you make while the sheet is still open, which carries what is on the sheet at that moment. Editing a quiz you are in the middle of taking changes the questions without ending the conversation.
The sheet is silent while what you have written can be a quiz, and says what is wrong when it cannot: returning then leaves the sheet where it is, with the reason beside the button, and a link waits until the quiz is finished. Remove, beside the sheet's name, takes the quiz out of the project again, and so does emptying the box; it is also the way out of writing you have decided against, finished or not. Undo puts back the quiz you had before writing, editing or removing.
Note the link is the whole quiz, reference answers included: anyone who can read a link can read them, so a reference answer is there to help the student check themselves, not to be kept from them.
17Documents and notebooks#
A link, or a Markdown, R Markdown, Quarto or Jupyter notebook file you drop on the editor, can open as a document: text to read on a tab of its own, in place of the editor, with examples you run where they stand with Run here. The cells share their names with the console, a cell first runs the ones above it that have not run yet, and the document is files among yours: the Markdown, Quarto, R Markdown and notebook files at the top of your project are its chapters, and the files it brings become tabs like any other. The chapter files themselves have no tab of their own: the document's tab shows them, and the project's tree in the projects list lists them. Teachers write documents in Markdown or R Markdown and hand them out as a link.
All of it is on its own page: documents and notebooks, which you can also open in the editor as a document and try it out there.
18Is my work saved?#
Yes, automatically, in your browser, about half a second after every change. Reopen the page and everything is as you left it: all files (the document's among them, and where you were reading it), breakpoints, the list of packages, console history and the recent tutor conversation. You'll see Your files are back. There is no need to press Ctrl/Cmd+S, but it does no harm: it saves at once and says Saved. The theme, the sizes of the areas and the language are kept too, but for the browser rather than for the project: they are the same whichever project you open.
Eight things to keep in mind:
- It's saved in this browser on this computer. Another browser or another computer starts empty. To move work, use Download in the projects list (the document comes with the files; From files or a ZIP… brings the ZIP back elsewhere), or, in a Chromium browser, keep the project in a folder on your computer.
- The packages themselves are not kept, only their names. After a reload they are fetched again the first time your program needs them, which the browser's own cache makes quick.
- What is kept somewhere else. The projects list says, under the project's files, whether your work also exists outside this browser: Downloaded copy is up to date or Changed since you downloaded it after Download, the same for a link you copied, Also in folder … when a folder follows the project, and Only in this browser when none of them does. The same line stands beside each project in the list, and the list's footer says how much room the browser gives this site. A download or a link that leaves out a file whose tick you took off does not count as a copy. It is a reminder and never a warning for work you have downloaded or kept in a folder. The browser is asked to keep this site's storage at your first change (some show a question; if you decline, it is not asked again for a week), because a browser that is short of room may otherwise clear a site's data; Safari clears it after a week without a visit.
- Your projects. The browser keeps every project you start: a new one, each example you open, each link that carries a project, a copy. The button beside the logo names the one you are in and opens the list of them under it, newest first, with when each last changed (the day and the time) and how big it is; the same button closes the list again. Click a project to open it, or start one: New project (empty), From files or a ZIP… or, in Chromium browsers, From a folder…. Where the browser keeps only one project, the button opens that one, with its link, Download and folder. The project you are in has Rename (a pencil) and Delete at the end of its row. Over its files sit New file and Open files, as at the end of the tabs (the list stays open, and what they add shows among the files; a new file's name such as
data/a.csvmakes the folderdatatoo), and Run; at the end of the line of Files, in Chromium browsers, its folder: the drive (Save to a folder…), or the drive with the linked folder's name (click it to stop) or with Reconnect; its link (the chain link) and, below it, Download (a ZIP) sit over its files' tick boxes. Where the list is wide enough, as on a computer, these buttons say their names beside their icons (New file, Open, Save to a folder, Permalink, Download); on a phone, the icons alone. Another project shows its buttons once its files are open with the arrow beside its name: Rename and Delete in its row, its link and Download over its files; its link carries what is saved of it, as its Download does, with the file that was open and its cursor or selection. Rename makes the name a field: what you type there is the project's new name once you press Enter, click elsewhere or press Rename again; Escape brings back the old one. Two projects never share a name: a name another project has (in any mix of capitals) is refused and the field says so; a second example, copy or link of the same name gets a number (Hello 2). An example you open and leave as it came (nothing typed, added, renamed, installed or removed, or asked of the tutor) is not kept: it goes when you open another project, and the menu brings it back as it was. A deleted project keeps its row for a day, with Undo: after a reload, after closing the tab, and in your other tabs too, and only then is it gone for good. Until then its files still count towards what the browser keeps, so a line under the list says how many deleted projects are kept, with Empty the trash, which removes them for good at once; when the browser is out of room, the status line offers Empty the trash too, and saves again in the room it frees. A project that took its name meanwhile leaves it the name with a number; if its folder was linked to another project in the meantime, Undo asks whether to take the folder back (the other project then has none) or to bring the project back without it. Each tab works on one project at a time, and a new tab opens the most recent one no other tab has open. - One tab at a time writes a project. When a tab opens a project another tab has open, it shows it read-only, and follows it as you type in the other: a bar under the header says Open in another tab · read-only. Run, editing and the other buttons that change the project are off there. Press Edit here and the other tab saves and hands over, and becomes the read-only one; Make a copy makes a project of its own from what the tab shows. This is what stops two tabs from saving over each other. A tab opened while every project is open elsewhere shows the most recent one read-only, with the list over it. A link that carries a project, opened in a read-only tab, opens as a project of its own and the tab goes to it; a link that carries only a document does the same. If a tab holds changes it could not save, because another tab (or an older copy of the page) saved over them or the project was deleted, the bar says so and the changes stay on screen: Make a copy with them keeps them as a project of their own, Download my files keeps a copy on your computer, and the browser asks before such a tab is closed. In a browser that keeps only one project there is no copy to make, and Keep mine saves them over the other tab's instead.
- Large files are fine, and closing a tab loses nothing. Your files are kept as separate records in the browser's database, so a project can hold files of up to 25 MB each (a plot a program saved, a data file) and a save only writes what changed. A file your program writes is saved the moment it is written. If you close a tab in the middle of typing, what it had not yet saved is kept aside and put back the next time the project opens. In a browser that has no database to offer (or on a page that only lends storage), the project is kept as before in one piece, and files over 400 KB are refused.
- Some browser setups block saving, for instance a private window that allows no storage, the page opened directly from a file, or inside another site. The status line then says This browser cannot save your work: it goes when the tab closes, with Download files, and the logo says files not saved when you hover it (where saving works it says files saved in this browser). Use Download files before closing the page.
- A save that fails says so. If the browser refuses a save, because it is out of room, because its storage stopped answering (Safari does this now and then, and the page first opens the storage again and tries once more), or, in a browser that keeps the project in one piece, because the project has grown too large for that piece, the status line says Not saved (or This browser is out of room for your files) with Download files, and the logo says files not saved. Your files stay on screen as they are. The page tries again at your next change and every 15 seconds, and once a save goes in the status line says Your files are saved again.
Nothing you write is sent anywhere, apart from messages to the tutor.
19Changing the layout, theme and language#
Every boundary between two areas can be dragged: the sidebar's width, the height of the tape, the output area, the call stack, and the tutor. On a narrow screen the areas stack on top of each other instead.
The ◐ button at the right of the header switches the look: it steps from auto (follow your system) to light (☀) to dark (☾).
The globe beside it picks the language of the editor: English, Deutsch, Français or Italiano, each listed under its own name. The first time, Rprimo follows your browser's language. Choosing another reloads the page in it; your work is saved first and comes straight back. Your R code, R's own messages and this handbook stay as they are.
20Keyboard shortcuts#
Anywhere#
| Key | Action |
|---|---|
| Ctrl/Cmd+Enter | Run (recording, if Record is on); Continue, while stopped at a breakpoint; Stop, while running |
| ← / → | Step back / forward through a recording (when not typing) |
| Ctrl/Cmd+Z | Undo |
| Ctrl/Cmd+S | Save now, to the folder too if the project has one; the status line says Saved (the browser's own Save Page As would keep the web page, not your code) |
| Alt+← / Alt+→ on a file tab's play mark or × | Move the tab one place along the row |
Editor#
| Key | Action |
|---|---|
| Tab | Indent, or complete the name being typed |
| Shift+Tab | Un-indent |
| Enter | New line at the same indentation, one level deeper after an open bracket |
| Shift+Enter | Run the line the cursor is on, or the selected lines; while a recording is up, take the tape to that line, and to its next visit on each further press |
| Ctrl/Cmd+Space | Open the completion list |
| Ctrl/Cmd+F | Find and replace in this file |
| Enter / Shift+Enter in the search field | Next / previous match |
| F3 or Ctrl/Cmd+G | Next match (with Shift: previous) |
| Escape | Close the search bar |
| Cmd+Option+[ / ] (Mac), Ctrl+Shift+[ / ] | Fold / unfold the block that starts on the cursor's line |
| Ctrl+Alt+[ / ] (Mac: Ctrl+Option) | Fold / unfold every block in the file |
Console#
| Key | Action |
|---|---|
| Enter | Run the line |
| Shift+Enter | Add a line without running |
| ↑ / ↓ | Earlier lines |
| Tab | Complete |
| Escape | Abandon an unfinished block |
Tutor#
| Key | Action |
|---|---|
| Enter | Send |
| Shift+Enter | New line |
Guided tour#
| Key | Action |
|---|---|
| Enter or → | Next stop (after Back too) |
| ← | The stop before |
| Escape | End the tour |
21Things Rprimo can't do#
- Recording stops after 5,000 steps. For long-running programs switch Record off.
- Steps are whole lines. Rprimo cannot show you the pieces of a line one at a time; split a busy line into several to see each part.
- Only the file that runs is recorded. A file read with
source()runs normally, but its lines are not steps on the tape, and breakpoints in it do not stop the program. - An error your own
tryCatch()ortry()catches leaves no mark on the tape. Only the error that ended the run is shown in red. - The Variables box shows at most 26 variables, and long values are shortened to their first 150 characters or so.
- Plots: twelve per run.
- No profiler.
Rprof()is not available in this R, so there is no%prun;%timeand%timeitsay how long something takes. - The internet only with your yes, and only through R's own functions.
readLines(),read.csv(),url()anddownload.file()of an address wait until you allow them, and a site that does not let other web pages read it has to be fetched by hand; see Reading from the web. Packages likehttrandcurlcannot connect at all; a browser safety rule. Maps draw their pictures from the few map servers named under Interactive tables and maps. - Only packages built for the browser. Anything that is not in the webR repository cannot be installed.
- No windows beyond the Plots, Draw and Tables tabs.
View()opens the Tables tab, and a plotly chart or other interactive output lands on the Plots tab. - Everything lives in one browser. Use Download in the projects list to move work elsewhere, or a folder on your computer in a Chromium browser such as Chrome, Edge, Brave or Opera.
- The tutor can be wrong. It is a language model: its answers are not fixed, and it can be mistaken about your code. Check what it tells you by running the program.
22When something goes wrong#
It never gets past "Downloading R". R is fetched from the internet the first time. Check your connection and reload.
The status says reading input and drawing need a "cross-origin-isolated page". The page was served without the setting that lets R wait for you. Programs still run, but readline() starts the program again with each answer, and breakpoints do not stop it. Ask whoever gave you the page for the proper web address.
My files are gone after reloading. Saving is blocked in this browser setup; hover the logo to check. Ask whoever gave you the page for a proper web address, and use Download in the projects list in the meantime.
read.csv("data.csv") says cannot open file. The name must match a tab exactly, capital letters and folder names included.
source("helpers.R") doesn't work. The file must be called helpers.R, and you write the whole name, .R included, in quotes. The name is counted from the project's top, as R counts it from the working directory, also in a program in a folder: hw3/main.R reads source("hw3/helpers.R").
there is no package called ‘glue’. Run fetches every package your code names with library(); if it still says this, look at the packages tab, which says why this one could not be installed. Check the spelling and the capitals first.
The tutor says it can't reach the server, or asks me to sign in. The page has to be opened from a web address, not from a file on your disk, and the tutor needs your university account.
My program is stuck, or prints for ever. Press Stop; while a program runs, that is what the Run button becomes. An endless loop stops there and then, with your files and everything the run had built up untouched; there is no need to reload the page. If R does not come back, the status line offers Restart R; press it and R starts again, without the console's names. With Record on, a run also stops itself after 5,000 steps.