diff --git a/build/pkgs/jupyter_sphinx/checksums.ini b/build/pkgs/jupyter_sphinx/checksums.ini
index f53c5af453a..14f1bdf7594 100644
--- a/build/pkgs/jupyter_sphinx/checksums.ini
+++ b/build/pkgs/jupyter_sphinx/checksums.ini
@@ -1,5 +1,5 @@
tarball=jupyter_sphinx-VERSION.tar.gz
-sha1=241f6dfcd3aae4f44f330e2ba76480011b382d3d
-md5=e7ab370d9793be5b20bce5447ccbd45b
-cksum=2021246952
+sha1=fb2abdd5e35da0886b12d45a6373c4dbcc24b244
+md5=130daa6be810976c9f8e30aa04011e50
+cksum=2882523000
upstream_url=https://pypi.io/packages/source/j/jupyter_sphinx/jupyter_sphinx-VERSION.tar.gz
diff --git a/build/pkgs/jupyter_sphinx/package-version.txt b/build/pkgs/jupyter_sphinx/package-version.txt
index d15723fbe8d..8af2848288a 100644
--- a/build/pkgs/jupyter_sphinx/package-version.txt
+++ b/build/pkgs/jupyter_sphinx/package-version.txt
@@ -1 +1 @@
-0.3.2
+0.4.0.p0
diff --git a/build/pkgs/jupyter_sphinx/patches/0001-Patch-for-sage-live-doc.patch b/build/pkgs/jupyter_sphinx/patches/0001-Patch-for-sage-live-doc.patch
new file mode 100644
index 00000000000..afbb0c1273f
--- /dev/null
+++ b/build/pkgs/jupyter_sphinx/patches/0001-Patch-for-sage-live-doc.patch
@@ -0,0 +1,57 @@
+From 5bffbe38302c695123779f87300d84090b4bd118 Mon Sep 17 00:00:00 2001
+From: Kwankyu Lee
+Date: Mon, 28 Aug 2023 00:18:59 +0900
+Subject: [PATCH] Patch for sage live doc
+
+---
+ jupyter_sphinx/__init__.py | 4 ++--
+ jupyter_sphinx/execute.py | 11 +++++++++++
+ 2 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/jupyter_sphinx/__init__.py b/jupyter_sphinx/__init__.py
+index 34af884..b7ca8ee 100644
+--- a/jupyter_sphinx/__init__.py
++++ b/jupyter_sphinx/__init__.py
+@@ -31,7 +31,7 @@ from .thebelab import ThebeButton, ThebeButtonNode, ThebeOutputNode, ThebeSource
+ REQUIRE_URL_DEFAULT = (
+ "https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.4/require.min.js"
+ )
+-THEBELAB_URL_DEFAULT = "https://unpkg.com/thebelab@^0.4.0"
++THEBELAB_URL_DEFAULT = "https://unpkg.com/thebe@latest/lib/index.js"
+
+ logger = logging.getLogger(__name__)
+
+@@ -186,7 +186,7 @@ def setup(app):
+ app.add_config_value("jupyter_sphinx_embed_url", None, "html")
+
+ # thebelab config, can be either a filename or a dict
+- app.add_config_value("jupyter_sphinx_thebelab_config", None, "html")
++ app.add_config_value("jupyter_sphinx_thebelab_config", None, "env")
+ app.add_config_value("jupyter_sphinx_thebelab_url", THEBELAB_URL_DEFAULT, "html")
+
+ # linenos config
+diff --git a/jupyter_sphinx/execute.py b/jupyter_sphinx/execute.py
+index 558a26b..de44455 100644
+--- a/jupyter_sphinx/execute.py
++++ b/jupyter_sphinx/execute.py
+@@ -152,6 +152,17 @@ class ExecuteJupyterCells(SphinxTransform):
+ kernel_name = default_kernel
+ file_name = next(default_names)
+
++ # Save time when jupyter notebook execution is not necessary
++ if not any(not "execute" in node or node["execute"] for node in nodes):
++ # mimics empty cell output for each node
++ for node in nodes:
++ source = node.children[0]
++ source.attributes["classes"].append("code_cell")
++ node.attributes["cm_language"] = kernel_name
++ node += CellOutputNode(classes=["cell_output"])
++ apply_styling(node, thebe_config)
++ continue
++
+ # Add empty placeholder cells for non-executed nodes so nodes
+ # and cells can be zipped and the provided input/output
+ # can be inserted later
+--
+2.42.0
+
diff --git a/src/doc/common/static/custom-codemirror-monokai.css b/src/doc/common/static/custom-codemirror-monokai.css
new file mode 100644
index 00000000000..3489e3d61e5
--- /dev/null
+++ b/src/doc/common/static/custom-codemirror-monokai.css
@@ -0,0 +1,42 @@
+/* from https://codemirror.net/5/theme/monokai.css */
+/* Based on Sublime Text's Monokai theme */
+
+.cm-s-monokai.CodeMirror { background: #272822; color: #f8f8f2; }
+.cm-s-monokai div.CodeMirror-selected { background: #49483E; }
+.cm-s-monokai .CodeMirror-line::selection, .cm-s-monokai .CodeMirror-line > span::selection, .cm-s-monokai .CodeMirror-line > span > span::selection { background: rgba(73, 72, 62, .99); }
+.cm-s-monokai .CodeMirror-line::-moz-selection, .cm-s-monokai .CodeMirror-line > span::-moz-selection, .cm-s-monokai .CodeMirror-line > span > span::-moz-selection { background: rgba(73, 72, 62, .99); }
+.cm-s-monokai .CodeMirror-gutters { background: #272822; border-right: 0px; }
+.cm-s-monokai .CodeMirror-guttermarker { color: white; }
+.cm-s-monokai .CodeMirror-guttermarker-subtle { color: #d0d0d0; }
+.cm-s-monokai .CodeMirror-linenumber { color: #d0d0d0; }
+.cm-s-monokai .CodeMirror-cursor { border-left: 1px solid #f8f8f0; }
+
+.cm-s-monokai span.cm-comment { color: #75715e; }
+.cm-s-monokai span.cm-atom { color: #ae81ff; }
+.cm-s-monokai span.cm-number { color: #ae81ff; }
+
+.cm-s-monokai span.cm-comment.cm-attribute { color: #97b757; }
+.cm-s-monokai span.cm-comment.cm-def { color: #bc9262; }
+.cm-s-monokai span.cm-comment.cm-tag { color: #bc6283; }
+.cm-s-monokai span.cm-comment.cm-type { color: #5998a6; }
+
+.cm-s-monokai span.cm-property, .cm-s-monokai span.cm-attribute { color: #a6e22e; }
+.cm-s-monokai span.cm-keyword { color: #f92672; }
+.cm-s-monokai span.cm-builtin { color: #66d9ef; }
+.cm-s-monokai span.cm-string { color: #e6db74; }
+
+.cm-s-monokai span.cm-variable { color: #f8f8f2; }
+.cm-s-monokai span.cm-variable-2 { color: #9effff; }
+.cm-s-monokai span.cm-variable-3, .cm-s-monokai span.cm-type { color: #66d9ef; }
+.cm-s-monokai span.cm-def { color: #fd971f; }
+.cm-s-monokai span.cm-bracket { color: #f8f8f2; }
+.cm-s-monokai span.cm-tag { color: #f92672; }
+.cm-s-monokai span.cm-header { color: #ae81ff; }
+.cm-s-monokai span.cm-link { color: #ae81ff; }
+.cm-s-monokai span.cm-error { background: #f92672; color: #f8f8f0; }
+
+.cm-s-monokai .CodeMirror-activeline-background { background: #373831; }
+.cm-s-monokai .CodeMirror-matchingbracket {
+ text-decoration: underline;
+ color: white !important;
+}
diff --git a/src/doc/common/static/custom-jupyter-sphinx.css b/src/doc/common/static/custom-jupyter-sphinx.css
new file mode 100644
index 00000000000..a68a5cb05aa
--- /dev/null
+++ b/src/doc/common/static/custom-jupyter-sphinx.css
@@ -0,0 +1,140 @@
+div.jupyter_container {
+ margin: .5rem 0;
+}
+
+div.jupyter_container + div.jupyter_container {
+ margin: 0 0 .5rem 0;
+}
+
+div.jupyter_container div.cell_input pre {
+ margin: .5rem;
+}
+
+div.jupyter_container div.cell_output div.output {
+ margin: .5rem;
+}
+
+.thebelab-cell .jp-OutputArea {
+ margin: 0 .5rem;
+}
+
+.thebelab-cell .jp-OutputArea-output {
+ margin: 0 0 .5rem 0;
+ overflow-x: auto;
+}
+
+.thebelab-button {
+ margin: .5rem 0 .5rem .5rem;
+ padding: 0 .5rem;
+ min-width: 2rem;
+}
+
+.thebelab-button:active {
+ color: #0f0fff;
+}
+
+.thebelab-busy {
+ margin-left: .5rem;
+}
+
+#thebelab-activate-button {
+ position: fixed;
+ right: -5.1rem;
+ top: calc(50% - 1.5rem);
+ width: 6rem;
+ border-radius: 1rem;
+ transition-property: right;
+ transition-duration: 300ms;
+ transition-timing-function: ease-out;
+ z-index: 100;
+}
+
+#thebelab-activate-button:hover {
+ right: .4rem;
+}
+
+#thebelab-activate-button:active {
+ color: #0f0fff;
+}
+
+body[data-theme="dark"] {
+ .jupyter_container {
+ color: white;
+ background-color: black;
+ }
+
+ .jupyter_container .highlight {
+ background-color: black;
+ }
+
+ .thebelab-button {
+ color: #d0d0d0;
+ background-color: #383838;
+ }
+
+ .thebelab-button:active {
+ color: #368ce2;
+ }
+
+ #thebelab-activate-button {
+ background-color: #383838;
+ }
+
+ #thebelab-activate-button:active {
+ color: #368ce2;
+ }
+
+ .thebelab-cell .jp-OutputArea-output {
+ color: white;
+ background-color: black;
+ }
+
+ .thebelab-cell .jp-OutputArea-output pre {
+ color: white;
+ background-color: black;
+ }
+}
+
+@media (prefers-color-scheme: dark) {
+ body[data-theme="auto"] { /* the same styles with body[data-theme="dark"] */
+ .jupyter_container {
+ color: white;
+ background-color: black;
+ }
+
+ .jupyter_container .highlight {
+ background-color: black;
+ }
+
+ .thebelab-button {
+ color: #d0d0d0;
+ background-color: #383838;
+ }
+
+ .thebelab-button:active {
+ color: #368ce2;
+ }
+
+ #thebelab-activate-button {
+ background-color: #383838;
+ }
+
+ #thebelab-activate-button:active {
+ color: #368ce2;
+ }
+
+ .thebelab-cell .jp-OutputArea-output {
+ color: white;
+ background-color: black;
+ }
+
+ .thebelab-cell .jp-OutputArea-output pre {
+ color: white;
+ background-color: black;
+ }
+ }
+}
+
+
+
+
diff --git a/src/doc/common/static/jupyter-sphinx-furo.js b/src/doc/common/static/jupyter-sphinx-furo.js
new file mode 100644
index 00000000000..5194ff470fc
--- /dev/null
+++ b/src/doc/common/static/jupyter-sphinx-furo.js
@@ -0,0 +1,114 @@
+// Change the editor theme according to the furo light/dark/auto mode
+function changeTheme(editor, theme) {
+ if (theme === 'dark') {
+ editor.setOption('theme', 'monokai'); // the same with pygments dark style in conf.py
+ } else if (theme === 'auto' && window.matchMedia('(prefers-color-scheme: dark)').matches) {
+ editor.setOption('theme', 'monokai');
+ } else {
+ editor.setOption('theme', 'default');
+ }
+}
+
+// Change the editor theme of all CodeMirror cells
+function changeThemeAll(theme) {
+ const querySet = document.querySelectorAll('.CodeMirror');
+ for (var i = 0; i < querySet.length; i++) {
+ changeTheme(querySet[i].CodeMirror, theme);
+ }
+}
+
+// Use the theme data of the body element set by setTheme function
+// defined in https://github.com/pradyunsg/furo/blob/main/src/furo/assets/scripts/furo.js
+const body = document.body;
+const observer1 = new MutationObserver((mutationsList) => {
+ for (let mutation of mutationsList) {
+ if (mutation.type === 'attributes' && mutation.attributeName === 'data-theme') {
+ const theme = body.dataset.theme;
+ changeThemeAll(theme);
+ }
+ }
+});
+observer1.observe(body, { attributes: true });
+
+
+// In the furo auto mode, we watch prefers-color-scheme and use the theme data
+// of the body element to change the CodeMirror editor theme
+const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
+
+function handlePrefersColorSchemeChange(e) {
+ const theme = body.dataset.theme;
+ if (theme === 'auto') {
+ changeThemeAll(theme);
+ }
+}
+
+prefersDarkMode.addEventListener('change', handlePrefersColorSchemeChange);
+
+
+// Change the editor theme of a new CodeMirror cell.
+const callback = function(mutationsList, observer) {
+ for(const mutation of mutationsList) {
+ if (mutation.type === 'childList') {
+ const theme = body.dataset.theme;
+ for (const addedNode of mutation.addedNodes) {
+ if (addedNode.classList && addedNode.classList.contains('CodeMirror')) {
+ changeTheme(addedNode.CodeMirror, theme);
+ }}}}};
+const observer2 = new MutationObserver(callback);
+observer2.observe(document.getElementsByClassName("content")[0], { childList: true, subtree: true });
+
+
+// Listen to the kernel status changes
+// https://thebe.readthedocs.io/en/stable/events.html
+thebelab.on("status", function (evt, data) {
+ if (data.status === 'building') {
+ const elements = document.querySelectorAll('.thebelab-cell');
+ elements.forEach(element => {
+ element.style.filter = 'opacity(50%)';
+ });
+ const element = document.getElementById("thebelab-activate-button");
+ element.innerHTML = "Building";
+ element.style.right = '.4rem';
+ }
+ else if (data.status === 'built') {
+ const elements = document.querySelectorAll('.thebelab-cell');
+ elements.forEach(element => {
+ element.style.filter = 'opacity(60%)';
+ });
+ const element = document.getElementById("thebelab-activate-button");
+ element.innerHTML = "Built";
+ element.style.right = '.4rem';
+ }
+ else if (data.status === 'launching') {
+ const elements = document.querySelectorAll('.thebelab-cell');
+ elements.forEach(element => {
+ element.style.filter = 'opacity(70%)';
+ });
+ const element = document.getElementById("thebelab-activate-button");
+ element.innerHTML = "Launching";
+ element.style.right = '.4rem';
+ }
+ else if (data.status === 'failed') {
+ const elements = document.querySelectorAll('.thebelab-cell');
+ elements.forEach(element => {
+ element.style.filter = 'opacity(50%)';
+ });
+ const element = document.getElementById("thebelab-activate-button");
+ element.innerHTML = 'Failed: ' + data.message;
+ element.style.right = '.4rem';
+ element.style.width = 'auto';
+ element.style.color = 'red';
+ }
+ else if (data.status === 'ready') {
+ const elements = document.querySelectorAll('.thebelab-cell');
+ elements.forEach(element => {
+ element.style.filter = 'opacity(100%)';
+ });
+ const element = document.getElementById("thebelab-activate-button");
+ element.innerHTML = "Ready";
+ element.style.right = null;
+ // Run custom code when the kernel is ready
+ const kernel = data.kernel;
+ kernel.requestExecute({code: "%display latex"});
+ }
+});
diff --git a/src/doc/common/static/thebe-sage.js b/src/doc/common/static/thebe-sage.js
deleted file mode 100644
index 567e3488802..00000000000
--- a/src/doc/common/static/thebe-sage.js
+++ /dev/null
@@ -1,147 +0,0 @@
-/**
- * @overview
- * This file aims at replacing the document's Sage code blocks by executable
- * notebook cells. Users are presented a dedicated button in the top right
- * corner. When they click on it, each code block is appended a "Run" button
- * to execute the corresponding code.
- *
- * This is based on the Thebe library (https://github.com/oreillymedia/thebe/)
- * installed in ${SAGE_ROOT}/local/share/thebe/thebe.js by Sage's thebe package.
- */
-
-$(function() {
-
- /**
- * Build and return the Thebe instance that will communicate with the
- * Jupyter notebook (or tmpnb server).
- *
- * This function categorizes the cells lines into "code" and "result"
- * categories to refine the given cell selector and pass only the code
- * lines to Thebe.
- *
- * @param {String} cellSelector - A jQuery selector that matches the cells
- * @param {Object} thebeOptions - Thebe options, must not contain "selector"
- */
- function setupThebeSage(cellSelector, thebeOptions) {
- var lineClass = 'sage-cell-line',
- codeClass = 'sage-code',
- codeBlockClass = 'sage-code-block',
- resultClass = 'sage-expected-result',
- resultBlockClass = 'sage-expect-result-block';
- $(cellSelector).each(function() {
- wrapEachCellLine(this, lineClass);
- categorizeCellLines(this, lineClass, codeClass, resultClass);
- wrapLineBlocks(this, lineClass, codeClass, codeBlockClass);
- wrapLineBlocks(this, lineClass, resultClass, resultBlockClass);
- $('.' + resultBlockClass, this).hide();
- sanitizeCode(this, codeClass);
- });
- thebeOptions.selector = '.' + codeBlockClass;
- return new Thebe(thebeOptions);
- }
-
- /**
- * Sanitize the code before executing. For now, transforms the code line
- * into pure text, also stripping out the Sage prompts and continuation
- * characters at line start, if any.
- *
- * @param {Element} cellNode - The DOM element of the cell
- * @param {String} codeClass - The class name associated to code line
- */
- function sanitizeCode(cellNode, codeClass) {
- var rgx = /^(sage: )|(\.\.\.\.: )|(\.\.\. )/;
- var codeLines = cellNode.getElementsByClassName(codeClass);
- Array.prototype.forEach.call(codeLines, function(line) {
- line.textContent = line.textContent.replace(rgx, '');
- });
- }
-
- /**
- * Wrap consecutive lines of the same type in a given cell in line blocks.
- *
- * @param {Element} cellNode - The DOM element of the cell
- * @param {String} lineClass - The class name that identifies all cell lines
- * @param {String} specificClass - The class name that identifies the lines
- * to be wrapped
- * @param {String} blockClass - The class name to be given to the add
- * wrapper blocks
- */
- function wrapLineBlocks(cellNode, lineClass, specificClass, blockClass) {
- var wrapper,
- lines = cellNode.getElementsByClassName(lineClass);
- Array.prototype.forEach.call(lines, function(line) {
- if (line.classList.contains(specificClass)) {
- if (! wrapper) {
- wrapper = document.createElement('span');
- wrapper.classList.add(blockClass);
- cellNode.insertBefore(wrapper, line);
- }
- wrapper.appendChild(line);
- } else {
- wrapper = null;
- }
- });
- }
-
- /**
- * Add a class on each line of a cell to categorize them as code or result.
- *
- * @param {Element} cellNode - The DOM element of the cell to categorize the
- * lines of
- * @param {String} lineClass - A class name to identify each cell line
- * @param {String} codeClass - A class name to be added on code lines
- * @param {String} resultClass - A class name to be added on result lines
- */
- function categorizeCellLines(cellNode, lineClass, codeClass, resultClass) {
- var lines = cellNode.getElementsByClassName(lineClass);
- var previousCategory;
- Array.prototype.forEach.call(lines, function(line) {
- var lineText = line.textContent;
- if (lineText.startsWith('sage: ')) {
- line.classList.add(codeClass);
- previousCategory = 'code';
- return;
- }
- if (previousCategory === 'code'
- && (lineText.startsWith('....: ')
- || lineText.startsWith('... '))) {
- line.classList.add(codeClass);
- return;
- }
- line.classList.add(resultClass);
- previousCategory = 'result';
- });
- }
-
- /**
- * Add a (span) DOM element around each line of an executable cell
- *
- * @param {Element} cellNode - cell to wrap the lines of
- * @param {String} lineClass - class attribute value for the added span tags
- */
- function wrapEachCellLine(cellNode, lineClass) {
- var html = '';
- cellNode.innerHTML.split('\n').forEach(function(htmlLine) {
- html += '' + htmlLine + '\n';
- });
- cellNode.innerHTML = html;
- }
-
- if (window.location.protocol.startsWith('http')) {
- var cellSelector = "pre:contains('sage: ')";
- if ($(cellSelector).length > 0) {
- $('')
- .css({position: 'absolute', right: 0})
- .click(function() {
- setupThebeSage(cellSelector, {
- tmpnb_mode: false,
- load_css: false,
- url: window.location.origin,
- kernel_name: "sagemath"
- });
- $(this).attr('disabled', 'disabled');
- })
- .prependTo('div.body');
- }
- }
-});
diff --git a/src/doc/common/themes/sage-classic/layout.html b/src/doc/common/themes/sage-classic/layout.html
index ab9a05261aa..1cea7f178a9 100644
--- a/src/doc/common/themes/sage-classic/layout.html
+++ b/src/doc/common/themes/sage-classic/layout.html
@@ -17,8 +17,6 @@
{% block extrahead %}
-
-
{% endblock %}
{%- block footer %}
diff --git a/src/doc/en/a_tour_of_sage/index.rst b/src/doc/en/a_tour_of_sage/index.rst
index 15e9d2aae46..8f638378130 100644
--- a/src/doc/en/a_tour_of_sage/index.rst
+++ b/src/doc/en/a_tour_of_sage/index.rst
@@ -1,38 +1,35 @@
.. _a-tour-of-sage:
-=========================
-Welcome to a Tour of Sage
-=========================
+===============
+Welcome to Sage
+===============
-This is a tour of Sage that closely follows the tour of Mathematica
-that is at the beginning of the Mathematica Book.
+This is a short tour of Sage as a calculator.
-
-Sage as a Calculator
-====================
-
-The Sage command line has a ``sage:`` prompt; you do not have to add
-it. If you use the Sage notebook, then put everything after the
-``sage:`` prompt in an input cell, and press shift-enter to compute the
-corresponding output.
+The Sage command line has a prompt "``sage:``". To experiment with the
+following examples, you only enter the part after the prompt.
::
sage: 3 + 5
8
+If you use Sage on the Jupyter notebook, then likewise put everything after the
+prompt in an input cell, and press :kbd:`Shift-Enter` to get the corresponding
+output.
+
The caret symbol means "raise to a power".
::
- sage: 57.1 ^ 100
+ sage: 57.1^100
4.60904368661396e175
We compute the inverse of a :math:`2 \times 2` matrix in Sage.
::
- sage: matrix([[1,2], [3,4]])^(-1)
+ sage: matrix([[1, 2], [3, 4]])^(-1)
[ -2 1]
[ 3/2 -1/2]
@@ -41,11 +38,11 @@ Here we integrate a simple function.
::
sage: x = var('x') # create a symbolic variable
- sage: integrate(sqrt(x)*sqrt(1+x), x)
- 1/4*((x + 1)^(3/2)/x^(3/2) + sqrt(x + 1)/sqrt(x))/((x + 1)^2/x^2 - 2*(x + 1)/x + 1) - 1/8*log(sqrt(x + 1)/sqrt(x) + 1) + 1/8*log(sqrt(x + 1)/sqrt(x) - 1)
+ sage: integrate(sqrt(x) * sqrt(1 + x), x)
+ 1/4*((x + 1)^(3/2)/x^(3/2) + sqrt(x + 1)/sqrt(x))/((x + 1)^2/x^2 - 2*(x + 1)/x + 1)
+ - 1/8*log(sqrt(x + 1)/sqrt(x) + 1) + 1/8*log(sqrt(x + 1)/sqrt(x) - 1)
-This asks Sage to solve a quadratic equation. The symbol ``==``
-represents equality in Sage.
+This asks Sage to solve a quadratic equation. The symbol ``==`` represents equality in Sage.
::
@@ -59,10 +56,10 @@ The result is a list of equalities.
::
- sage: S[0].rhs()
+ sage: S[0].rhs() # right hand side of the equation
-1/2*sqrt(4*a + 1) - 1/2
-Naturally, Sage can plot various useful functions.
+Sage can plot various useful functions, of course.
::
@@ -71,39 +68,39 @@ Naturally, Sage can plot various useful functions.
.. image:: sin_plot.*
-Power Computing with Sage
-=========================
-
-First we create a :math:`500 \times 500` matrix of random
-numbers.
+Sage is a very powerful calculator. To experience it, first we create a :math:`500 \times 500`
+matrix of random numbers.
::
- sage: m = random_matrix(RDF,500)
+ sage: m = random_matrix(RDF, 500)
-It takes Sage a few seconds to compute the eigenvalues of the
-matrix and plot them.
+It takes Sage a second to compute the eigenvalues of the matrix and plot them.
.. link
::
- sage: e = m.eigenvalues() #about 2 seconds
+ sage: e = m.eigenvalues() # about 1 second
sage: w = [(i, abs(e[i])) for i in range(len(e))]
sage: show(points(w))
.. image:: eigen_plot.*
-Thanks to the GNU Multiprecision Library (GMP), Sage can handle
-very large numbers, even numbers with millions or billions of
+Sage can handle very large numbers, even numbers with millions or billions of
digits.
::
sage: factorial(100)
93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
- sage: n = factorial(1000000) #about 2.5 seconds
+
+::
+
+ sage: n = factorial(1000000) # about 1 second
+ sage: len(n.digits())
+ 5565709
This computes at least 100 digits of :math:`\pi`.
@@ -131,17 +128,13 @@ This asks Sage to factor a polynomial in two variables.
sage: F.expand()
x^99 + y^99
-Sage takes just under 5 seconds to compute the numbers of ways to
-partition one hundred million as a sum of positive integers.
+Sage takes less than 1 second to compute the numbers of ways to partition one
+hundred million as a sum of positive integers.
::
- sage: z = Partitions(10^8).cardinality() #about 4.5 seconds
- sage: str(z)[:40]
- '1760517045946249141360373894679135204009'
-
-Accessing Algorithms in Sage
-============================
+ sage: z = Partitions(10^8).cardinality() # about .1 second
+ sage: z
+ 1760517045946249141360373894679135204009...
-Whenever you use Sage you are accessing one of the world's largest
-collections of open source computational algorithms.
+Sage is the world's most advanced open source math software.
diff --git a/src/doc/en/installation/binary.rst b/src/doc/en/installation/binary.rst
index 5fcce7d5943..4943245a845 100644
--- a/src/doc/en/installation/binary.rst
+++ b/src/doc/en/installation/binary.rst
@@ -1,6 +1,6 @@
.. _sec-installation-from-binaries:
-Install from Pre-built Binaries
+Install from Pre-Built Binaries
===============================
Linux
diff --git a/src/doc/en/installation/index.rst b/src/doc/en/installation/index.rst
index 9baf654f457..50d0af27341 100644
--- a/src/doc/en/installation/index.rst
+++ b/src/doc/en/installation/index.rst
@@ -127,16 +127,17 @@ Linux
In the cloud
============
-- `CoCalc `_: an online service that provides SageMath and
- many other tools.
+- `Sage Binder repo `_ provides a
+ Binder badge to launch JupyterLab environment with Sage.
+
+- `Sage Cell Server `_ is a free online service for
+ quick computations with Sage.
-- On any system that allows you to bring your own Docker images to run
- in a container: Use the `Docker image sagemathinc/cocalc
- `_ or :trac:`another Docker
- image providing SageMath `.
+- `CoCalc `_ is an online commercial service that provides Sage and
+ many other tools.
-- `Sage Cell Server `_: an online service for
- elementary SageMath computations.
+- `Docker image sagemathinc/cocalc
+ `_ can be used on any system with Docker to run CoCalc locally.
More information:
diff --git a/src/doc/en/installation/linux.rst b/src/doc/en/installation/linux.rst
index ec3b5e07ecf..2b2e7bafe2b 100644
--- a/src/doc/en/installation/linux.rst
+++ b/src/doc/en/installation/linux.rst
@@ -1,6 +1,6 @@
.. _sec-GNU-Linux:
-Linux package managers
+Linux Package Managers
======================
SageMath is available from various distributions and can be installed
diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst
index b156165778b..b16fd8e7295 100644
--- a/src/doc/en/installation/source.rst
+++ b/src/doc/en/installation/source.rst
@@ -1,9 +1,3 @@
-.. comment:
- ***************************************************************************
- If you alter this document, please change the last line:
- **This page was last updated in MONTH YEAR (Sage X.Y).**
- ***************************************************************************
-
.. HIGHLIGHT:: shell-session
.. _sec-installation-from-sources:
@@ -11,27 +5,23 @@
Install from Source Code
========================
-.. contents:: Table of contents
- :depth: 2
- :class: this-will-duplicate-information-and-it-is-still-useful-here
-
-Some familiarity with the use of the Unix command line may be required to
-build Sage from the :wikipedia:`source code `.
-
-Building Sage from the source code has the major advantage that your install
-will be optimized for your particular computer and should therefore offer
-better performance and compatibility than a binary install.
+Building Sage from the :wikipedia:`source code ` has the major
+advantage that your install will be optimized for your particular computer and
+should therefore offer better performance and compatibility than a binary
+install.
-Moreover, it offers you full development capabilities:
-you can change absolutely any part of Sage or the programs on which it depends,
-and recompile the modified parts.
+Moreover, it offers you full development capabilities: you can change
+absolutely any part of Sage or the packages on which it depends, and recompile
+the modified parts.
See the file `README.md `_
in ``SAGE_ROOT`` for information on supported platforms and
step-by-step instructions.
-The following sections provide some additional details. Most users
-will not need to read them.
+The following sections provide some additional details. Most users will not
+need to read them. Some familiarity with the use of the Unix command line may
+be required to build Sage from the source code.
+
.. _section-prereqs:
@@ -436,7 +426,6 @@ On other systems, check the documentation for your particular operating system.
.. _section_conda_compilers:
-
Notes on using conda
^^^^^^^^^^^^^^^^^^^^
@@ -457,70 +446,12 @@ If you don't want conda to be used by sage, deactivate conda (for the current sh
operating system, or its own compilers.
-Additional software
--------------------
-
-Recommended programs
-^^^^^^^^^^^^^^^^^^^^
-
-The following programs are recommended.
-They are not strictly required at build time or at run time,
-but provide additional capabilities:
-
-- **dvipng**.
-- **ffmpeg**.
-- **ImageMagick**.
-- **LaTeX**: highly recommended.
-
-It is highly recommended that you have
-:wikipedia:`LaTeX `
-installed, but it is not required.
-The most popular packaging is `TeX Live `_,
-which can be installed following the directions on their web site.
-On Linux systems you can alternatively install your distribution's
-texlive packages::
-
- $ sudo apt-get install texlive # debian
- $ sudo yum install texlive # redhat
-
-or similar commands. In addition to the base TeX Live install, you may
-need some optional TeX Live packages, for example
-country-specific babel packages for the localized Sage
-documentation.
-
-If you don't have either ImageMagick or ffmpeg, you won't be able to
-view animations.
-ffmpeg can produce animations in more different formats than ImageMagick,
-and seems to be faster than ImageMagick when creating animated GIFs.
-Either ImageMagick or dvipng is used for displaying some LaTeX output in the
-Sage notebook.
-
-On Debian/Ubuntu, the following system packages are recommended.
-
-- ``texlive-generic-extra`` (to generate pdf documentation)
-
-- ``texlive-xetex`` (to convert Jupyter notebooks to pdf)
-
-- ``latexmk`` (to generate pdf documentation)
-
-- ``pandoc`` (to convert Jupyter notebooks to pdf)
-
-- ``dvipng`` (to render text with LaTeX in Matplotlib)
-
-- ``default-jdk`` (to run the Jmol 3D viewer from the console and generate images for 3D plots in the documentation)
-
-- ``ffmpeg`` (to produce animations)
-
-- ``libavdevice-dev`` (to produce animations)
-
Tcl/Tk
^^^^^^
-If you want to use `Tcl/Tk `_ libraries in Sage,
-you need to install the Tcl/Tk and its development headers before building
-Sage.
-Sage's Python will then automatically recognize your system's install of
-Tcl/Tk.
+If you want to use `Tcl/Tk `_ libraries in Sage, you need
+to install the Tcl/Tk and its development headers before building Sage. Sage's
+Python will then automatically recognize your system's install of Tcl/Tk.
On Linux systems, these are usually provided by the **tk** and **tk-dev**
(or **tk-devel**) packages which can be installed using::
@@ -548,13 +479,11 @@ If
does not raise an :class:`ImportError`, then it worked.
-.. _build-from-source-step-by-step:
-Step-by-step installation procedure
------------------------------------
+.. _build-from-source-step-by-step:
-General procedure
-^^^^^^^^^^^^^^^^^
+Installation steps
+------------------
#. Follow the procedure in the file `README.md `_
in ``SAGE_ROOT``.
@@ -936,23 +865,6 @@ Here are some of the more commonly used variables affecting the build process:
Python-level profiling is always available; This option enables
profiling in Cython modules.
-- :envvar:`SAGE_SPKG_INSTALL_DOCS` - if set to ``yes``, then install
- package-specific documentation to
- :file:`$SAGE_ROOT/local/share/doc/PACKAGE_NAME/` when an spkg is
- installed.
- This option may not be supported by all spkgs.
- Some spkgs might also assume that certain programs are available on the
- system (for example, ``latex`` or ``pdflatex``).
-
-- :envvar:`SAGE_DOCBUILD_OPTS` - the value of this variable is passed as an
- argument to ``sage --docbuild all html`` or ``sage --docbuild all pdf`` when
- you run ``make``, ``make doc``, or ``make doc-pdf``.
- For example, you can add ``--no-plot`` to this variable to avoid building
- the graphics coming from the ``.. PLOT`` directive within the documentation,
- or you can add ``--include-tests-blocks`` to include all "TESTS" blocks in the
- reference manual. Run ``sage --docbuild help`` to see the full list
- of options.
-
- :envvar:`SAGE_BUILD_DIR` - the default behavior is to build each spkg in a
subdirectory of :file:`$SAGE_ROOT/local/var/tmp/sage/build/`; for
example, build version 7.27.0 of
@@ -1034,6 +946,67 @@ Here are some of the more commonly used variables affecting the build process:
supports :envvar:`SAGE_SUDO`, into a root-owned installation
hierarchy (:envvar:`SAGE_LOCAL`).
+Environment variables for documentation build:
+
+- :envvar:`SAGE_DOCBUILD_OPTS` - the value of this variable is passed as an
+ argument to ``sage --docbuild all html`` or ``sage --docbuild all pdf`` when
+ you run ``make``, ``make doc``, or ``make doc-pdf``. For example, you can
+ add ``--no-plot`` to this variable to avoid building the graphics coming from
+ the ``.. PLOT`` directive within the documentation, or you can add
+ ``--include-tests-blocks`` to include all "TESTS" blocks in the reference
+ manual. Run ``sage --docbuild help`` to see the full list of options.
+
+- :envvar:`SAGE_SPKG_INSTALL_DOCS` - if set to ``yes``, then install
+ package-specific documentation to
+ :file:`$SAGE_ROOT/local/share/doc/PACKAGE_NAME/` when an spkg is installed.
+ This option may not be supported by all spkgs. Some spkgs might also assume
+ that certain programs are available on the system (for example, ``latex`` or
+ ``pdflatex``).
+
+- :envvar:`SAGE_USE_CDNS` -- if set to ``yes``, then build the documentation
+ using CDNs (Content Distribution Networks) for scripts necessary for HTML
+ documentation, such as `MathJax `_.
+
+- :envvar:`SAGE_LIVE_DOC` -- if set to ``yes``, then build live Sage
+ documentation. If the ``Make live`` button on any webpage of the live doc is
+ clicked, every example code gets a `CodeMirror `_
+ code cell runnable via `Thebe `_.
+ Thebe is responsible in sending the code to the Sage computing environment
+ built by `Binder `_ and showing the output result.
+ The Sage computing environment can be specified to either a Binder repo or a
+ local Jupyter server. The environment variable :envvar:`SAGE_JUPYTER_SERVER`
+ is used for this purpose.
+
+ :envvar:`SAGE_JUPYTER_SERVER` - set this to either ``binder``,
+ ``binder:repo`` with ``repo`` specifying a Binder repo or the URL to a local
+ Jupyter server.
+
+ - ``binder`` refers to `Sage's official Binder repo
+ `_. This is assumed if the
+ environment variable :envvar:`SAGE_JUPYTER_SERVER` is not set.
+
+ - ``binder:repo`` specifies a Binder repo with ``repo``, which is a GitHub
+ repository name, optionally added with a branch name with ``/`` separator.
+
+ - To use a local Jupyter server instead of Binder, then set the URL to
+ :envvar:`SAGE_JUPYTER_SERVER` and the secret token to environment variable
+ :envvar:`SAGE_JUPYTER_SERVER_TOKEN`, which can be left unset if the default
+ token ``secret`` is used. If the live doc was built with
+ ``SAGE_JUPYTER_SERVER=http://localhost:8889``, run a local Jupyter server
+ by
+
+ .. CODE-BLOCK:: bash
+
+ ./sage --notebook=jupyterlab \
+ --ServerApp.token='secret' \
+ --ServerApp.allow_origin='null' \
+ --ServerApp.disable_check_xsrf=true \
+ --ServerApp.port=8889 \
+ --ServerApp.open_browser=false
+
+ before opening the Sage documentation webpage.
+
+
Environment variables dealing with specific Sage packages:
- :envvar:`SAGE_MATPLOTLIB_GUI` - if set to anything non-empty except ``no``,
@@ -1045,14 +1018,14 @@ Environment variables dealing with specific Sage packages:
support (which is disabled by default). See the file
:file:`build/pkgs/pari/spkg-install` for more information.
-- :envvar:`SAGE_TUNE_PARI`: If yes, enable PARI self-tuning. Note that
+- :envvar:`SAGE_TUNE_PARI` - if yes, enable PARI self-tuning. Note that
this can be time-consuming. If you set this variable to "yes", you
will also see this: ``WARNING: Tuning PARI/GP is unreliable. You may
find your build of PARI fails, or PARI/GP does not work properly
once built. We recommend to build this package with
SAGE_CHECK="yes".``
-- :envvar:`PARI_MAKEFLAGS`: The value of this variable is passed as an
+- :envvar:`PARI_MAKEFLAGS` - The value of this variable is passed as an
argument to the ``$MAKE`` command when compiling PARI.
Some standard environment variables which are used by Sage:
@@ -1094,7 +1067,7 @@ Some standard environment variables which are used by Sage:
- :envvar:`OPENBLAS_CONFIGURE` - adds additional configuration flags for
the OpenBLAS package that gets added to the make command. (see :trac:`23272`)
-Variables dealing with doctesting:
+Environment variables dealing with doctesting:
- :envvar:`SAGE_TIMEOUT` - used for Sage's doctesting: the number of seconds
to allow a doctest before timing it out.
@@ -1105,7 +1078,7 @@ Variables dealing with doctesting:
``sage -t --long``.
If this isn't set, the default is 1800 seconds (30 minutes).
-- :envvar:`SAGE_TEST_GLOBAL_ITER`, :envvar:`SAGE_TEST_ITER`: these can
+- :envvar:`SAGE_TEST_GLOBAL_ITER`, :envvar:`SAGE_TEST_ITER` - these can
be used instead of passing the flags ``--global-iterations`` and
``--file-iterations``, respectively, to ``sage -t``. Indeed, these
variables are only used if the flags are unset. Run ``sage -t -h``
@@ -1146,7 +1119,7 @@ see a list, execute ``sage.env.[TAB]`` while running Sage.
***************************************************************************
-Installation in a Multiuser Environment
+Installation in a multiuser environment
---------------------------------------
This section addresses the question of how a system administrator can install
@@ -1183,4 +1156,54 @@ a single copy of Sage in a multi-user computer network.
$ sudo chown -R root SAGE_LOCAL
-**This page was last updated in September 2022 (Sage 9.8).**
+Additional software
+-------------------
+
+The following programs are not strictly required at build time or at run time,
+but provide additional capabilities to Sage. We highly recommend a Sage user to
+install them.
+
+LaTeX
+^^^^^
+
+It is highly recommended that you have :wikipedia:`LaTeX ` installed,
+but it is not required. The most popular packaging is `TeX Live
+`_, which can be installed following the
+directions on their web site. On Linux systems you can alternatively install
+your distribution's texlive packages::
+
+ $ sudo apt-get install texlive # debian
+ $ sudo yum install texlive # redhat
+
+or similar commands. In addition to the base TeX Live install, you may
+need some optional TeX Live packages, for example
+country-specific Babel packages for the localized Sage
+documentation.
+
+Additionally, the following system packages are recommended on Debian/Ubuntu:
+
+- ``texlive-generic-extra`` (to generate pdf documentation)
+
+- ``texlive-xetex`` (to convert Jupyter notebooks to pdf)
+
+- ``latexmk`` (to generate pdf documentation)
+
+- ``dvipng`` (to render text with LaTeX in Matplotlib)
+
+pandoc
+^^^^^^
+
+This is useful to convert Jupyter notebooks to pdf.
+
+ffmpeg, ImageMagick
+^^^^^^^^^^^^^^^^^^^
+
+If you don't have either ImageMagick or ffmpeg, you won't be able to view
+animations. ffmpeg can produce animations in more different formats than
+ImageMagick, and seems to be faster than ImageMagick when creating animated
+GIFs.
+
+``libavdevice-dev`` is a component of ffmpeg to produce animations, and
+recommended to install on Debian/Ubuntu.
+
+
diff --git a/src/doc/en/tutorial/latex.rst b/src/doc/en/tutorial/latex.rst
index aafaaea6ac5..a173afd75c5 100644
--- a/src/doc/en/tutorial/latex.rst
+++ b/src/doc/en/tutorial/latex.rst
@@ -1,71 +1,99 @@
-*********************************
+***********************
Sage, LaTeX and Friends
-*********************************
+***********************
Sage and the LaTeX dialect of TeX have an intensely synergistic relationship.
This section aims to introduce the variety of interactions, beginning with the
most basic and proceeding to the more unusual.
-Overview
-========
-
-It may be easiest to understand the various uses of LaTeX with a
-brief overview of the mechanics of the three principal methods
-employed by Sage.
-
- #. Every "object" in Sage is required to have a LaTeX representation. You
- can access this representation by executing ``latex(foo)`` where
- ``foo`` is some object in Sage. The output is a string that should
- render a reasonably accurate representation of ``foo`` when used in
- TeX's math-mode (for example, when enclosed between a pair of single
- dollar signs). Some examples of this follow below.
-
- In this way, Sage can be used effectively for constructing portions of
- a LaTeX document: create or compute an object in Sage, print ``latex()``
- of the object and cut/paste it into your document.
-
- #. The Jupyter notebook interface uses `MathJax `_
- to render mathematics cleanly in a web browser. You can start this
- automatic rendering by executing ``%display latex`` (and stop by
- executing ``%display plain``).
-
- MathJax is an open source JavaScript display engine for mathematics that
- works in all modern browsers. It is able to render a large, but not
- totally complete, subset of TeX. It has no support for things like
- complicated tables, sectioning or document management, as it is oriented
- towards accurately rendering "snippets" of TeX. Seemingly automatic
- rendering of math in the notebook is provided by converting the
- ``latex()`` representation of an object (as described above) into a form
- of HTML palatable to MathJax.
-
- #. A system-wide installation of LaTeX can be employed. Sage includes
- almost everything you need to build and use Sage, but a significant
- exception is TeX itself. So in these situations you need to have
- TeX installed, along with some associated conversion utilities, to
- utilize the full power.
-
-Here we demonstrate some basic uses of the ``latex()`` function. ::
+Basic Use
+=========
+
+Every "object" in Sage is required to have a LaTeX representation. You can
+access this representation by executing ``latex(foo)`` where ``foo`` is some
+object in Sage. The output is a string that should render a reasonably
+accurate representation of ``foo`` when used in TeX's math-mode (for example,
+when enclosed between a pair of single dollar signs). Some examples of this
+follow below. ::
sage: var('z')
z
sage: latex(z^12)
z^{12}
- sage: latex(integrate(z^4, z))
- \frac{1}{5} \, z^{5}
+ sage: latex(sqrt(z^2 + 1/2))
+ \sqrt{z^{2} + \frac{1}{2}}
sage: latex('a string')
\text{\texttt{a{ }string}}
sage: latex(QQ)
\Bold{Q}
+ sage: latex(ZZ['x'])
+ \Bold{Z}[x]
sage: latex(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
\left(\begin{array}{rrr}
2 & 4 & 6 \\
-1 & -1 & -1
\end{array}\right)
-Basic MathJax functionality is largely automatic in the notebook, but we can
-partially demonstrate this support with the ``MathJax`` class. The object of
-this class converts a Sage object to its LaTeX representation and then wraps it
-in HTML. ::
+In this way, Sage can be used effectively for constructing portions of
+a LaTeX document: create or compute an object in Sage, do ``latex(foo)``
+of the object ``foo`` and cut/paste the LaTeX string into your document.
+
+The command ``view(foo)`` will show the rendered LaTeX
+representation of ``foo``. In the background, the command runs ``latex(foo)``
+and incorporates the LaTeX string into a simple LaTeX document, processes that
+document with the system-wide TeX installation, and finally an appropriate
+viewer will be called to display the output.
+
+In the Jupyter notebook, you can see the rendered LaTeX representation of the
+output of the entered commands automatically. You can start this
+automatic rendering by executing ``%display latex`` (and stop by executing
+``%display plain``).
+
+.. ONLY:: html
+
+ Thus, in the Jupyter notebook, you get
+
+ .. JUPYTER-EXECUTE::
+
+ %display latex
+ var('z')
+ z^12
+
+ .. JUPYTER-EXECUTE::
+
+ sqrt(z^2 + 1/2)
+
+ .. JUPYTER-EXECUTE::
+
+ 'a string'
+
+ .. JUPYTER-EXECUTE::
+
+ QQ
+
+ .. JUPYTER-EXECUTE::
+
+ ZZ['x']
+
+ .. JUPYTER-EXECUTE::
+
+ matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]])
+
+ .. JUPYTER-EXECUTE::
+
+ %display plain
+
+The Jupyter notebook uses `MathJax `_ to render
+mathematics cleanly in a web browser. MathJax is an open source JavaScript
+display engine for mathematics that works in all modern browsers. It is able
+to render a large, but not totally complete, subset of LaTeX. It has no
+support for things like complicated tables, sectioning or document management,
+as it is oriented towards accurately rendering math snippets of LaTeX.
+
+The automatic LaTeX rendering in the Jupyter notebook (with ``%display latex``
+on) is internally done via the :class:`sage.misc.html.MathJax` class. The
+object of this class converts a Sage object through ``latex()`` to a form of
+HTML palatable to MathJax and then wraps it in HTML. ::
sage: from sage.misc.html import MathJax
sage: mj = MathJax()
@@ -73,28 +101,22 @@ in HTML. ::
z
sage: mj(z^12)
\[z^{12}\]
+ sage: mj(sqrt(z^2 + 1/2))
+ \[\sqrt{z^{2} + \frac{1}{2}}\]
+ sage: mj('a string')
+ \[\verb|a|\verb| |\verb|string|\]
sage: mj(QQ)
\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Q}\]
sage: mj(ZZ['x'])
\[\newcommand{\Bold}[1]{\mathbf{#1}}\Bold{Z}[x]\]
- sage: mj(integrate(z^4, z))
- \[\frac{1}{5} \, z^{5}\]
-
-Basic Use
-=========
+ sage: mj(matrix(QQ, 2, 3, [[2,4,6],[-1,-1,-1]]))
+ \[\left(\begin{array}{rrr}
+ 2 & 4 & 6 \\
+ -1 & -1 & -1
+ \end{array}\right)\]
-As indicated in the overview, the simplest way to exploit Sage's support of
-LaTeX is to use the ``latex()`` function to create legitimate LaTeX code to
-represent mathematical objects. These strings can then be incorporated into
-standalone LaTeX documents.
+This is useful to know if you need to understand the LaTeX rendering of a Sage object.
-At the other extreme is the ``view()`` command. The command ``view(foo)`` will
-create the LaTeX representation of ``foo``, incorporate this into a simple
-LaTeX document, and then process that document with your system-wide TeX
-installation. Finally, the appropriate viewer will be called to display the
-output from the TeX command. Which version of TeX is used, and therefore the
-nature of the output and associated viewer, can be customized (see
-:ref:`sec-custom-processing`).
.. _sec-custom-generation:
@@ -152,30 +174,74 @@ done in written work. This is accomplished by redefining the
\[\newcommand{\Bold}[1]{\mathbb{#1}}\Bold{Q}\]
sage: latex.blackboard_bold(False)
-It is possible to take advantage of the extensible nature of TeX by adding in
-new macros and new packages. First, individual macros can be added so that
-they are used when MathJax interprets a snippet of TeX in the notebook. ::
+.. ONLY:: html
+ In the Jupyter notebook,
+
+ .. JUPYTER-EXECUTE::
+
+ %display latex
+ QQ
+
+ .. JUPYTER-EXECUTE::
+
+ latex.blackboard_bold(True)
+ QQ
+
+ .. JUPYTER-EXECUTE::
+
+ latex.blackboard_bold(False)
+ %display plain
+
+It is possible to take advantage of the extensible nature of LaTeX by adding in
+new macros. Individual macros can be added so that they are used when MathJax
+interprets a LaTeX snippet. ::
+
+ sage: latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
sage: latex.extra_macros()
- ''
- sage: latex.add_macro("\\newcommand{\\foo}{bar}")
- sage: latex.extra_macros()
- '\\newcommand{\\foo}{bar}'
+ '\\newcommand{\\sqrt}[1]{(#1)^\\frac{1}{2}}'
sage: var('x y')
(x, y)
- sage: latex(x+y)
- x + y
+ sage: latex(sqrt(x+y))
+ \sqrt{x + y}
sage: from sage.misc.html import MathJax
sage: mj = MathJax()
- sage: mj(x+y)
- \[\newcommand{\foo}{bar}x + y\]
+ sage: mj(sqrt(x + y))
+ \[\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}\sqrt{x + y}\]
+ sage: latex.extra_macros('')
+
+.. ONLY:: html
+
+ In the Jupyter notebook,
-Additional macros added this way will also be used in the event that the
-system-wide version of TeX is called on something larger than MathJax can
-handle. The command ``latex_extra_preamble`` is used to build the preamble of
-a complete LaTeX document, so the following illustrates how this is
-accomplished. As usual note the need for the double-backslashes in the Python
-strings. ::
+ .. JUPYTER-EXECUTE::
+
+ %display latex
+ var('x y')
+ sqrt(x + y)
+
+ .. JUPYTER-EXECUTE::
+
+ latex.add_macro(r"\newcommand{\sqrt}[1]{(#1)^\frac{1}{2}}")
+ sqrt(x + y)
+
+ .. JUPYTER-EXECUTE::
+
+ latex.extra_macros('')
+ %display plain
+
+
+.. _sec-custom-processing:
+
+Customizing LaTeX Processing
+============================
+
+The system-wide TeX is called to process a complete LaTeX document, such as
+when you ``view(foo)``, where ``foo`` is a complicated Sage object, too
+complicated for ``MathJax`` to handle. The command ``latex_extra_preamble`` is
+used to build the preamble of the complete LaTeX document, so the following
+illustrates how this is accomplished. As usual note the need for the
+double-backslashes in the Python strings. ::
sage: latex.extra_macros('')
sage: latex.extra_preamble('')
@@ -229,38 +295,40 @@ package that presumably does not exist. ::
sage: latex.extra_preamble()
'\\usepackage{foo-bar-unchecked}'
-.. _sec-custom-processing:
+Which dialect of TeX is used, and therefore the nature of the output and
+associated viewer, can also be customized.
-Customizing LaTeX Processing
-============================
+.. NOTE::
-It is also possible to control which variant of TeX is used for system-wide
-invocations, thus also influencing the nature of the output.
+ Sage includes almost everything you need to build and use Sage, but a
+ significant exception is TeX itself. So in the following situations you
+ need to have a full TeX system installed, along with some associated
+ conversion utilities. Many versions of Linux have packages based on
+ TeXLive, for macOS there is MacTeX and for Windows there is MiKTeX.
The ``latex.engine()`` command can be used to control if the system-wide
-executables ``latex``, ``pdflatex`` or ``xelatex`` are employed for more
-complicated LaTeX expressions. When ``view()`` is called and the engine is set
-to ``latex``, a dvi file is produced and Sage will use a dvi viewer (like xdvi)
-to display the result. In contrast, using ``view()`` when the engine is set to
-``pdflatex`` will produce a PDF as the result and Sage will call your system's
-utility for displaying PDF files (acrobat, okular, evince, etc.).
-
-For a concrete example of how complicated LaTeX expressions can be processed,
-see the example in the next section (:ref:`sec-tkz-graph`) for using the LaTeX
-``tkz-graph`` package to produce high-quality renderings of combinatorial
-graphs. For other examples, there are some pre-packaged test cases. To use
-these, it is necessary to import the ``sage.misc.latex.latex_examples`` object,
-which is an instance of the ``sage.misc.latex.LatexExamples`` class, as
-illustrated below. This class currently has examples of commutative diagrams,
-combinatorial graphs, knot theory and pstricks, which respectively exercise the
-following packages: xy, tkz-graph, xypic, pstricks. After the import, use
-tab-completion on ``latex_examples`` to see the pre-packaged examples. Calling
-each example will give you back some explanation about what is required to make
-the example render properly. To actually see the examples, it is necessary to
-use ``view()`` (once the preamble, engine, etc are all set properly). ::
+executables ``latex``, ``pdflatex`` or ``xelatex`` are employed. When
+``view()`` is called and the engine is set to ``latex``, a dvi file is produced
+and Sage will use a dvi viewer (like xdvi) to display the result. In contrast,
+using ``view()`` when the engine is set to ``pdflatex`` will produce a PDF as
+the result and Sage will call your system's utility for displaying PDF files
+(acrobat, okular, evince, etc.).
+
+For your exercises with these facilities, there are some pre-packaged examples.
+To use these, it is necessary to import the ``sage.misc.latex.latex_examples``
+object, which is an instance of the :class:`sage.misc.latex.LatexExamples`
+class, as illustrated below. This class currently has examples of commutative
+diagrams, combinatorial graphs, knot theory and pstricks, which respectively
+exercise the following packages: xy, tkz-graph, xypic, pstricks. After the
+import, use tab-completion on ``latex_examples`` to see the pre-packaged
+examples. Calling each example will give you back some explanation about what
+is required to make the example render properly. To actually see the examples,
+it is necessary to use ``view(foo)`` (once the preamble, engine, etc are all set
+properly). ::
sage: from sage.misc.latex import latex_examples
- sage: latex_examples.diagram()
+ sage: foo = latex_examples.diagram()
+ sage: foo
LaTeX example for testing display of a commutative diagram produced
by xypic.
@@ -269,63 +337,47 @@ use ``view()`` (once the preamble, engine, etc are all set properly). ::
and try viewing again. You should get a picture (a part of the diagram arising
from a filtered chain complex).
-.. _sec-tkz-graph:
-
-An Example: Combinatorial Graphs with tkz-graph
-===============================================
-
-High-quality illustrations of combinatorial graphs (henceforth just "graphs")
-are possible with the ``tkz-graph`` package. This package is built on top of
-the ``tikz`` front-end to the ``pgf`` library. So all of these components need
-to be part of a system-wide TeX installation, and it may be possible that these
-components may not be at their most current versions as packaged in some TeX
-implementations. So for best results, it could be necessary or advisable to
-install these as part of your personal texmf tree. Creating, maintaining and
-customizing a system-wide or personal TeX installation is beyond the scope of
-this document, but it should be easy to find instructions. The necessary files
-are listed in :ref:`sec-system-wide-tex`.
-
-Thus, to start we need to insure that the relevant packages are included by
-adding them to the preamble of the eventual LaTeX document. The images of
-graphs do not form properly when a dvi file is used as an intermediate format,
-so it is best to set the latex engine to the ``pdflatex`` executable. At this
-point a command like ``view(graphs.CompleteGraph(4))`` should produce a PDF
-with an appropriate image of the complete graph `K_4`.
+For an example of how complicated LaTeX expressions can be processed, let us see the
+example of combinatorial graphs, that use ``tkz-graph`` LaTeX package.
+
+.. NOTE::
+
+ ``tkz-graph`` LaTeX package is built on top of the ``tikz`` front-end to
+ the ``pgf`` library. Rendering combinatorial graphs requires the ``pgf``
+ library, and the files ``tkz-graph.sty`` and ``tkz-berge.sty``. It is
+ highly likely that they are already part of your system-wide TeX
+ installation. Even if not, it should be easy to find instructions to
+ install them.
+
+First, we ensure that the relevant packages are included by adding them to the
+preamble of the LaTeX document. ::
+
+ sage: latex.extra_preamble('\\usepackage{tikz}\n\\usepackage{tkz-graph}\n'
+ ....: '\\usepackage{tkz-berge}\n\\usetikzlibrary{arrows,shapes}')
+
+The images of graphs do not form properly when a dvi file is used as an
+intermediate format, so it is best to set the latex engine to the ``pdflatex``
+executable::
+
+ sage: latex.engine('pdflatex')
+
+At this point a command like ``view(graphs.CompleteGraph(4))`` should produce a
+PDF with an appropriate image of the complete graph `K_4`.
+
+Actually the preliminary steps could be omitted as the preamble is
+automatically set up properly for graphs and ``pdflatex`` is the default LaTeX
+engine in Sage. Try the command again after restarting Sage.
Note that there is a variety of options to affect how a graph is rendered in
-LaTeX via ``tkz-graph``, which is again outside the scope of this section, see
-the section of the Reference manual titled "LaTeX Options for Graphs" for
-instructions and details.
-
-.. _sec-system-wide-tex:
-
-A Fully Capable TeX Installation
-================================
-
-Many of the more advanced features of the integration of TeX with Sage requires
-a system-wide installation of TeX. Many versions of Linux have base TeX
-packages based on TeX Live, for macOS there is TeXShop and for Windows there is
-MiKTeX. The ``convert`` utility is part of the `ImageMagick
-`_ suite (which should be a package or an easy
-download), and the three programs ``dvipng``, ``ps2pdf``, and ``dvips`` may be
-included with your TeX distribution. The first two may also be obtained,
-respectively, from http://sourceforge.net/projects/dvipng/ and as part of
-`Ghostscript `_.
-
-Rendering combinatorial graphs requires a recent version of the PGF library,
-the file ``tkz-graph.sty`` from https://www.ctan.org/pkg/tkz-graph, and the
-files ``tkz-arith.sty`` and perhaps ``tkz-berge.sty`` from
-https://www.ctan.org/pkg/tkz-berge.
+LaTeX via ``tkz-graph``, which is outside the scope of this section. See the
+section :ref:`sage.graphs.graph_latex` of the Reference Manual for instructions
+and details.
+
SageTeX
=======
-SageTeX is a program available to further integrate TeX and Sage. A concise
-description of SageTeX is that it is a collection of TeX macros that allow a
-LaTeX document to include instructions to have Sage compute various objects
-and/or format objects using the ``latex()`` support built into Sage. So as an
-intermediate step of compiling a LaTeX document, all of the computational and
-LaTeX-formatting features of Sage can be handled automatically. As an example,
-a mathematics examination can maintain a correct correspondence between
-questions and answers by using SageTeX to have Sage compute one from the other.
+SageTeX is a program available to further integrate TeX and Sage. It is a
+collection of TeX macros that allow a LaTeX document to include instructions to
+have Sage compute various objects and format objects using the ``latex()``.
See :ref:`sec-sagetex` for more information.
diff --git a/src/doc/en/website/templates/index_furo.html b/src/doc/en/website/templates/index_furo.html
index ae70b6ea4df..922068b9b52 100644
--- a/src/doc/en/website/templates/index_furo.html
+++ b/src/doc/en/website/templates/index_furo.html
@@ -49,9 +49,7 @@
- This is a tour of Sage that closely follows the tour of
- Mathematica that is at the beginning of the Mathematica
- Book.
+ A one page introduction to Sage as a handy calculator.
@@ -85,7 +83,7 @@
- This tutorial is the best way to become familiar with Sage
+ The best way to become familiar with Sage
in only a few hours.
diff --git a/src/sage/env.py b/src/sage/env.py
index f4899639a6d..b1fe9a89cd1 100644
--- a/src/sage/env.py
+++ b/src/sage/env.py
@@ -1,10 +1,6 @@
r"""
Sage Runtime Environment
-AUTHORS:
-
-- \R. Andrew Ohana (2012): Initial version.
-
Verify that importing ``sage.all`` works in Sage's Python without any ``SAGE_``
environment variables, and has the same ``SAGE_ROOT`` and ``SAGE_LOCAL``
(see also :trac:`29446`)::
@@ -16,6 +12,11 @@
sage: out = check_output([sys.executable, "-c", cmd], env=env).decode().strip() # long time
sage: out == repr((SAGE_ROOT, SAGE_LOCAL)) # long time
True
+
+AUTHORS:
+
+- \R. Andrew Ohana (2012): initial version
+
"""
# ****************************************************************************
@@ -200,7 +201,6 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st
POLYTOPE_DATA_DIR = var("POLYTOPE_DATA_DIR", join(SAGE_SHARE, "reflexive_polytopes"))
GAP_LIB_DIR = var("GAP_LIB_DIR", join(SAGE_LOCAL, "lib", "gap"))
GAP_SHARE_DIR = var("GAP_SHARE_DIR", join(SAGE_SHARE, "gap"))
-THEBE_DIR = var("THEBE_DIR", join(SAGE_SHARE, "thebe"))
COMBINATORIAL_DESIGN_DATA_DIR = var("COMBINATORIAL_DESIGN_DATA_DIR", join(SAGE_SHARE, "combinatorial_designs"))
CREMONA_MINI_DATA_DIR = var("CREMONA_MINI_DATA_DIR", join(SAGE_SHARE, "cremona"))
CREMONA_LARGE_DATA_DIR = var("CREMONA_LARGE_DATA_DIR", join(SAGE_SHARE, "cremona"))
diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py
index 5687c6f9c8c..fe8d4896426 100644
--- a/src/sage/plot/plot3d/plot3d.py
+++ b/src/sage/plot/plot3d/plot3d.py
@@ -10,17 +10,6 @@
sage: S = sphere((0, 0, 0), size=0.3, color='red', aspect_ratio=[1,1,1])
sage: show(W + S, figsize=8)
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x, y = var('x y')
- W = plot3d(sin(pi*((x)^2 + (y)^2))/2, (x, -1, 1), (y, -1, 1), frame=False, color='purple', opacity=0.8)
- S = sphere((0, 0, 0), size=0.3, color='red', aspect_ratio=[1,1,1])
- show(W + S, figsize=8)
-
.. PLOT::
x, y = var('x y')
@@ -36,17 +25,6 @@
....: color=rainbow(60, 'rgbtuple'), max_bend=.1, max_depth=15)
sage: P.show()
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- def f(x,y):
- return math.sin(y^2 + x^2)/math.sqrt(x^2 + y^2 + 0.0001)
- P = plot3d(f, (-3, 3), (-3, 3), adaptive=True, color=rainbow(60, 'rgbtuple'), max_bend=.1, max_depth=15)
- P.show()
-
.. PLOT::
def f(x,y): return math.sin(y**2 + x**2)/math.sqrt(x**2 + y**2 + 0.0001)
@@ -63,20 +41,6 @@ def f(x,y): return math.sin(y**2 + x**2)/math.sqrt(x**2 + y**2 + 0.0001)
sage: S = P + axes(6, color='black')
sage: S.show()
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- def f(x,y):
- return math.exp(x/5)*math.sin(y)
-
- P = plot3d(f, (-5, 5), (-5, 5), adaptive=True, color=['red', 'yellow'])
- from sage.plot.plot3d.plot3d import axes
- S = P + axes(6, color='black')
- S.show()
-
.. PLOT::
def f(x,y): return math.exp(x/5)*math.sin(y)
@@ -93,17 +57,6 @@ def f(x,y): return math.exp(x/5)*math.sin(y)
sage: plot3d(x*x + y*y, (x, -4, 4), (y, -4, 4), color=(c, cm))
Graphics3d Object
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x, y = var('x y')
- cm = colormaps.hsv
- def c(x, y): return float((x + y + x*y)/15) % 1
- plot3d(x*x + y*y, (x, -4, 4), (y, -4, 4), color=(c, cm))
-
.. PLOT::
x, y = var('x y')
@@ -135,23 +88,6 @@ def c(x, y): return float((x + y + x*y)/15) % 1
sage: cape_man = P.scale(.2) + S.translate(1, 0, 0)
sage: cape_man.show(aspect_ratio=[1, 1, 1])
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- S = sphere(size=.5, color='yellow')
- from sage.plot.plot3d.shapes import Cone
- S += Cone(.5, .5, color='red').translate(0,0,.3)
- S += sphere((.45, -.1, .15), size=.1, color='white') + sphere((.51,-.1,.17), size=.05, color='black')
- S += sphere((.45, .1, .15), size=.1, color='white') + sphere((.51, .1,.17), size=.05, color='black')
- S += sphere((.5, 0, -.2), size=.1, color='yellow')
- def f(x,y): return math.exp(x/5)*math.cos(y)
- P = plot3d(f, (-5, 5), (-5, 5), adaptive=True, color=['red','yellow'], max_depth=10)
- cape_man = P.scale(.2) + S.translate(1, 0, 0)
- cape_man.show(aspect_ratio=[1, 1, 1])
-
.. PLOT::
S = sphere(size=.5, color='yellow')
@@ -171,14 +107,6 @@ def f(x,y): return math.exp(x/5)*math.cos(y)
sage: plot3d(pi, (-1,1), (-1,1))
Graphics3d Object
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- plot3d(pi, (-1,1), (-1,1))
-
.. PLOT::
sphinx_plot(plot3d(pi, (-1,1), (-1,1)))
@@ -577,16 +505,6 @@ class Spherical(_Coordinates):
sage: plot3d(phi * theta, (theta, 0, pi), (phi, 0, 1), transformation=T)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, phi, theta = var('r phi theta')
- T = Spherical('radius', ['azimuth', 'inclination'])
- plot3d(phi * theta, (theta, 0, pi), (phi, 0, 1), transformation=T)
-
.. PLOT::
r, phi, theta = var('r phi theta')
@@ -600,16 +518,6 @@ class Spherical(_Coordinates):
sage: plot3d(3, (r,0,3), (theta, 0, 2*pi), transformation=S)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- S = Spherical('inclination', ['radius', 'azimuth'])
- r, theta = var('r,theta')
- plot3d(r-r+3, (r,0,3), (theta, 0, 2*pi), transformation=S)
-
.. PLOT::
S = Spherical('inclination', ['radius', 'azimuth'])
@@ -666,16 +574,6 @@ class SphericalElevation(_Coordinates):
sage: plot3d(phi * theta, (theta, 0, pi), (phi, 0, 1), transformation=T)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- T = SphericalElevation('radius', ['azimuth', 'elevation'])
- r, theta, phi = var('r theta phi')
- plot3d(phi * theta, (theta, 0, pi), (phi, 0, 1), transformation=T)
-
.. PLOT::
T = SphericalElevation('radius', ['azimuth', 'elevation'])
@@ -688,24 +586,14 @@ class SphericalElevation(_Coordinates):
sage: SE = SphericalElevation('elevation', ['radius', 'azimuth'])
sage: r, theta = var('r,theta')
- sage: plot3d(3, (r,0,3), (theta, 0, 2*pi), transformation=SE)
+ sage: plot3d(3, (r, 0, 3), (theta, 0, 2*pi), transformation=SE)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- SE = SphericalElevation('elevation', ['radius', 'azimuth'])
- r, theta = var('r,theta')
- plot3d(3+r-r, (r,0,3), (theta, 0, 2*pi), transformation=SE)
-
.. PLOT::
SE = SphericalElevation('elevation', ['radius', 'azimuth'])
r, theta = var('r,theta')
- sphinx_plot(plot3d(3+r-r, (r,0,3), (theta, 0, 2*pi), transformation=SE))
+ sphinx_plot(plot3d(3 + r - r, (r,0,3), (theta, 0, 2*pi), transformation=SE))
Plot a sin curve wrapped around the equator::
@@ -715,24 +603,12 @@ class SphericalElevation(_Coordinates):
sage: P1 + P2
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, theta = var('r,theta')
- SE = SphericalElevation('elevation', ['radius', 'azimuth'])
- P1 = plot3d( (pi/12)*sin(8*theta), (r,0.99,1), (theta, 0, 2*pi), transformation=SE, plot_points=(10,200))
- P2 = sphere(center=(0,0,0), size=1, color='red', opacity=0.3)
- P1 + P2
-
.. PLOT::
r, theta = var('r,theta')
SE = SphericalElevation('elevation', ['radius', 'azimuth'])
- P1 = plot3d( (pi/12)*sin(8*theta), (r,0.99,1), (theta, 0, 2*pi), transformation=SE, plot_points=(10,200))
- P2 = sphere(center=(0,0,0), size=1, color='red', opacity=0.3)
+ P1 = plot3d( (pi/12)*sin(8*theta), (r, 0.99, 1), (theta, 0, 2*pi), transformation=SE, plot_points=(10,200))
+ P2 = sphere(center=(0, 0, 0), size=1, color='red', opacity=0.3)
sphinx_plot(P1 + P2)
Now we graph several constant elevation functions alongside several constant
@@ -753,23 +629,6 @@ class SphericalElevation(_Coordinates):
....: for a in angles]
sage: show(sum(P1+P2), aspect_ratio=1)
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, phi, theta = var('r phi theta')
- SE = SphericalElevation('elevation', ['radius', 'azimuth'])
- S = Spherical('inclination', ['radius', 'azimuth'])
- angles = [pi/18, pi/12, pi/6]
- P1=Graphics()
- P2=Graphics()
- for a in angles:
- P1 += plot3d( a, (r,0,3), (theta, 0, 2*pi), transformation=SE, opacity=0.85, color='blue')
- P2 += plot3d( a, (r,0,3), (theta, 0, 2*pi), transformation=S, opacity=0.85, color='red')
- P1+P2
-
.. PLOT::
r, phi, theta = var('r phi theta')
@@ -834,16 +693,6 @@ class Cylindrical(_Coordinates):
sage: plot3d(9-r^2, (r, 0, 3), (theta, 0, pi), transformation=T)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- T = Cylindrical('height', ['radius', 'azimuth'])
- r, theta, z = var('r theta z')
- plot3d(9-r**2, (r, 0, 3), (theta, 0, pi), transformation=T)
-
.. PLOT::
T = Cylindrical('height', ['radius', 'azimuth'])
@@ -857,21 +706,11 @@ class Cylindrical(_Coordinates):
sage: plot3d(3, (theta, 0, 2*pi), (z, -2, 2), transformation=S)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- S = Cylindrical('radius', ['azimuth', 'height'])
- theta, z = var('theta, z')
- plot3d(3, (theta, 0, 2*pi), (z, -2, 2), transformation=S)
-
.. PLOT::
S = Cylindrical('radius', ['azimuth', 'height'])
theta, z = var('theta, z')
- sphinx_plot(plot3d(3+z-z, (theta, 0, 2*pi), (z, -2, 2), transformation=S))
+ sphinx_plot(plot3d(3 + z - z, (theta, 0, 2*pi), (z, -2, 2), transformation=S))
See also :func:`cylindrical_plot3d` for more examples of plotting in cylindrical
coordinates.
@@ -1006,14 +845,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(lambda x, y: x^2 + y^2, (-2,2), (-2,2))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2))
-
.. PLOT::
sphinx_plot(plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2)))
@@ -1023,14 +854,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(lambda x, y: x^2 + y^2, (-2,2), (-2,2), adaptive=True)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2), adaptive=True)
-
.. PLOT::
sphinx_plot(plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2), adaptive=True))
@@ -1040,14 +863,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(lambda x, y: x^2 + y^2, (-2,2), (-2,2), adaptive=True, initial_depth=5)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2), adaptive=True, initial_depth=5)
-
.. PLOT::
sphinx_plot(plot3d(lambda x, y: x**2 + y**2, (-2,2), (-2,2), adaptive=True, initial_depth=5))
@@ -1059,15 +874,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(x^2 + y^2, (x,-2,2), (y,-2,2))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- var('x y')
- plot3d(x**2 + y**2, (x,-2,2), (y,-2,2))
-
.. PLOT::
var('x y')
@@ -1078,15 +884,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(sin(x*y), (x, -pi, pi), (y, -pi, pi))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- var('x y')
- plot3d(sin(x*y), (x, -pi, pi), (y, -pi, pi))
-
.. PLOT::
var('x y')
@@ -1099,15 +896,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(sin(x^2 + y^2), (x,-5,5), (y,-5,5), plot_points=200)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- var('x y')
- plot3d(sin(x^2 + y^2),(x,-5,5),(y,-5,5), plot_points=200)
-
.. PLOT::
var('x y')
@@ -1118,15 +906,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(sin(x^2 + y^2), (x, -5, 5), (y, -5, 5), plot_points=[10, 100])
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- var('x y')
- plot3d(sin(x^2 + y^2), (x, -5, 5), (y, -5, 5), plot_points=[10, 100])
-
.. PLOT::
var('x y')
@@ -1139,15 +918,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(sin(x - y)*y*cos(x), (x, -3, 3), (y, -3, 3), mesh=True)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- var('x,y')
- plot3d(sin(x - y)*y*cos(x), (x, -3, 3), (y, -3, 3), mesh=True)
-
.. PLOT::
var('x y')
@@ -1171,17 +941,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: P + Q
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x,y = var('x,y')
- P = plot3d(x + y + sin(x*y), (x, -10, 10), (y, -10, 10), opacity=0.87, color='blue')
- Q = plot3d(x - 2*y - cos(x*y),(x, -10, 10), (y, -10, 10), opacity=0.3, color='red')
- P + Q
-
.. PLOT::
x,y = var('x,y')
@@ -1197,17 +956,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: L + P + Q
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- L = plot3d(lambda x,y: 0, (-5,5), (-5,5), color="lightblue", opacity=0.8)
- P = plot3d(lambda x,y: 4 - x^3 - y^2, (-2,2), (-2,2), color='green')
- Q = plot3d(lambda x,y: x^3 + y^2 - 4, (-2,2), (-2,2), color='orange')
- L + P + Q
-
.. PLOT::
L = plot3d(lambda x,y: 0, (-5,5), (-5,5), color="lightblue", opacity=0.8)
@@ -1221,15 +969,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(sin(pi*(x^2 + y^2))/2, (x, -1, 1), (y, -1, 1))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x, y = var('x y')
- plot3d(sin(pi*(x^2 + y^2))/2, (x, -1, 1), (y, -1, 1))
-
.. PLOT::
x, y = var('x y')
@@ -1241,15 +980,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(4*x*exp(-x^2 - y^2), (x, -2, 2), (y, -2, 2))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x, y = var('x y')
- plot3d(4*x*exp(-x^2 - y^2), (x, -2, 2), (y, -2, 2))
-
.. PLOT::
x, y = var('x y')
@@ -1261,16 +991,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: trans = (r*cos(phi), r*sin(phi), z)
sage: plot3d(cos(r), (r, 0, 17*pi/2), (phi, 0, 2*pi), transformation=trans, opacity=0.87).show(aspect_ratio=(1,1,2), frame=False)
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, phi, z = var('r phi z')
- trans = (r*cos(phi), r*sin(phi), z)
- plot3d(cos(r), (r, 0, 17*pi/2), (phi, 0, 2*pi), transformation=trans, opacity=0.87).show(aspect_ratio=(1,1,2), frame=False)
-
.. PLOT::
r, phi, z = var('r phi z')
@@ -1285,16 +1005,6 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds):
sage: plot3d(3, (theta, 0, pi/2), (z, 0, pi/2), transformation=cylindrical)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, theta, z = var('r theta z')
- cylindrical(r, theta, z) = [r*cos(theta), r*sin(theta), z]
- plot3d(3, (theta, 0, pi/2), (z, 0, pi/2), transformation=cylindrical)
-
.. PLOT::
r, theta, z = var('r theta z')
@@ -1420,30 +1130,28 @@ def plot3d_adaptive(f, x_range, y_range, color="automatic",
INPUT:
- - ``f`` -- a symbolic function or a Python function of
- 3 variables.
+ - ``f`` -- a symbolic function or a Python function of 3 variables
- - ``x_range`` -- x range of values: 2-tuple (xmin,
+ - ``x_range`` -- x range of values: 2-tuple (xmin,
xmax) or 3-tuple (x,xmin,xmax)
- - ``y_range`` -- y range of values: 2-tuple (ymin,
- ymax) or 3-tuple (y,ymin,ymax)
+ - ``y_range`` -- y range of values: 2-tuple (ymin, ymax) or 3-tuple
+ (y,ymin,ymax)
- - ``grad_f`` -- gradient of f as a Python function
+ - ``grad_f`` -- gradient of f as a Python function
- - ``color`` -- "automatic" - a rainbow of num_colors
- colors
+ - ``color`` -- "automatic" - a rainbow of num_colors colors
- - ``num_colors`` -- (default: 128) number of colors to
- use with default color
+ - ``num_colors`` -- (default: 128) number of colors to use with default
+ color
- - ``max_bend`` -- (default: 0.5)
+ - ``max_bend`` -- (default: 0.5)
- - ``max_depth`` -- (default: 5)
+ - ``max_depth`` -- (default: 5)
- - ``initial_depth`` -- (default: 4)
+ - ``initial_depth`` -- (default: 4)
- - ``**kwds`` -- standard graphics parameters
+ - ``**kwds`` -- standard graphics parameters
EXAMPLES:
@@ -1454,16 +1162,6 @@ def plot3d_adaptive(f, x_range, y_range, color="automatic",
sage: plot3d_adaptive(sin(x*y), (x, -pi, pi), (y, -pi, pi), initial_depth=5)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- from sage.plot.plot3d.plot3d import plot3d_adaptive
- x, y = var('x,y')
- plot3d_adaptive(sin(x*y), (x, -pi, pi), (y, -pi, pi), initial_depth=5)
-
.. PLOT::
from sage.plot.plot3d.plot3d import plot3d_adaptive
@@ -1559,15 +1257,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: spherical_plot3d(2, (x, 0, 2*pi), (y, 0, pi))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x,y = var('x,y')
- spherical_plot3d(2, (x, 0, 2*pi), (y, 0, pi))
-
.. PLOT::
x, y = var('x,y')
@@ -1581,18 +1270,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: ima = spherical_plot3d(abs(imag(Y)), (phi, 0, 2*pi), (theta, 0, pi), color='red', opacity=0.6)
sage: (rea + ima).show(aspect_ratio=1) # long time (4s on sage.math, 2011)
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- phi, theta = var('phi, theta')
- Y = spherical_harmonic(2, 1, theta, phi)
- rea = spherical_plot3d(abs(real(Y)), (phi, 0, 2*pi), (theta, 0, pi), color='blue', opacity=0.6)
- ima = spherical_plot3d(abs(imag(Y)), (phi, 0, 2*pi), (theta, 0, pi), color='red', opacity=0.6)
- (rea + ima).show(aspect_ratio=1) # long time (4s on sage.math, 2011)
-
.. PLOT::
phi, theta = var('phi, theta')
@@ -1606,15 +1283,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: x,y = var('x,y')
sage: spherical_plot3d(e^-y, (x, 0, 2*pi), (y, 0, pi), opacity=0.5).show(frame=False)
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x,y = var('x,y')
- spherical_plot3d(e^-y, (x, 0, 2*pi), (y, 0, pi), opacity=0.5).show(frame=False)
-
.. PLOT::
x, y = var('x,y')
@@ -1626,15 +1294,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: spherical_plot3d((2 + cos(2*x))*(y + 1), (x, 0, 2*pi), (y, 0, pi), rgbcolor=(1, .1, .1))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x,y = var('x,y')
- spherical_plot3d((2 + cos(2*x))*(y + 1), (x, 0, 2*pi), (y, 0, pi), rgbcolor=(1, .1, .1))
-
.. PLOT::
x, y = var('x,y')
@@ -1646,15 +1305,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: spherical_plot3d(1 + sin(5*x)/5, (x, 0, 2*pi), (y, 0, pi), rgbcolor=(1, 0.5, 0), plot_points=(80, 80), opacity=0.7)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x,y = var('x,y')
- spherical_plot3d(1 + sin(5*x)/5, (x, 0, 2*pi), (y, 0, pi), rgbcolor=(1, 0.5, 0), plot_points=(80, 80), opacity=0.7)
-
.. PLOT::
x,y = var('x,y')
@@ -1665,15 +1315,6 @@ def spherical_plot3d(f, urange, vrange, **kwds):
sage: x, y = var('x,y')
sage: spherical_plot3d(1 + 2*cos(2*y), (x, 0, 3*pi/2), (y, 0, pi)).show(aspect_ratio=(1, 1, 1))
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- x, y = var('x,y')
- spherical_plot3d(1 + 2*cos(2*y), (x, 0, 3*pi/2), (y, 0, pi)).show(aspect_ratio=(1, 1, 1))
-
.. PLOT::
x, y = var('x,y')
@@ -1693,17 +1334,6 @@ def cylindrical_plot3d(f, urange, vrange, **kwds):
sage: plot3d(f, urange, vrange, transformation=T)
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- r, u, v = var('r,u,v')
- f = u*v; urange = (u, 0, pi); vrange = (v, 0, pi)
- T = (r*cos(u), r*sin(u), v, [u, v])
- plot3d(f, urange, vrange, transformation=T)
-
.. PLOT::
r, u, v = var('r,u,v')
@@ -1737,15 +1367,6 @@ def cylindrical_plot3d(f, urange, vrange, **kwds):
sage: cylindrical_plot3d(2, (theta, 0, 3*pi/2), (z, -2, 2))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- theta, z = var('theta,z')
- cylindrical_plot3d(2, (theta, 0, 3*pi/2), (z, -2, 2))
-
.. PLOT::
theta, z = var('theta,z')
@@ -1758,16 +1379,7 @@ def cylindrical_plot3d(f, urange, vrange, **kwds):
sage: cylindrical_plot3d(cosh(z), (theta, 0, 2*pi), (z, -2, 2))
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- theta, z = var('theta,z')
- cylindrical_plot3d(cosh(z), (theta, 0, 2*pi), (z, -2, 2))
-
- .. PLOT::
+ .. PLOT::
theta, z = var('theta,z')
sphinx_plot(cylindrical_plot3d(cosh(z), (theta, 0, 2*pi), (z, -2, 2)))
@@ -1776,22 +1388,12 @@ def cylindrical_plot3d(f, urange, vrange, **kwds):
sage: cylindrical_plot3d(e^(-z^2)*(cos(4*theta) + 2) + 1, (theta, 0, 2*pi), (z, -2, 2), plot_points=[80, 80]).show(aspect_ratio=(1, 1, 1))
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- theta, z = var('theta,z')
- cylindrical_plot3d(e^(-z^2)*(cos(4*theta) + 2) + 1, (theta, 0, 2*pi), (z, -2, 2), plot_points=[80, 80]).show(aspect_ratio=(1, 1, 1))
-
- .. PLOT::
+ .. PLOT::
theta, z = var('theta,z')
P = cylindrical_plot3d(e**(-z**2)*(cos(4*theta) + 2) + 1, (theta, 0, 2*pi), (z, -2, 2), plot_points=[80, 80])
P.aspect_ratio([1, 1, 1])
sphinx_plot(P)
-
"""
return plot3d(f, urange, vrange, transformation=Cylindrical('radius', ['azimuth', 'height']), **kwds)
@@ -1802,9 +1404,10 @@ def axes(scale=1, radius=None, **kwds):
INPUT:
- - ``scale`` -- (default: 1) The length of the axes (all three
- will be the same).
- - ``radius`` -- (default: .01) The radius of the axes as arrows.
+ - ``scale`` -- (default: 1) the length of the axes (all three will be the
+ same)
+
+ - ``radius`` -- (default: .01) the radius of the axes as arrows
EXAMPLES::
@@ -1812,16 +1415,7 @@ def axes(scale=1, radius=None, **kwds):
sage: S = axes(6, color='black'); S
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- from sage.plot.plot3d.plot3d import axes
- S = axes(6, color='black'); S
-
- .. PLOT::
+ .. PLOT::
from sage.plot.plot3d.plot3d import axes
S = axes(6, color='black')
@@ -1832,16 +1426,7 @@ def axes(scale=1, radius=None, **kwds):
sage: T = axes(2, .5); T
Graphics3d Object
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- from sage.plot.plot3d.plot3d import axes
- T = axes(2, .5); T
-
- .. PLOT::
+ .. PLOT::
from sage.plot.plot3d.plot3d import axes
T = axes(2, .5)
diff --git a/src/sage/repl/ipython_kernel/interact.py b/src/sage/repl/ipython_kernel/interact.py
index 0551c83480e..c9c3d627657 100644
--- a/src/sage/repl/ipython_kernel/interact.py
+++ b/src/sage/repl/ipython_kernel/interact.py
@@ -22,18 +22,6 @@
x: IntSlider(value=5, description='x', max=10)
sage: f.widget.children
(IntSlider(value=5, description='x', max=10), Output())
-
-.. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- from sage.repl.ipython_kernel.interact import interact
- @interact
- def f(x=(0, 10)):
- pass
-
"""
# ****************************************************************************
@@ -72,16 +60,6 @@ class sage_interactive(interactive):
x: IntSlider(value=10, description='x')
y: Text(value='hello', description='y')
z: Dropdown(description='z', options=('one', 'two', 'three'), value=None)
-
- .. ONLY:: html
-
- .. JUPYTER-EXECUTE::
- :hide-code:
- :hide-output:
-
- from sage.repl.ipython_kernel.interact import sage_interactive
- def myfunc(x=10, y="hello", z=None): pass
- sage_interactive(myfunc, x=(0,100), z=["one", "two", "three"])
"""
def __init__(self, *args, **kwds):
"""
diff --git a/src/sage/repl/rich_output/backend_ipython.py b/src/sage/repl/rich_output/backend_ipython.py
index 86bdf342e3e..69e63b76d60 100644
--- a/src/sage/repl/rich_output/backend_ipython.py
+++ b/src/sage/repl/rich_output/backend_ipython.py
@@ -17,6 +17,7 @@
import os
import sys
+import html
from IPython.display import publish_display_data
from sage.repl.rich_output.backend_base import BackendBase
from sage.repl.rich_output.output_catalog import *
@@ -574,7 +575,7 @@ def displayhook(self, plain_text, rich_output):
'text/plain': plain_text.text.get_str(),
}, {})
elif isinstance(rich_output, OutputSceneThreejs):
- escaped_html = rich_output.html.get_str().replace('"', '"')
+ escaped_html = html.escape(rich_output.html.get_str())
iframe = IFRAME_TEMPLATE.format(
escaped_html=escaped_html,
width='100%',
diff --git a/src/sage_docbuild/__main__.py b/src/sage_docbuild/__main__.py
index 77919ec4000..0d15808a69c 100644
--- a/src/sage_docbuild/__main__.py
+++ b/src/sage_docbuild/__main__.py
@@ -294,6 +294,9 @@ def setup_parser():
standard.add_argument("--no-pdf-links", dest="no_pdf_links",
action="store_true",
help="do not include PDF links in DOCUMENT 'website'; FORMATs: html, json, pickle, web")
+ standard.add_argument("--live-doc", dest="live_doc",
+ action="store_true",
+ help="make Sage code blocks live for html FORMAT")
standard.add_argument("--warn-links", dest="warn_links",
action="store_true",
help="issue a warning whenever a link is not properly resolved; equivalent to '--sphinx-opts -n' (sphinx option: nitpicky)")
@@ -474,6 +477,8 @@ def excepthook(*exc_info):
build_options.ALLSPHINXOPTS += "-n "
if args.no_plot:
os.environ['SAGE_SKIP_PLOT_DIRECTIVE'] = 'yes'
+ if args.live_doc:
+ os.environ['SAGE_LIVE_DOC'] = 'yes'
if args.skip_tests:
os.environ['SAGE_SKIP_TESTS_BLOCKS'] = 'True'
if args.use_cdns:
diff --git a/src/sage_docbuild/conf.py b/src/sage_docbuild/conf.py
index 5eca4ed29b0..b8de3d1291a 100644
--- a/src/sage_docbuild/conf.py
+++ b/src/sage_docbuild/conf.py
@@ -27,10 +27,11 @@
import sage.version
from sphinx import highlighting
+from sphinx.transforms import SphinxTransform
from IPython.lib.lexers import IPythonConsoleLexer, IPyLexer
from sage.misc.sagedoc import extlinks
-from sage.env import SAGE_DOC_SRC, SAGE_DOC, THEBE_DIR, PPLPY_DOCS, MATHJAX_DIR
+from sage.env import SAGE_DOC_SRC, SAGE_DOC, PPLPY_DOCS, MATHJAX_DIR
from sage.misc.latex_macros import sage_mathjax_macros
from sage.features import PythonModule
@@ -54,17 +55,56 @@
jupyter_execute_default_kernel = 'sagemath'
-jupyter_sphinx_thebelab_config = {
- 'requestKernel': True,
- 'binderOptions': {
- 'repo': "sagemath/sage-binder-env",
- },
- 'kernelOptions': {
- 'name': "sagemath",
- 'kernelName': "sagemath",
- 'path': ".",
- },
-}
+if os.environ.get('SAGE_LIVE_DOC', 'no') == 'yes':
+ SAGE_JUPYTER_SERVER = os.environ.get('SAGE_JUPYTER_SERVER', 'binder')
+ if SAGE_JUPYTER_SERVER.startswith('binder'):
+ # format: "binder" or
+ # "binder:sagemath/sage-binder-env" or
+ # "binder:sagemath/sage-binder-env/dev"
+ if SAGE_JUPYTER_SERVER == 'binder':
+ binder_repo = "sagemath/sage-binder-env/master"
+ else:
+ binder_repo = SAGE_JUPYTER_SERVER[7:]
+ s = binder_repo.split('/', 2)
+ if len(s) > 2:
+ binder_options = {
+ 'repo': s[0] + '/' + s[1],
+ 'ref': s[2]
+ }
+ else:
+ binder_options = {
+ 'repo': binder_repo
+ }
+ jupyter_sphinx_thebelab_config = {
+ 'requestKernel': False,
+ 'binderOptions': binder_options,
+ 'kernelOptions': {
+ 'name': "sagemath",
+ 'kernelName': "sagemath",
+ 'path': ".",
+ },
+ 'selector': "div.live-doc"
+ }
+ else: # local jupyter server
+ SAGE_JUPYTER_SERVER_TOKEN = os.environ.get('SAGE_JUPYTER_SERVER_TOKEN', 'secret')
+ jupyter_sphinx_thebelab_config = {
+ 'requestKernel': False,
+ 'kernelOptions': {
+ 'name': "sagemath",
+ 'kernelName': "sagemath",
+ 'path': ".",
+ 'serverSettings': {
+ 'baseUrl': SAGE_JUPYTER_SERVER,
+ 'token': SAGE_JUPYTER_SERVER_TOKEN
+ },
+ },
+ 'selector': "div.live-doc"
+ }
+ jupyter_sphinx_thebelab_config.update({
+ 'codeMirrorConfig': {
+ 'lineNumbers': True,
+ }
+ })
# This code is executed before each ".. PLOT::" directive in the Sphinx
# documentation. It defines a 'sphinx_plot' function that displays a Sage object
@@ -310,7 +350,14 @@ def set_intersphinx_mappings(app, config):
# or fully qualified paths (eg. https://...)
html_css_files = [
'custom-furo.css',
+ 'custom-jupyter-sphinx.css',
+ 'custom-codemirror-monokai.css',
]
+
+ html_js_files = [
+ 'jupyter-sphinx-furo.js',
+ ]
+
# A list of paths that contain extra templates (or templates that overwrite
# builtin/theme-specific templates). Relative paths are taken as relative
# to the configuration directory.
@@ -348,8 +395,7 @@ def set_intersphinx_mappings(app, config):
# conf.py read by Sphinx was the cause of subtle bugs in builders (see #30418 for
# instance). Hence now html_common_static_path contains the common paths to static
# files, and is combined to html_static_path in each conf.py file read by Sphinx.
-html_common_static_path = [os.path.join(SAGE_DOC_SRC, 'common', 'static'),
- THEBE_DIR, 'static']
+html_common_static_path = [os.path.join(SAGE_DOC_SRC, 'common', 'static'), 'static']
# Configure MathJax
# https://docs.mathjax.org/en/latest/options/input/tex.html
@@ -913,6 +959,69 @@ class will be properly documented inside its surrounding class.
return skip
+from jupyter_sphinx.ast import JupyterCellNode, CellInputNode
+
+class SagecodeTransform(SphinxTransform):
+ """
+ Transform a code block to a live code block enabled by jupyter-sphinx.
+
+ Effectively a code block like::
+
+ EXAMPLE::
+
+ sage: 1 + 1
+ 2
+
+ is transformed into::
+
+ EXAMPLE::
+
+ sage: 1 + 1
+ 2
+
+ .. ONLY:: html
+
+ .. JUPYTER-EXECUTE::
+ :hide-code:
+ :hide-output:
+ :raises:
+ :stderr:
+
+ 1 + 1
+
+ enabling live execution of the code.
+ """
+ # lower than the priority of jupyer_sphinx.execute.ExecuteJupyterCells
+ default_priority = 170
+
+ def apply(self):
+ if self.app.builder.tags.has('html') or self.app.builder.tags.has('inventory'):
+ for node in self.document.traverse(nodes.literal_block):
+ if node.get('language') is None and node.astext().startswith('sage:'):
+ source = node.rawsource
+ lines = []
+ for line in source.splitlines():
+ newline = line.lstrip()
+ if newline.startswith('sage: ') or newline.startswith('....: '):
+ lines.append(newline[6:])
+ cell_node = JupyterCellNode(
+ execute=False,
+ hide_code=True,
+ hide_output=True,
+ emphasize_lines=[],
+ raises=False,
+ stderr=True,
+ code_below=False,
+ classes=["jupyter_cell"])
+ cell_input = CellInputNode(classes=['cell_input','live-doc'])
+ cell_input += nodes.literal_block(
+ text='\n'.join(lines),
+ linenos=False,
+ linenostart=1)
+ cell_node += cell_input
+
+ node.parent.insert(node.parent.index(node) + 1, cell_node)
+
# This replaces the setup() in sage.misc.sagedoc_conf
def setup(app):
app.connect('autodoc-process-docstring', process_docstring_cython)
@@ -924,6 +1033,8 @@ def setup(app):
app.connect('autodoc-process-docstring', skip_TESTS_block)
app.connect('autodoc-skip-member', skip_member)
app.add_transform(SagemathTransform)
+ if os.environ.get('SAGE_LIVE_DOC', 'no') == 'yes':
+ app.add_transform(SagecodeTransform)
# When building the standard docs, app.srcdir is set to SAGE_DOC_SRC +
# 'LANGUAGE/DOCNAME'.
diff --git a/src/sage_docbuild/sphinxbuild.py b/src/sage_docbuild/sphinxbuild.py
index 94407cad5eb..5ae1d2e6b10 100644
--- a/src/sage_docbuild/sphinxbuild.py
+++ b/src/sage_docbuild/sphinxbuild.py
@@ -77,14 +77,14 @@ def _init_chatter(self):
re.compile(r'^loading cross citations... done \([0-9]* citations\).'),
re.compile('^Compiling a sub-document'),
re.compile('^updating environment: 0 added, 0 changed, 0 removed'),
+ re.compile('^executing .*'),
re.compile('^looking for now-outdated files... none found'),
re.compile(r'^building \[.*\]: targets for 0 source files that are out of date'),
re.compile(r'^building \[.*\]: targets for 0 po files that are out of date'),
re.compile(r'^building \[.*\]: targets for 0 mo files that are out of date'),
re.compile('^pickling environment... done'),
re.compile('^dumping object inventory... done'),
- # We still have "Build finished."
- re.compile('^build succeeded.'),
+ re.compile('^build succeeded.'), # We still have "Build finished."
re.compile('^checking consistency... done'),
re.compile('^preparing documents... done'),
re.compile('^copying extra files... done'),