Skip to main content

Prevent accidentally copying the prompt character in console code snippets

My posts often include some commands to be run at a console, for example:

$ echo "hello world"
hello world

Here the command is echo "hello world" and the output is hello world. I’ve included the command prompt $ in the snippet, but if somebody’s copying the command, I don’t want them to accidentally copy the prompt character.

To avoid this, I have some CSS that makes the prompt character unselectable. What I’ve done is specific to my choice of syntax highlighter, but you can adapt this for other highlighters.

Here’s what the Markdown source for that snippet looks like:

```console
$ echo "hello world"
hello world
```

and here’s the HTML generated by the Rouge syntax highlighter I’m using (with added linebreaks for readability):

<div class="language-console highlighter-rouge">
  <div class="highlight">
    <pre class="highlight">
      <code>
        <span class="gp">$</span>
        <span class="w"> </span>
        <span class="nb">echo</span> <span class="s2">"hello world"</span><span class="go">hello world</span>
      </code>
    </pre>
  </div>
</div>

The syntax highlighter has broken the code into “tokens”, and each token is an individual <span>. The class attribute on the span tells us what sort of token this is – whitespace, keyword, constant, and so on – from the list of tokens supported by Rouge. Those classes can then be used in CSS rules to make certain tokens a particular colour, or weight, or style.

The two tokens I’m interested in are the gp (Generic.Prompt) and w (Text.Whitespace) tokens, which create the $ prompt at the start of the line.

The following CSS will prevent either of those tokens being selected:

.language-console .gp, .language-console .gp + .w {
  /* Disable text selection highlighting
   * https://stackoverflow.com/a/4407335/1558022 */
  -webkit-touch-callout: none; /* iOS Safari */
    -webkit-user-select: none; /* Safari */
     -khtml-user-select: none; /* Konqueror HTML */
       -moz-user-select: none; /* Firefox */
        -ms-user-select: none; /* Internet Explorer/Edge */
            user-select: none; /* Non-prefixed version, currently
                                  supported by Chrome and Opera */
}

I’ve deliberately limited this to code blocks using .language-console, so this doesn’t accidentally break copying of code blocks in other languages.

I’ve also used a + (the adjacent sibling operator) so it only matches whitespace immediately after a command prompt, and doesn’t break copying of whitespace in the middle of a line.

Most syntax highlighting tools use this sort of approach. This exact CSS won’t work if you don’t use Rouge, but by studying the generated HTML you should be able to write similar CSS that excludes copying the prompt in your snippets.