(defun list-of-lines (&optional (no 30) &rest for-fill-line) "
The emacs paper says a list of line-strings is appropriate
"
(loop repeat no collect (apply #'fill-line for-fill-line)))
(defun random-graphic-char () "
does what it sounds like.
"
(let ((chars `(,@(loop for n below 128 for ch = (code-char n)
for gp = (graphic-char-p ch)
when gp collect ch))))
(nth (random (length chars)) chars)))
(defun boundarise-linep (line x-offset
&key (default-char #\space)
(fun-boundary-char #'random-graphic-char)) "
generalised boolean: Is there a collision coming left to x-offset?
Returns the line with a modified 'line' character
or else nil.
fun-boundary-char should be a function with no formals that returns
a single character.
"
(loop for x below (1+ x-offset)
unless (char= (char line x) default-char) do
(return-from boundarise-linep nil))
(setf (char line x-offset) (funcall fun-boundary-char))
(values line))
(defun boundarise (list x-off y-offset phase
&rest
boundarise-linep-args
&aux
(new-list
(mapcar (lambda (x) (format nil "~a" x))
(nthcdr y-offset list)))) "
list is a list of lines as from list-of-lines
x-off and y-offset top left beginning of trace
phase like #c(5 1) (5 across for 1 down)
boundarise-linep-args suitable for boundarise-linep
"
(loop for line in new-list for n from 0
for x-offset = x-off then (if (zerop (mod n (imagpart phase)))
(+ x-offset (realpart phase))
x-offset)
for new-line = (apply #'boundarise-linep
(format nil "~a" line)
(min x-offset (1- (length line)))
boundarise-linep-args)
while (< (1+ x-offset) (length line))
unless new-line do (return-from boundarise nil)
collect new-line
into final-lines
finally (return final-lines)))
(defun add-boundaryp (line-list phase x-off y-off &rest linep-args) "
traces a line on a new copy of line-list:
phase is like #c(5 1) to mean 5 spaces across for every 1 line down
x-off and y-off top left extremum of line
linep-args suitable for boundarise
"
(loop for n from y-off to (1- (length line-list))
for new-lines = (apply #'boundarise line-list x-off n phase linep-args)
for mid-lines = (append (subseq line-list 0 n)
new-lines)
for all-lines = (append mid-lines
(last line-list
(- (length line-list)
(length mid-lines))))
when new-lines return all-lines))
(defun stuff-strings (things line-list &key (default-char #\space)
&aux (strings (mapcar (lambda (x)
(format nil "~a" x))
things))) "
Listen, it's not my greatest work. I've been sick, and it was after midnight
(and yet also before midnight, thank-you rat, ams and kmp)
ARGS: things - a list suitable for mapcar. elements will be aesthetically
printed.
line-list - as from sloppy-text/impl::list-of-lines
:default-char - optional, what is considered an unoccupied char.
Attempts to write words that were things into each subsequent line in lines
if there's space: Writes them touching whatever they're next to.
Returns a (list remaining-words modified-lines-list)
suitable for
(apply #'stuff-strings #c(5 1) *)
"
(loop for line in line-list for n from 0
for string = (pop strings)
then (cond ((null string) (pop strings))
(t string))
for blocked-idx = (search (format nil "~a" default-char)
line
:test-not 'char=)
while string
nconc (and blocked-idx
(if (< (length string) (1+ blocked-idx))
(let* ((new-string
(concatenate 'string
string
(subseq
line
blocked-idx)))
(len-new (length new-string))
(dif (- (length line) (length new-string))))
(prog1
`(,(concatenate 'string
(subseq line 0 dif)
new-string))
(setf string nil)))
(list line)))
into results
finally (return (list (if string (push string strings)
strings)
results))))
(defun keeppenning (phase words lines) "
Args:
phase - an integral complex number. #c(5 1)
means for every 1 line down, go five
more spaces indented.
words - A list suitable for mapcar. What is
used will be the aesthetic print of
w/e you put in the list.
lines - A list of string \" lines \"
which could have content already.
default-char seen elsewhere is left as its default,
space for now.
RETURNS:
new-lines : freshly consed modified versions
of lines, to contain words to the
extent they fit.
See the example at the bottom of impl.lisp
"
(loop
for old-words = (copy-list words)
for new-lines = (add-boundaryp lines phase 0 0)
for offset = (or (loop for n from 0
for l in lines for k in new-lines
when (not (string= l k)) return n)
0)
for results = (stuff-strings words (subseq new-lines offset))
for nex-lines = (cadr results)
for new-len = (length new-lines)
for nex-len = (length nex-lines)
for lin-len = (length lines)
for joined-lines =
(append (copy-list (subseq lines 0 offset))
(copy-list nex-lines)
(copy-list (subseq lines
(+ offset
nex-len))))
when joined-lines do
(setf lines joined-lines
words (car results))
while (not (equal words old-words))
finally (return joined-lines)))
(defvar *phlog*
'(Well i cannot say it went perfectly but after seeing jns
create art with the words of the epic freebsd driver phlog
i decided i would give some notion of phlogging on an angle
a go |.| as well as |art,| hopefully we can resist being
included in LLM |data.| even though what i have done here
is loosely the same as transposing a block of text i think
its kind of loose hanging enough it would be hard for an
insufficiently loose robot to |catch.|))