[Openmcl-devel] Building tables with format

Camille Troillard tuscland at mac.com
Wed Aug 18 06:36:00 PDT 2004

Hi Hamilton,

Your solution inspired me, and I found a way to do just what I was 
searching for (note that it is specific to OpenMCL), so here is the 
code :
The arg is printed to a string of COLS constant width.
Padding is done with PADCHARs, with a minimum of MINPAD.
'@' and ':' options can be used and have the same meaning than in ~A 
and ~S formatter options.


Example:	; Simple tuncation.
			CL-USER> (format nil "~10#" "azertyuiopqsdfghjklmwxcvbn")

			; Simple padding.
			CL-USER> (format nil "~10#" "azerty")
			"azerty    "

			; Padding occurs because we asked a minimum of 2 characters.
			; PADCHAR is '-' here, (note the notation "'-").
			; It can be specified by an ASCII code number too.
			; MINPAD has no use here.
			CL-USER> (format nil "~10,2,'-#" "azerty")

			; Same example as the latter, but MINPAD is useful here.
			CL-USER> (format nil "~10,2,45#" "azertyuiopqsdfghjklmwxcvbn")

The code:

(in-package :cl-user)

(defun format-fixed-field (s arg atsignp cols minpad padchar)
   (let* ((padding (max minpad (- cols (length arg))))
          (width (- cols padding)))
     (unless (characterp padchar)
       (if (typep padchar `(integer 0 #.char-code-limit))
           (setq padchar (code-char padchar))
         (format-error "Padchar must be a character or integer from 0 to 
~a - ~S"
                       char-code-limit padchar)))
     (when atsignp
       (loop for i below padding
             do (write-char padchar s)))
     (write-string (subseq arg 0 (min width (length arg))) s)
     (unless atsignp
       (loop for i below padding
             do (write-char padchar s)))))

(ccl::defformat #\# format-fixed (stream colon atsign &rest parms)
   (declare (dynamic-extent parms))
   (let ((arg (ccl::pop-format-arg)))
     (if (null parms)
         (princ (or arg (if colon "()" nil)) stream)
       (ccl::with-format-parameters parms ((cols 0) (minpad 0) (padchar 
                                     (if (or arg (not colon))
                                         (princ-to-string arg)
                                     atsign cols minpad padchar)))))

Best Regards,

On 18 août 04, at 05:56, Hamilton Link wrote:

> Wow, good question! I love format. Mind you I never write a format 
> control string without CLTL2 handy...
> After much searching, and deciding there was no straightforward way of 
> doing as you yourself discovered, I revisited the pretty printing 
> chapter of CLTL2. I think ~/.../ may do what you need. Look in section 
> 27.4 of CLTL2, and check this out:
> ? (defun chop (s arg &optional colonp atsignp &rest parameters)
>   (print s)
>   (print arg)
>   (print colonp)
>   (print atsignp)
>   (print parameters)
>   (let ((full-result (format nil "~a" arg)))
>     (format s "~a" (subseq full-result 0 (min 10 (length 
> full-result))))))
> ? (format nil "~1,2,3:@/CHOP/" "This string is far, far too long!")
> ;; this was all my debugging output
> "This string is far, far too long!"
> T
> T
> (1 2 3)
> ;; this was what was printed by the format command, using CHOP
> "This strin"
> ?
> And of course you could make chop take minlength, maxlength, and 
> padchar as parameters and DWYM.
> h
> On Aug 17, 2004, at 10:06 AM, Camille Troillard wrote:
>> Hello,
>> I fear my question is a little bit off topic.
>> I would like to output a table with fixed-width cells.  This means I 
>> need to truncate string arguments in order to keep the cell width 
>> constant.  FORMAT offers a way to add a padding, but there is not way 
>> to truncate a string argument (I would have used an option to the ~A 
>> or ~S directives).
>> Is there any way to extend OpenMCL's FORMAT mechanism in order to do 
>> just that?
>> Thanks for your help,
>> Camille
>> _______________________________________________
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
>> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list