(defun linebreak (string line-length) (loop with words = (split-sequence-if #'φ:whitespacep string :remove-empty-subseqs t) for (word next-word) on words with stack = '() with length = 0 if (or (null stack) (<= (+ length (length word)) line-length)) do (push word stack) (incf length (1+ (length word))) else collect (format nil "~{~A~^ ~}" (nreverse stack)) and do (setf stack (list word) length (length word)) when (null next-word) collect (format nil "~{~A~^ ~}" (nreverse stack)))) (defun test-linebreak (&optional data) (flet ((test (length input expected) (let ((actual (linebreak input length))) (unless (equal actual expected) (format t "# Failed: ~S ~S ~S~%# Expected: ~S~%# Actual: ~S~%~%" length input expected expected actual))))) (cond (data (apply #'test data)) (t (mapc (alexandria:curry #'apply #'test) *test-data*))) nil)) (defparameter *test-data* '((5 "" ()) (5 " " ()) (5 " " ()) (5 " " ()) (5 "a" ("a")) (5 "a a" ("a a")) (5 "a a a" ("a a a")) (5 "a a a aaa a a" ("a a a" "aaa a" "a")) (5 "a a a a" ("a a a" "a")) (5 "aaaaa" ("aaaaa")) (5 "aaaaa a" ("aaaaa" "a")) (5 "aaaaa a " ("aaaaa" "a")) (5 " aaaaa a " ("aaaaa" "a")) (5 "aaaaaa" ("aaaaaa")) (5 "aaaaaa a" ("aaaaaa" "a")) (60 "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Hendrerit auctor libero, mattis erat. Vivamus, tempor, donec auctor. Adipiscing eleifend, egestas quisque. Dolor arcu tortor. Aliquam interdum phasellus, mattis lectus bibendum ullamcorper leo. Gravida, dis condimentum, pretium dolor non hendrerit nullam donec. Adipiscing malesuada ante porttitor nisl porta, ante etiam etiam. Aenean nisl, lobortis. Porttitor ante aliquam dictumst magna." ("Lorem ipsum dolor sit amet, consectetur adipiscing elit." "Hendrerit auctor libero, mattis erat. Vivamus, tempor, donec" "auctor. Adipiscing eleifend, egestas quisque. Dolor arcu" "tortor. Aliquam interdum phasellus, mattis lectus bibendum" "ullamcorper leo. Gravida, dis condimentum, pretium dolor non" "hendrerit nullam donec. Adipiscing malesuada ante porttitor" "nisl porta, ante etiam etiam. Aenean nisl, lobortis." "Porttitor ante aliquam dictumst magna."))))