最终版与我们之前的规划有两处不同:第一,它在变量列表中增加了一次性计算的若干值;第二,它增加了一个选项,用于指定每行标注的增量。后一功能后来被证明是必不可少的;否则图表可能会有超出显示器或纸张可容纳的行数。
这一新功能要求修改 Y-axis-column 函数,为其增加 vertical-step 参数。函数如下:
;;; Final version.
(defun Y-axis-column
(height width-of-label &optional vertical-step)
"构造纵轴标注列表。
HEIGHT 是图表最大高度。
WIDTH-OF-LABEL 是标注最大宽度。
VERTICAL-STEP 为可选参数,是一个正整数,
指定纵轴标注每行递增多少。
例如,步长 5 表示每一行代表图表的 5 个单位。"
(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)))
图表最大高度和符号宽度的值由 print-graph 在其 let 表达式中计算;因此 graph-body-print 必须修改以接收这些值。
;;; Final version.
(defun graph-body-print (numbers-list height symbol-width)
"打印 NUMBERS-LIST 对应的柱状图。
数字列表由纵轴数值组成。
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)
;; 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")))
最后是 print-graph 函数的代码:
;;; Final version.
(defun print-graph
(numbers-list &optional vertical-step)
"打印带标注的 NUMBERS-LIST 柱状图。
数字列表由纵轴数值组成。
可选参数 VERTICAL-STEP 为正整数, 指定纵轴标注每行递增多少。 例如,步长 5 表示每一行代表 5 个单位。
(let* ((symbol-width (length graph-blank))
;; 既是最大数字,也是位数最多的数字。
(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)))