eintr: The final version

 
 Changes for the Final Version
 -----------------------------
 
 The final version is different from what we planned in two ways: first,
 it contains additional values calculated once in the varlist; second, it
 carries an option to specify the labels’ increment per row.  This latter
 feature turns out to be essential; otherwise, a graph may have more rows
 than fit on a display or on a sheet of paper.
 
    This new feature requires a change to the ‘Y-axis-column’ function,
 to add ‘vertical-step’ to it.  The function looks like this:
 
      ;;; Final version.
      (defun Y-axis-column
        (height width-of-label &optional vertical-step)
        "Construct list of labels for Y axis.
      HEIGHT is maximum height of graph.
      WIDTH-OF-LABEL is maximum width of label.
      VERTICAL-STEP, an option, is a positive integer
      that specifies how much a Y axis label increments
      for each line.  For example, a step of 5 means
      that each line is five units of the graph."
        (let (Y-axis
              (number-per-line (or vertical-step 1)))
          (while (> height 1)
            (if (zerop (% height Y-axis-label-spacing))
                ;; Insert label.
                (setq Y-axis
                      (cons
                       (Y-axis-element
                        (* height number-per-line)
                        width-of-label)
                       Y-axis))
              ;; Else, insert blanks.
              (setq Y-axis
                    (cons
                     (make-string width-of-label ? )
                     Y-axis)))
            (setq height (1- height)))
          ;; Insert base line.
          (setq Y-axis (cons (Y-axis-element
                              (or vertical-step 1)
                              width-of-label)
                             Y-axis))
          (nreverse Y-axis)))
 
    The values for the maximum height of graph and the width of a symbol
 are computed by ‘print-graph’ in its ‘let’ expression; so
 ‘graph-body-print’ must be changed to accept them.
 
      ;;; Final version.
      (defun graph-body-print (numbers-list height symbol-width)
        "Print a bar graph of the NUMBERS-LIST.
      The numbers-list consists of the Y-axis values.
      HEIGHT is maximum height of graph.
      SYMBOL-WIDTH is number of each column."
        (let (from-position)
          (while numbers-list
            (setq from-position (point))
            (insert-rectangle
             (column-of-graph height (car numbers-list)))
            (goto-char from-position)
            (forward-char symbol-width)
            ;; Draw graph column by column.
            (sit-for 0)
            (setq numbers-list (cdr numbers-list)))
          ;; Place point for X axis labels.
          (forward-line height)
          (insert "\n")))
 
    Finally, the code for the ‘print-graph’ function:
 
      ;;; Final version.
      (defun print-graph
        (numbers-list &optional vertical-step)
        "Print labeled bar graph of the NUMBERS-LIST.
      The numbers-list consists of the Y-axis values.
 
      Optionally, VERTICAL-STEP, a positive integer,
      specifies how much a Y axis label increments for
      each line.  For example, a step of 5 means that
      each row is five units."
        (let* ((symbol-width (length graph-blank))
               ;; height is both the largest number
               ;; and the number with the most digits.
               (height (apply 'max numbers-list))
               (height-of-top-line
                (if (zerop (% height Y-axis-label-spacing))
                    height
                  ;; else
                  (* (1+ (/ height Y-axis-label-spacing))
                     Y-axis-label-spacing)))
               (vertical-step (or vertical-step 1))
               (full-Y-label-width
                (length
                 (concat
                  (number-to-string
                   (* height-of-top-line vertical-step))
                  Y-axis-tic))))
 
          (print-Y-axis
           height-of-top-line full-Y-label-width vertical-step)
          (graph-body-print
           numbers-list height-of-top-line symbol-width)
          (print-X-axis numbers-list)))