created: 2016-10-09 00:00:00,tags:common-lisp,

cat -n (--number) と同様のインデントを common lisp で実装する

CommonLisp の練習に cat コマンドの機能をちびちび実装している時に覚えた話。

cat コマンドの --number オプションは地味にインデントが面倒なタイプだったので、勉強になった。

     1  #! /usr/bin/sbcl --script
     2  
     3  (defparameter *option-hash* (make-hash-table)) ;; これはこの話の中では使わない
     4  (defparameter *default-space-number* 5)
     5  
     6  (defun number-of-digits (n)
     7    (truncate (log n 10)))
     8  
     9  (defun number-of-spaces (n)
    10    (- *default-space-number* (number-of-digits n)))
    11  
    12  (defun control-char-for-indentation (n)
    13    (format nil "~~~dT" (number-of-spaces n)))
    14  
    15  (defun set-line-number (n)
    16    (if (gethash '-n *option-hash*)
    17        (format nil "~@?~a~a" (control-char-for-indentation n) n #\TAB)
    18        ""))

インデントと行数を付ける部分のコードを自分で作った cat で吐いたコードの一部が上のコードで、 行の桁数が変わる際に、右に桁が増えるタイプでは無く、左の空白の数が減る実装だった部分がちょっと面倒だった。

単純に考えれば空白文字を生成する関数を作れば良いんだけど、format 関数で既に実装されているのに他の方法で出力するのが気に喰わなかったので、良い方法が無いかと捜した。

format の ~? (Recursive Processing) というのを見つけ、これを使えば出来そうだったので試したら出来たというのがさっき。

他に上手くやる方法があったりするのかなぁ。