打印纵轴时,我们希望每隔五行插入类似 ‘5 -’ 和 ‘10 - ’ 这样的字符串。 此外,我们希望数字和短横线对齐,因此较短的数字需要在前面补空格。如果部分字符串使用两位数,那么一位数的字符串必须在数字前补一个空格。
要获取数字的长度,需要使用 length 函数。但 length 只能用于字符串,不能直接用于数字。因此必须先将数字转换为字符串,这可以通过 number-to-string 函数实现。例如:
(length (number-to-string 35))
⇒ 2
(length (number-to-string 100))
⇒ 3
(number-to-string 也叫作 int-to-string;你会在不同资料中看到这个别名。)
此外,每个标注中的数字后面都会跟着类似 ‘ - ’ 的字符串,我们称之为 Y-axis-tic 刻度标记。该变量使用 defvar 定义:
(defvar Y-axis-tic " - " "纵轴标注中跟在数字后的字符串。")
纵轴标注的总长度为刻度标记长度与图表顶端数字长度之和。
(length (concat (number-to-string height) Y-axis-tic)))
该值会由 print-graph 函数在其变量列表中计算为 full-Y-label-width 并传递使用。(注意我们最初提出变量列表时并未想到包含它。)
要构造完整的纵轴标注,需要将数字与刻度标记拼接;根据数字长度,前面可能带有一个或多个空格。一个标注由三部分组成:(可选的)前导空格、数字、刻度标记。函数接收当前行对应的数字,以及顶端行宽度(由 print-graph 只计算一次)作为参数。
(defun Y-axis-element (number full-Y-label-width) "构造带 NUMBER 数字的标注元素。 一个带编号的元素形如 ` 5 - ', 并根据需要填充空格,使其与最大数字的标注对齐。"
(let* ((leading-spaces
(- full-Y-label-width
(length
(concat (number-to-string number)
Y-axis-tic)))))
(concat
(make-string leading-spaces ? )
(number-to-string number)
Y-axis-tic)))
Y-axis-element 函数将前导空格(如有)、转为字符串的数字以及刻度标记拼接在一起。
为计算标注需要多少前导空格,函数用目标标注宽度减去实际标注长度——即数字长度加上刻度标记长度。
空格使用 make-string 函数插入。该函数接收两个参数:第一个指定字符串长度,第二个以特殊格式指定要插入的字符符号。格式为问号后跟空格,即 ‘? ’。关于字符语法的说明,参见 See Character Type in The GNU Emacs Lisp Reference Manual。(当然,你也可以把空格换成其他字符……你知道该怎么做。)
拼接表达式中使用了 number-to-string 函数,将数字转为字符串后与前导空格和刻度标记拼接。