Recent Posts

My weekly workflow

7 minute read


I’ve had a bunch of conversations with friends who were interested in how to keep track of the various projects they’re working on, and to prioritize their time over the course of a week. I thought it might be helpful to post my own approach to planning time throughout the week in case it’s useful for others to riff off of.

Signaling openness

7 minute read


How do open projects signal their “openness” to the outside community? This is a really hard question, particularly because nowadays “open” has become a buzzword that doesn’t just signal a project’s position to the community, but is also used as a marketing term to increase support, users, or resources.

I like Rust’s governance structure

9 minute read


Recently I’ve been reading up on governance models for several large-ish open source projects. This is partially because I’m involved in a bunch of these projects myself, and partially because it’s fascinating to see distributed groups of people organizing themselves in effective (or not) ways on the internet.

Using CircleCI to preview documentation in Pull Requests

4 minute read


Writing documentation is important - it’s the first point of contact between many users and your project, and can be a pivotal moment in whether they decide to adopt your tech or become a contributor.

Summer conference report back

6 minute read


This is a short update on several of the conferences and workshops over the summer of this year. There’s all kinds of exciting things going on in open source and open communities, so this is a quick way for me to collect my thoughts on some things I’ve learned this summer.

Adding copy buttons to code blocks in Sphinx

3 minute read


NOTE: This is now a sphinx extension! Thanks to some friendly suggestions, I’ve written this up as a super tiny sphinx extension. Check it out here:

Sphinx is a fantastic way to build documentation for your Python package. On the Jupyter project, we use it for almost all of our repositories.

A common use for Sphinx is to step people through a chunk of code. For example, in the Zero to JupyterHub for Kubernetes guide we step users through a number of installation and configuration steps.

A common annoyance is that there is a lot of copy/pasting involved. Sometimes you accidentally miss a character or some whitespace. So, I spent a bit of time figuring out how to automatically embed a copy button into code blocks. It turns out this is pretty easy!

Here’s what the final result will look like (just hover the code block below)

wow = this_text
is_so = much*more*copyable

Adding a copy button to your Sphinx code blocks

To accomplish this we’ll use the excellent clipboard.js which provides the machinery for copying the contents of an HTML element as well as jquery for modifying our built documentation on-demand.

The result will be a Sphinx site with code blocks that display a copy button when you hover over them. You can see how it looks on this very page, which uses a similar method (but is built with Jekyll).

Here’s what you should do:

  1. Add the clipboard.js javascript. Create a javascript script called doc/_static/custom.js. In the file, put the following code (see comments for explanation):

     function addCopyButtonToCode(){
     // get all code elements
     var allCodeBlocksElements = $( "div.highlight pre" );
     // For each element, do the following steps
     allCodeBlocksElements.each(function(ii) {
     // define a unique id for this element and add it
     var currentId = "codeblock" + (ii + 1);
     $(this).attr('id', currentId);
     // create a button that's configured for clipboard.js
     // point it to the text that's in this code block
     // add the button just after the text in the code block w/ jquery
     var clipButton = '<button class="btn copybtn" data-clipboard-target="#' + currentId + '"><img src="" width="13" alt="Copy to clipboard"></button>';
     // tell clipboard.js to look for clicks that match this query
     new Clipboard('.btn');
     $(document).ready(function () {
     // Once the DOM is loaded for the page, attach clipboard buttons
  2. Add some CSS to make it pretty. Create a custom CSS file called doc/_static/custom.css (or add to one you’ve already got). In the file, put these lines:

    /* Copy buttons */
    button.copybtn {
      webkit-transition: opacity .3s ease-in-out;
      -o-transition: opacity .3s ease-in-out;
      transition: opacity .3s ease-in-out;
      opacity: 0;
      padding: 2px 6px;
      position: absolute;
      right: 4px;
      top: 4px;
    div.highlight:hover .copybtn, div.highlight .copybtn:focus {
        opacity: .3;
    div.highlight .copybtn:hover {
        opacity: 1;
    div.highlight {
        position: relative;
  3. Link these scripts in your configuration. You need to link your custom JS and CSS scripts, as well as the clipboard.js script so it ships with your site. In your file, add the following function/lines (or add to one you’ve already got defined).

    def setup(app):

And that’s it! Once you clear your Sphinx cache and re-build your site, you should now have buttons that appear when you hover over them, and that copy the text inside when you click them.


Many thanks to this StackOverflow post for the majority of the code that led to this hack!

Blog Archive