From 8033643754d3c602794776af7f78dbda7205282b Mon Sep 17 00:00:00 2001 From: AC Date: Thu, 15 Oct 2026 12:34:17 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9A=20DOCS:=20Match=20longer=20IPython?= =?UTF-8?q?=20continuation=20prompts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/conf.py | 2 +- docs/use.md | 19 ++++++++++++++----- sphinx_copybutton/_static/test.js | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 1f80aea..0cf17ed 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -111,7 +111,7 @@ myst_enable_extensions = ["colon_fence"] # CopyButton configuration -copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " +copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.{3,}: | {5,8}: " copybutton_prompt_is_regexp = True copybutton_line_continuation_character = "\\" copybutton_here_doc_delimiter = "EOT" diff --git a/docs/use.md b/docs/use.md index f833200..bfe27ff 100644 --- a/docs/use.md +++ b/docs/use.md @@ -85,7 +85,7 @@ i.e. at [RegEx101]. For example this documentation uses the following configuration: ```python -copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.\.\.: | {5,8}: " +copybutton_prompt_text = r">>> |\.\.\. |\$ |In \[\d*\]: | {2,5}\.{3,}: | {5,8}: " copybutton_prompt_is_regexp = True ``` @@ -106,13 +106,16 @@ Which matches the following prompts and their continuations if they exist: - ``r'\$ '`` - ``'$ '`` * - ``ipython`` and ``qtconsole`` + continuation - - ``r'In \[\d*\]: | {2,5}\.\.\.: '`` - - ``'In []: '``, ``'In [999]: '``, ``' ...: '``, ``' ...: '`` + - ``r'In \[\d*\]: | {2,5}\.{3,}: '`` + - ``'In []: '``, ``'In [999]: '``, ``' ...: '``, ``' ....: '``, ``' .....: '``, ``' ...: '`` * - ``jupyter-console`` + continuation - ``r'In \[\d*\]: | {5,8}: '`` - ``'In []: '``, ``'In [999]: '``, ``' ...: '``, ``' ...: '`` ``` +The IPython Sphinx directive adds continuation dots as the cell number grows (for example, `In [10]:` uses ` ....: `). +The `\.{3,}` pattern matches these longer prompts as well as the three-dot prompts used by interactive IPython and QtConsole. + An example usage would be the `ipython`-directive: ```restructuredtext @@ -123,7 +126,10 @@ An example usage would be the `ipython`-directive: In [1]: first ...: continuation output - In [2]: second + In [10]: first + ....: continuation + output + In [11]: second ``jupyter`` style: @@ -141,7 +147,10 @@ An example usage would be the `ipython`-directive: In [1]: first ...: continuation output -In [2]: second +In [10]: first + ....: continuation +output +In [11]: second ``` `jupyter` style: diff --git a/sphinx_copybutton/_static/test.js b/sphinx_copybutton/_static/test.js index f2158d5..47b1431 100644 --- a/sphinx_copybutton/_static/test.js +++ b/sphinx_copybutton/_static/test.js @@ -1,4 +1,6 @@ import test from 'ava'; +import { readFileSync } from 'fs'; +import { join } from 'path'; import { formatCopyText, filterText } from "./copybutton_funcs"; const parameters = [ @@ -300,3 +302,21 @@ filterParameters.forEach((p) => { }); }) */ + + +// Exercise the configuration that readers copy and the documentation itself uses. +const docsConfig = readFileSync(join(__dirname, '../../docs/conf.py'), 'utf8'); +const documentedPrompt = docsConfig.match(/^copybutton_prompt_text = r"(.*)"$/m)[1]; +const usage = readFileSync(join(__dirname, '../../docs/use.md'), 'utf8'); +test('documented prompt matches the documentation configuration', t => { + t.true(usage.includes(`copybutton_prompt_text = r"${documentedPrompt}"`)); +}); + +[1, 10, 100, 1000].forEach(count => { + test(`documented prompt copies IPython cell ${count} continuations`, t => { + // IPython's Sphinx directive uses two more dots than counter digits. + const continuation = ' ' + '.'.repeat(String(count).length + 2) + ': '; + const text = `In [${count}]: for value in [1, 2]:\n${continuation} print(value)\n1\n2`; + t.is(formatCopyText(text, documentedPrompt, true), 'for value in [1, 2]:\n print(value)'); + }); +});