(defparameter line-len 87)
(setf (documentation 'line-len 'variable)
"Characters allowed in one text line")
;; Using subseq; not fancy
(defun %limit-len (filepath)
(with-output-to-string
(out)
(with-open-file
(in filepath)
(loop
for line = (read-line in nil nil)
while line do
(if (< (length line) line-len)
(format out "~a~%" line)
(let ((seq-start 0))
(loop
while (< seq-start (length line))
do
(format out "~a~%" (subseq line
seq-start
(min (length line)
(incf seq-start line-len)))))))))))
;; Using split-sequence
;;; However can't handle lines starting with a word longer than one line
;;; Or words longer than two lines generally.
(require #:split-sequence)
(use-package 'split-sequence)
(defun %%limit-len (line)
(let ((words (split-sequence #\Space line))
(string "")
(counter (let ((count 0))
(lambda (&key incf reset check)
(cond (incf (incf count incf))
(reset (setf count 0))
(check (values count))
(t (error ":-(")))))))
(loop
for word in words
do (cond ((and (not (string= string ""))
(char= #\newline (char string (1- (length string)))))
(setf string (format nil "~a~a" string word))
(funcall counter :incf (length word)))
((and (/= 1 (length word))
(= 1 (- line-len (funcall counter :check t))))
(setf string (format nil "~a~%~a" string word))
(funcall counter :incf (length word)))
((> line-len (+ (funcall counter :check t)
(1+ (length word))))
(setf string (format nil "~a ~a" string word))
(funcall counter :incf (1+ (length word))))
((or (= line-len (+ (funcall counter :check t)
(1+ (length word))))
(= line-len (+ (funcall counter :check t)
(length word))))
(setf string (format nil "~a ~a~%" string word))
(funcall counter :reset t))
((/= 1 (length word))
(let ((first-half (subseq word 0 (1- (- line-len (funcall counter :check t)))))
(second-half (subseq word (1- (- line-len (funcall counter :check t))))))
(setf string (format nil "~a ~a-~%~a" string first-half second-half))
(funcall counter :reset t)
(funcall counter :incf (length second-half))))
(t (error "fell through"))))
(values (subseq string 1))))