From: Madhu
Subject: Question for FORMAT Gurus: Layout Justification
Date: 
Message-ID: <m3ir48lova.fsf@robolove.meer.net>
[There was a related thread this September from which the example is
taken.  The FORMAT facility used here is in specified in 22.3.6.2 of the
spec]

(defvar $words
  '("Four" "score" "and" "seven" "years" "ago" "our" "fathers" "brought"
    "forth" "on" "this" "continent" "a" "new" "nation" "conceived" "in"
    "liberty" "and" "dedicated" "to" "the" "proposition" "that" "most"
    "people" "like" "sports" "bars."))

The elusive desired output is:

A="Four score and seven years ago our fathers brought forth on"
A="this continent a new nation conceived in liberty and dedicated"
A="to the proposition that most people like sports bars."

Is it possible to get this output using FORMAT's justification
directives?

Here are two of my failed attempts. The first fails because I cannot
control the trailing space on each output. The second fails because I
cannot supress the pad char at the beginning of each line.

* (format t "~%A=\"~{~:<\"~%A=\"~,65:;~A~>~^ ~}\"~%" $words)

A="Four score and seven years ago our fathers brought forth on "
A="this continent a new nation conceived in liberty and dedicated "
A="to the proposition that most people like sports bars."

* (format t "~%A=\"~{~,,1,:<\"~%A=\"~0,65:;~A~>~}\"~%" $words)

A=" Four score and seven years ago our fathers brought forth on"
A=" this continent a new nation conceived in liberty and dedicated"
A=" to the proposition that most people like sports bars."

Am I missing something which would let me get the desired output? Or is
FORMAT not upto this particular task?
--
Madhu

PS: Apparently CMUCL has a bug which formats my second form incorrectly,
splitting the output into 4 lines instead of 3.

From: Steven M. Haflich
Subject: Re: Question for FORMAT Gurus: Layout Justification
Date: 
Message-ID: <%GMZi.5118$852.1466@newssvr17.news.prodigy.net>
I don't think the layout directives are quite powerful enough to solve 
this.  Below is an ugly solution using the pprint-logical-block that
works, but isn't a serious approach.  Your desired layout is simple
enough to achieve by writing code that emits words, spaces, and line
breaks individually that using format in weird ways seems silly and
unreadable.

By the way, this code fails if any of the words contains ~ in its
print name.  Exercise for the student to protect against this...

* (with-input-from-string
       (s (with-output-to-string (s)
	   (let ((*print-pretty* t)
		 (*print-right-margin* 63))
	     (format s (format nil "~~<~{~a~^ ·····@>" $words) nil))))
     (loop as line = (read-line s nil nil)
	while line
	do (format t "A=\"~A\"~%" line)))
A="Four score and seven years ago our fathers brought forth on"
A="this continent a new nation conceived in liberty and dedicated"
A="to the proposition that most people like sports bars."
nil
From: Madhu
Subject: Re: Question for FORMAT Gurus: Layout Justification
Date: 
Message-ID: <m3d4ugkwgz.fsf@robolove.meer.net>
Helu
* "Steven M. Haflich" <···················@newssvr17.news.prodigy.net> :

| I don't think the layout directives are quite powerful enough to solve
| this.  Below is an ugly solution using the pprint-logical-block that
| works, but isn't a serious approach.

Thanks for this idea.

| Your desired layout is simple enough to achieve by writing code that
| emits words, spaces, and line breaks individually that using format in
| weird ways seems silly and unreadable.

Normally I would tend to agree.  Actually I have a function (appended
below) which does what I want, (I think).  But the CL spec for FORMAT
(22.3.6.2) is very close and specifies 99% of what this function does:
the only missing bit is the special treatement of the `suffix'
parameter---which could possibly be handled by a `last clause' inside a
~:< ~> block.

[The toss is between debugging your own function which implements what
 FORMAT does, and getting all the corner cases right, or coming up with
 a one liner of write-only-line-noise, which is guaranteed by the spec
 to work.  Though in this case, I suspected FORMAT does not give
 occassion for the cigar.]

(defun my-format-block (stream total-width prefix suffix separator words)
  (let ((separator-length (length separator)) word
        (effective-width (- total-width (+ (length prefix) (length suffix)
                                           -1)))
        (current-width 0))
    (assert (> effective-width 0))
    (when words
      (write-string prefix stream)
      (setq word (car words) words (cdr words))
      (loop
         (assert word)
         (cond ((endp words)
                (write-string word stream)
                (write-string suffix stream)
                (terpri stream)
                (return))
               ((<= (+ current-width (length word)) effective-width)
                (write-string word stream)
                (incf current-width (length word))
                (cond ((<= (+ current-width separator-length
                             (length (car words)))
                          effective-width)
                       (write-string separator stream)
                       (incf current-width separator-length))
                      (t (write-string suffix stream)
                         (terpri stream)
                         (write-string prefix stream)
                         (setq current-width 0)))
                (setq word (car words) words (cdr words)))
               (t (write-string suffix stream)
                  (terpri stream)
                  (write-string prefix stream)
                  (setq current-width 0)))))))

* (my-format-block *standard-output* 65 "A=\"" "\"" " " $words)

A="Four score and seven years ago our fathers brought forth on"
A="this continent a new nation conceived in liberty and dedicated"
A="to the proposition that most people like sports bars."

--
Madhu