Skip to content

Commit

Permalink
Add the autorun option for interactive documents. (#153)
Browse files Browse the repository at this point in the history
  • Loading branch information
coatless authored Feb 5, 2024
1 parent 1381e37 commit aafa8d9
Show file tree
Hide file tree
Showing 7 changed files with 138 additions and 40 deletions.
2 changes: 1 addition & 1 deletion _extensions/webr/_extension.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: webr
title: Embedded webr code cells
author: James Joseph Balamuta
version: 0.4.0-dev.8
version: 0.4.0-dev.9
quarto-required: ">=1.2.198"
contributes:
filters:
Expand Down
44 changes: 29 additions & 15 deletions _extensions/webr/qwebr-cell-initialization.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ qwebrCellDetails.map(
// Identify non-interactive cells (in order)
const filteredEntries = qwebrCellDetails.filter(entry => {
const contextOption = entry.options && entry.options.context;
return ['output', 'setup'].includes(contextOption);
return ['output', 'setup'].includes(contextOption) || (contextOption == "interactive" && entry.options && entry.options.autorun === 'true');
});

// Condition non-interactive cells to only be run after webR finishes its initialization.
Expand Down Expand Up @@ -49,35 +49,49 @@ qwebrInstance.then(
const cellCode = entry.code;
const qwebrCounter = entry.id;

// Disable further global status updates
const activeContainer = document.getElementById(`qwebr-non-interactive-loading-container-${qwebrCounter}`);
activeContainer.classList.remove('qwebr-cell-needs-evaluation');
activeContainer.classList.add('qwebr-cell-evaluated');
if (['output', 'setup'].includes(evalType)) {
// Disable further global status updates
const activeContainer = document.getElementById(`qwebr-non-interactive-loading-container-${qwebrCounter}`);
activeContainer.classList.remove('qwebr-cell-needs-evaluation');
activeContainer.classList.add('qwebr-cell-evaluated');

// Update status on the code cell
const activeStatus = document.getElementById(`qwebr-status-text-${qwebrCounter}`);
activeStatus.innerText = " Evaluating hidden code cell...";
activeStatus.classList.remove('qwebr-cell-needs-evaluation');
activeStatus.classList.add('qwebr-cell-evaluated');
// Update status on the code cell
const activeStatus = document.getElementById(`qwebr-status-text-${qwebrCounter}`);
activeStatus.innerText = " Evaluating hidden code cell...";
activeStatus.classList.remove('qwebr-cell-needs-evaluation');
activeStatus.classList.add('qwebr-cell-evaluated');
}

switch (evalType) {
case 'interactive':
// TODO: Make this more standardized.
// At the moment, we're overriding the interactive status update by pretending its
// output-like.
const tempOptions = entry.options;
tempOptions["context"] = "output"
// Run the code in a non-interactive state that is geared to displaying output
await qwebrExecuteCode(`${cellCode}`, qwebrCounter, tempOptions);
break;
case 'output':
// Run the code in a non-interactive state that is geared to displaying output
await qwebrExecuteCode(`${cellCode}`, qwebrCounter, entry.options);
break;
case 'setup':
const activeDiv = document.getElementById(`qwebr-noninteractive-setup-area-${qwebrCounter}`);
//activeDiv.textContent = "Computing hidden webR Startup ...";
// Run the code in a non-interactive state with all output thrown away
await mainWebR.evalRVoid(`${cellCode}`);
//activeDiv.textContent = "";
break;
default:
break;
}
// Disable visibility
activeContainer.style.visibility = 'hidden';
activeContainer.style.display = 'none';

if (['output', 'setup'].includes(evalType)) {
// Disable further global status updates
const activeContainer = document.getElementById(`qwebr-non-interactive-loading-container-${qwebrCounter}`);
// Disable visibility
activeContainer.style.visibility = 'hidden';
activeContainer.style.display = 'none';
}
}
}
).then(
Expand Down
9 changes: 9 additions & 0 deletions _extensions/webr/webr.lua
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ local qwebRDefaultCellOptions = {
["output"] = "true",
["comment"] = "",
["label"] = "",
["autorun"] = "",
["classes"] = "",
["dpi"] = 72,
["fig-cap"] = "",
Expand Down Expand Up @@ -568,6 +569,14 @@ local function enableWebRCodeCell(el)
if cellOptions["label"] == '' then
cellOptions["label"] = "unnamed-chunk-" .. qwebrCounter
end
-- Set autorun to false if interactive
if cellOptions["autorun"] == "" then
if cellOptions["context"] == "interactive" then
cellOptions["autorun"] = "false"
else
cellOptions["autorun"] = "true"
end
end

-- Remove space left between options and code contents
cellCode = removeEmptyLinesUntilContent(cellCode)
Expand Down
5 changes: 3 additions & 2 deletions docs/qwebr-cell-options.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ These options can be customized to tailor the behavior of the code block based o
The `{quarto-webr}` extension does not support all of the cell options from [Quarto](https://quarto.org/docs/reference/cells/cells-knitr.html) or [Knitr](https://yihui.org/knitr/options/). Please consult the tables below for details on what is available.
:::

## webR
## quarto-webr

| Option | Default Value | Description |
|-----------|---------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `context` | `interactive` | Describe how the cell should operate on the page through either `interactive` (Runnable code editor), `output` (Output only of executed at runtime), or `setup` (execute code without seeing output at runtime). |
| `autorun` | `false` | Allow `interactive` cells to be run during document initialization without a user pressing run code. |


:::{.callout-note}
The `context` option is unique to the `{quarto-webr}` extension. For more details, please see [Hiding and Executing Code](qwebr-internal-cell.qmd).
Options listed here are unique to the `{quarto-webr}` extension. For more details, please see [Hiding and Executing Code](qwebr-internal-cell.qmd).
:::

## Attributes
Expand Down
104 changes: 83 additions & 21 deletions docs/qwebr-internal-cell.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,41 @@ Please note that the contents of the hidden code cell can be viewed if the web p

You can create hidden setup code cells within your document using the special comment `#| context: setup`. The code within these cells executes discreetly in the background without displaying the code or its output.

::: {.panel-tabset group="setupIntro"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: setup
meaning_of_life = 42
```
#### Cell Code
```{{webr-r}}
#| context: setup
meaning_of_life = 42
```
:::

:::{.callout-note}
Once a `context:setup` is done running, the visual indicator will be removed from the document.
:::

In the example above, we've pre-loaded the `meaning_of_life` variable with a value of `42`. If you proceed to run the subsequent code cell, you'll observe the value of `meaning_of_life` being displayed as `42`.

::: {.panel-tabset group="setupIntro"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: setup
meaning_of_life = 42
#| context: interactive
#| autorun: true
meaning_of_life
```

```{webr-r}
#### Cell Code
```{{webr-r}}
#| context: interactive
#| autorun: true
meaning_of_life
```
:::



By incorporating the `setup` hidden code cell for data loading and preprocessing, you enhance the user experience by providing them with an accessible and interactive environment for working with the data while maintaining a clutter-free and organized document structure.

Expand All @@ -61,22 +81,26 @@ You also have the choice of crafting an output-only code cell within your `quart

For instance, the following code cell suppresses the creation of the matrix; but, displays the end result.

```{{webr-r}}
::: {.panel-tabset group="outputIntro"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: output
mat2x2 <- matrix(c(1, 2, 3, 4), nrow = 2)
mat2x2
```

```{webr-r}
#### Cell Code
```{{webr-r}}
#| context: output
mat2x2 <- matrix(c(1, 2, 3, 4), nrow = 2)
mat2x2
```

:::

In the next example, the code used to generate the graph is suppressed.

```{{webr-r}}
::: {.panel-tabset group="outputIntro"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: output
plot(
mpg ~ wt,
Expand All @@ -88,8 +112,8 @@ plot(
sub = "Source: 1974 Motor Trend US magazine."
)
```

```{webr-r}
#### Cell Code
```{{webr-r}}
#| context: output
plot(
mpg ~ wt,
Expand All @@ -101,6 +125,8 @@ plot(
sub = "Source: 1974 Motor Trend US magazine."
)
```
:::


By using `output` code cells, you maintain a streamlined and comprehensible document, focusing on the outcome rather than the intricate data processing steps. This approach will enhance the readability and clarity of your content, making it more accessible and informative to your audience.

Expand All @@ -114,7 +140,9 @@ The `setup` hidden code cell is a powerful tool for seamlessly pre-loading and p

In the following example, we demonstrate the process of loading and preprocessing a dataset. First, we download the dataset from an external source and save it as `'penguins.csv'` in the virtual webR file system. Next, we read the data into a data frame named `df_penguins`. All these operations occur silently in the background, ensuring that your document remains clean and focused on the data's application.

```{{webr-r}}
::: {.panel-tabset group="setupDataDemo"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: setup
# Download a dataset
Expand All @@ -123,11 +151,10 @@ download.file(
'penguins.csv'
)
# Read the data
df_penguins = read.csv("penguins.csv")
```

```{webr-r}
#### Cell Code
```{{webr-r}}
#| context: setup
# Download a dataset
Expand All @@ -136,14 +163,46 @@ download.file(
'penguins.csv'
)
# Read the data
df_penguins = read.csv("penguins.csv")
```
:::

Next, let's setup an interactive cell that can be modified and run.

::: {.panel-tabset group="setupDataDemo"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: interactive
# Display the head of the data
head(df_penguins)
```
#### Cell Code
```{{webr-r}}
#| context: interactive
# Display the head of the data
head(df_penguins)
```
:::

In this case, we may want to encourage the "Run code" functionality by having the interactive cell automatically run during document initialization by using `#| autorun: true`.

::: {.panel-tabset group="setupDataDemo"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: interactive
#| autorun: true
# Display the head of the data
head(df_penguins)
```
#### Cell Code
```{{webr-r}}
#| context: interactive
#| autorun: true
# Display the head of the data
head(df_penguins)
```
:::


::: {.callout-note}
If the setup code relies on specific R packages, we **strongly** recommend specifying the required packages in the document's YAML. This approach informs users that the webpage is not yet ready and communicates a clear status update at the top. For example:
Expand All @@ -164,31 +223,34 @@ You can use the output hidden code cell to generate summarized information about

For instance, in the code cell below, we transform the `mtcars` dataset, converting variables, and then promptly produce a summary of the modified data.

```{{webr-r}}
::: {.panel-tabset group="hiddenSummarizationDemo"}
#### `{quarto-webr}` Output
```{webr-r}
#| context: output
mtcars2 <- within(mtcars, {
vs <- factor(vs, labels = c("V", "S"))
am <- factor(am, labels = c("automatic", "manual"))
cyl <- ordered(cyl)
gear <- ordered(gear)
carb <- ordered(carb)
})
summary(mtcars2)
```

```{webr-r}
#### Cell Code
```{{webr-r}}
#| context: output
mtcars2 <- within(mtcars, {
vs <- factor(vs, labels = c("V", "S"))
am <- factor(am, labels = c("automatic", "manual"))
cyl <- ordered(cyl)
gear <- ordered(gear)
carb <- ordered(carb)
})
summary(mtcars2)
```
:::


## Hidden Solution Checking of Student Work
Expand Down
5 changes: 4 additions & 1 deletion docs/qwebr-release-notes.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ format:
- Implemented a custom JSON format for code cell data and option sharing between Quarto and webR. ([#120](https://github.com/coatless/quarto-webr/pull/120))
- Redesigned non-interactive cells to provide improved reliability and visual cues. ([#120](https://github.com/coatless/quarto-webr/pull/120))
- Interactive cells now have a toolbar above them that provides three actions: Run Code, Start Over, and Copy. ([#91](https://github.com/coatless/quarto-webr/issues/91))
- Initial [code cell option](https://quarto-webr.thecoatlessprofessor.com/qwebr-cell-options.html) support ([#104](https://github.com/coatless/quarto-webr/issues/104), [#117](https://github.com/coatless/quarto-webr/issues/117), [#125](https://github.com/coatless/quarto-webr/issues/125)):
- Initial [code cell option](https://quarto-webr.thecoatlessprofessor.com/qwebr-cell-options.html) support ([#104](https://github.com/coatless/quarto-webr/issues/104), [#117](https://github.com/coatless/quarto-webr/issues/117), [#125](https://github.com/coatless/quarto-webr/issues/125), [#151](https://github.com/coatless/quarto-webr/issues/151)):
- quarto-webR: `context` and `autorun`.
- Attributes: `label` and `classes`.
- Figures: `fig-cap`, `dpi`, `fig-width`, `fig-height`, `out-width`, & `out-height`.
- Cell output: `warning`/`message`, `results`, and `output`
Expand Down Expand Up @@ -50,6 +51,8 @@ format:
- Added a demo for showing [initial code cell option support](https://quarto-webr.thecoatlessprofessor.com/demos/qwebr-code-cell-options.html). ([#141](https://github.com/coatless/quarto-webr/pull/141))
- Modified the RevealJS presentation YAML to include an option to disable the webR status message header ([#110](https://github.com/coatless/quarto-webr/issues/110))
- Updated [blog posts](https://quarto-webr.thecoatlessprofessor.com/qwebr-community-examples.html#blog-posts) on [community examples](https://quarto-webr.thecoatlessprofessor.com/qwebr-community-examples.html) page ([#135](https://github.com/coatless/quarto-webr/pull/135))
- Updated [Hiding and Executing Code
](https://quarto-webr.thecoatlessprofessor.com/qwebr-internal-cell.html) to use [panel sets](https://quarto.org/docs/output-formats/html-basics.html#tabsets) when displaying output from `{quarto-webr}` and showing the underlying code.
- Minor documentation tweaks.

## Deployment
Expand Down
9 changes: 9 additions & 0 deletions tests/qwebr-test-internal-cell.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,20 @@ Test page for verifying cell context options set explicitly with `context`.

## Interactive

### Static
```{webr-r}
#| context: interactive
1 + 1
```

### Autorun

```{webr-r}
#| context: interactive
#| autorun: true
1 + 1
```

## Setup

Hidden cell that sets `x` and `y` vector values.
Expand Down

0 comments on commit aafa8d9

Please sign in to comment.