最初の関数は、X軸の目盛りを出力する必要があります。目盛り自体とその間隔を指定しなければなりません:
(defvar X-axis-label-spacing
(if (boundp 'graph-blank)
(* 5 (length graph-blank)) 5)
"Number of units from one X axis label to next.")
(なお、graph-blank の値は別の defvar によって設定されます。boundp
述語はすでに設定されているかどうかを判定し、設定されていなければ boundp は nil を返します。もし graph-blank
が未束縛であり、この条件付き構文を使用しなかった場合、デバッガに入り、‘Debugger entered--Lisp error:
(void-variable graph-blank)’ というエラーメッセージが表示されることになります。)
X-axis-tic-symbol に対する defvar は以下の通りです:
(defvar X-axis-tic-symbol "|" "String to insert to point to a column in X axis.")
目標は、このような線を作ることです:
| | | |
最初のティックは、Y軸のラベル用のスペースを確保するためにインデントされた第1列の下に配置されるよう、インデントされています。
ティック要素は、あるティックから次のティックまで延びる空白部分と、ティック記号で構成されます。空白の数は、ティック記号の幅とX-axis-label-spacingによって決まります。
コードはこんな感じです:
;;; X-axis-tic-element ... (concat (make-string ;; Make a string of blanks. (- (* symbol-width X-axis-label-spacing) (length X-axis-tic-symbol)) ? ) ;; Concatenate blanks with tic symbol. X-axis-tic-symbol) ...
次に、最初の目盛りをグラフの第1列までインデントするために必要な空白の数を算出します。ここでは、print-graph関数から渡されたfull-Y-label-widthの値を使用します。
X-axis-leading-spaces を作成するコードは次のようになります。
;; X-axis-leading-spaces ... (make-string full-Y-label-width ? ) ...
また、水平軸の長さ(数値リストの長さ)と、水平軸上の目盛りの数を決定する必要があります:
;; X-length ... (length numbers-list)
;; tic-width ... (* symbol-width X-axis-label-spacing)
;; number-of-X-ticks
(if (zerop (% (X-length tic-width)))
(/ (X-length tic-width))
(1+ (/ (X-length tic-width))))
以上により、X軸の目盛り線を描画する関数に直接たどり着きます。
(defun print-X-axis-tic-line
(number-of-X-tics X-axis-leading-spaces X-axis-tic-element)
"Print ticks for X axis."
(insert X-axis-leading-spaces)
(insert X-axis-tic-symbol) ; Under first column.
;; Insert second tic in the right spot. (insert (concat (make-string (- (* symbol-width X-axis-label-spacing) ;; Insert white space up to second tic symbol. (* 2 (length X-axis-tic-symbol))) ? ) X-axis-tic-symbol))
;; Insert remaining ticks.
(while (> number-of-X-tics 1)
(insert X-axis-tic-element)
(setq number-of-X-tics (1- number-of-X-tics))))
数値の列も同様に分かりやすい:
まず、各数字の前に空白を設けた番号付き要素を作成します:
(defun X-axis-element (number)
"Construct a numbered X axis element."
(let ((leading-spaces
(- (* symbol-width X-axis-label-spacing)
(length (number-to-string number)))))
(concat (make-string leading-spaces ? )
(number-to-string number))))
次に、第1列の数値1から始まる、番号付きの行を出力する関数を作成します:
(defun print-X-axis-numbered-line
(number-of-X-tics X-axis-leading-spaces)
"Print line of X-axis numbers"
(let ((number X-axis-label-spacing))
(insert X-axis-leading-spaces)
(insert "1")
(insert (concat
(make-string
;; Insert white space up to next number.
(- (* symbol-width X-axis-label-spacing) 2)
? )
(number-to-string number)))
;; Insert remaining numbers.
(setq number (+ number X-axis-label-spacing))
(while (> number-of-X-tics 1)
(insert (X-axis-element number))
(setq number (+ number X-axis-label-spacing))
(setq number-of-X-tics (1- number-of-X-tics)))))
最後に、print-X-axis-tic-lineとprint-X-axis-numbered-lineを使用するprint-X-axisを記述する必要があります。
この関数は、print-X-axis-tic-lineとprint-X-axis-numbered-lineの両方で使用される変数のローカル値を特定し、それらを呼び出す必要があります。また、2行を区切るキャリッジリターンを出力する必要があります。
この関数は、5つのローカル変数を指定するvarlistと、2つの行出力関数それぞれの呼び出しで構成されています:
(defun print-X-axis (numbers-list)
"Print X axis labels to length of NUMBERS-LIST."
(let* ((leading-spaces
(make-string full-Y-label-width ? ))
;; symbol-width is provided by graph-body-print
(tic-width (* symbol-width X-axis-label-spacing))
(X-length (length numbers-list))
(X-tic
(concat
(make-string
;; Make a string of blanks.
(- (* symbol-width X-axis-label-spacing)
(length X-axis-tic-symbol))
? )
;; Concatenate blanks with tic symbol.
X-axis-tic-symbol))
(tic-number
(if (zerop (% X-length tic-width))
(/ X-length tic-width)
(1+ (/ X-length tic-width)))))
(print-X-axis-tic-line tic-number leading-spaces X-tic)
(insert "\n")
(print-X-axis-numbered-line tic-number leading-spaces)))
print-X-axisをテストできます:
X-axis-tic-symbol、X-axis-label-spacing、print-X-axis-tic-line、およびX-axis-element、print-X-axis-numbered-line、print-X-axisをインストールしてください。
(progn
(let ((full-Y-label-width 5)
(symbol-width 1))
(print-X-axis
'(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16))))
eval-expression)。
yank)
でテスト式をミニバッファにヤンクします。
Emacsは横軸を次のように表示します:
| | | | |
1 5 10 15 20