## Chapter 3. Callouts

Callouts are a mechanism for decorating the verbatim content of programlisting elements with marks that can be cross-referenced in documentation. They have the real advantage that they can be used to decorate the actual code or other listing. Importing the actual listing assures that the documented listing and the actual listing will be the same.

A system where you have to import the code or add the markup inline introduces the risk that the listing being documented will not be updated when the underlying resource is updated.

The program below computes the “nth” Fibonacci number.

1#!/bin/env python
 
"""Computes the n'th Fibonacci number."""
 
5import sys
import math
import click  ①
 
SQRT5 = math.sqrt(5)  ②


Click is my current favorite library for parsing command line arguments in Python.

This constant1 is the $\sqrt{5}$.

I’m also taking advantage of the ability to use XInclude (and RFC 5147) to break the listing into manageable fragments for documentation. The listing above, and the one below, are lines from the same file.

11@click.command()
@click.argument("number", nargs=1,
               ③ type=click.IntRange(1, None))
def fibonacci(number):
15    """Calculate the 'number'th Fibonacci number."""
    prefix = f"The {make_ordinal(number)} Fibonacci number is "
    try:
        value = (((1 + SQRT5) / 2) ** number -
                 ((1 - SQRT5) / 2) ** number) / SQRT5      ④
20        print(f"{prefix}{math.floor(value):,}.")
    except OverflowError:
        print(f"{prefix}too large to calculate.")
        sys.exit(1)
 
25 
def make_ordinal(n):
    """Create an ordinal from a number."""
    # https://stackoverflow.com/questions/9647202          ⑤
    suffix = ["th", "st", "nd", "rd", "th"][min(n % 10, 4)]
30    if 11 <= (n % 100) <= 13:
        suffix = "th"
    return str(n) + suffix
 
 
35if __name__ == "__main__":
    fibonacci()  ⑥


One of the real strengths of using a tool like Click to wrangle arguments is that you get type and range checking pretty much for free.

This is the closed-form solution to finding the “nth” Fibonacci number:

$\frac{1}{\sqrt{5}}\left({\left(\frac{1+\sqrt{5}}{2}\right)}^{n}-{\left(\frac{1-\sqrt{5}}{2}\right)}^{n}\right)$

The closed-form solution amuses me because I used calculating Fibonacci numbers (recursively) as an argument for greater expressive power in XSLT 1.0. “What if I wanted to number a list with the Fibonacci numbers?”

Stackoverflow showed me how to print the number as an ordinal.

Finally, if this is a main program, compute the answer.

If you hover over the callout numbers in the listing, alt-text will be displayed.