最终版本的更改

最终版本与我们计划的不同,有两点不同:首先,它包含了一次在变量列表中计算的附加值;其次,它带有一个选项,用于指定标签每行的增量。 后者的功能证明是必要的;否则,图表可能具有超过显示屏或纸张上能容纳的行数。

这个新功能需要对 Y-axis-column 函数进行更改,以添加 vertical-step。该函数如下:

;;; 最终版本。
(defun Y-axis-column
  (height width-of-label &optional vertical-step)
  "构建Y轴标签列表。
HEIGHT 是图表的最大高度。
WIDTH-OF-LABEL 是标签的最大宽度。
VERTICAL-STEP,一个可选项,是一个正整数,
用于指定每行的Y轴标签增量。
例如,步长为5表示每行是图表的五个单位。"
  (let (Y-axis
        (number-per-line (or vertical-step 1)))
    (while (> height 1)
      (if (zerop (% height Y-axis-label-spacing))
          ;; 插入标签。
          (setq Y-axis
                (cons
                 (Y-axis-element
                  (* height number-per-line)
                  width-of-label)
                 Y-axis))
        ;; 否则,插入空白。
        (setq Y-axis
              (cons
               (make-string width-of-label ? )
               Y-axis)))
      (setq height (1- height)))
    ;; 插入基准线。
    (setq Y-axis (cons (Y-axis-element
                        (or vertical-step 1)
                        width-of-label)
                       Y-axis))
    (nreverse Y-axis)))

图表的最大高度和符号宽度的值由 print-graph 在其 let 表达式中计算;因此,graph-body-print 必须更改以接受它们。

;;; 最终版本。
(defun graph-body-print (numbers-list height symbol-width)
  "打印NUMBERS-LIST的条形图。
numbers-list 包含Y轴值。
HEIGHT 是图表的最大高度。
SYMBOL-WIDTH 是每列的数字。"
  (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)
      ;; 逐列绘制图表。
      (sit-for 0)
      (setq numbers-list (cdr numbers-list)))
    ;; 放置X轴标签的点。
    (forward-line height)
    (insert "\n")))

最后,print-graph 函数的代码:

;;; 最终版本。
(defun print-graph
  (numbers-list &optional vertical-step)
  "打印带有标签的条形图 NUMBERS-LIST。
numbers-list 包含Y轴值。

可选的,VERTICAL-STEP,一个正整数,
指定每行的Y轴标签增量。
例如,步长为5表示每行是图表的五个单位。"
  (let* ((symbol-width (length graph-blank))
         ;; height 既是最大的数字
         ;; 也是数字位数最多的数字。
         (height (apply 'max numbers-list))
         (height-of-top-line
          (if (zerop (% height Y-axis-label-spacing))
              height
            ;; 否则
            (* (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)))