Skip to content

Commit

Permalink
docs: add a "Copy Commands" button for shell-session snippets
Browse files Browse the repository at this point in the history
Add a "Copy Commands" to some code blocks. This new button attempts to
copy only commands (and not their output) to the clipboard. The
distinction between commands and output relies on the presence of a
prompt symbol, either "$" or "#", at the beginning of the commands. If a
command ends with a trailing backslash, copy the next line as well.

For example, the following snippet:

    .. code-block:: shell-session

        $ ls -l
        foo
        cat
        $ echo 1 \
        2 \
                3\
            4
        $nospace
        # exit

should place the following text into the clipboard:

    ls -l
    echo 1
    2
            3
        4
    exit

The button is added for the following blocks, when they contain several
lines and at least one command is found in the block:

- "code-block", but with language "shell-session" only,
- Literal blocks ("::"),
- Parsed literals.

Signed-off-by: Quentin Monnet <quentin@isovalent.com>
  • Loading branch information
qmonnet authored and aanm committed Jun 8, 2021
1 parent b8ca924 commit 869e678
Showing 1 changed file with 52 additions and 1 deletion.
53 changes: 52 additions & 1 deletion Documentation/_static/copybutton.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ function addCopyButtonToCodeCells() {
setTimeout(addCopyButtonToCodeCells, 1000);
return;
}
const promptRegExp = /^\s*(\$|#)\s/;
var codeCells = document.querySelectorAll(".rst-content pre");
codeCells.forEach(function(codeCell, index) {
var wrapper = document.createElement("div");
Expand All @@ -36,7 +37,8 @@ function addCopyButtonToCodeCells() {
var id = codeCellId(index);
codeCell.setAttribute("id", id);
function clipboardButton(id) {
var linesCount = codeCell.textContent.trim().split("\n").length;
var lines = codeCell.textContent.trim().split("\n");
var linesCount = lines.length;
var buttonHtml = [];
buttonHtml.push('<div class="copybutton-wrapper">');
buttonHtml.push(
Expand All @@ -50,6 +52,37 @@ function addCopyButtonToCodeCells() {
buttonHtml.push(linesCount > 1 ? "Copy First Line" : "Copy Line");
buttonHtml.push("</a>");
if (linesCount > 1) {
/*
* Add a button to print commands for literal and code blocks that may
* have prompt symbols to distinguish the commands from their output.
*
* Add it to:
* - "code-block" with language "shell-session", with a parent of class
* ".highlight-shell-session"
* - Literal blocks ("::"), with a parent of class ".highlight-default"
* - Parsed literal blocks, with a parent of class ".literal-block"
*
* Do not add it to a "code-block" with a language other than
* "shell-session".
*/
if (codeCell.closest(".highlight-shell-session") ||
codeCell.closest(".highlight-default") ||
codeCell.closest("literal-block")) {
for (const l of lines) {
/* Additionally, only add button if we find at least one command */
if (promptRegExp.test(l)) {
buttonHtml.push(
'<a class="copybutton" data-clipboard-mode="commands" data-clipboard-target="#' +
id +
'">'
);
buttonHtml.push("Copy Commands");
buttonHtml.push("</a>");
break;
}
}
}

buttonHtml.push(
'<a class="copybutton" data-clipboard-mode="all" data-clipboard-target="#' +
id +
Expand All @@ -75,6 +108,24 @@ function addCopyButtonToCodeCells() {
.trim()
.replace(/^\$/, "")
.trim();
} else if (mode === "commands") {
/*
* Copy lines with "commands": each line starting with a prompt symbol
* ($ or #), plus the continuation lines, for commands ending with a
* backslash.
*/
var cmds = "";
var continuation = false;
var lines = code.textContent.split("\n");
for (const l of lines) {
if (promptRegExp.test(l) || continuation) {
/* Keep line but remove prompt */
cmds += l.replace(promptRegExp, "") + "\n";
/* Expect a continuation line if command ends with a backslash */
continuation = /\\\s*$/.test(l);
}
}
return cmds;
} else {
return code.textContent;
}
Expand Down

0 comments on commit 869e678

Please sign in to comment.