From 38f708452bc1032ee1e42cf0e345ca8851316e4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=B6rnquist?= Date: Mon, 1 Jun 2020 16:02:54 +0200 Subject: Break text procedures into modules. --- module/text/flow.scm | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 module/text/flow.scm (limited to 'module/text/flow.scm') diff --git a/module/text/flow.scm b/module/text/flow.scm new file mode 100644 index 00000000..3d97bed6 --- /dev/null +++ b/module/text/flow.scm @@ -0,0 +1,51 @@ +(define-module (text flow) + :use-module (util) + :use-module (text util) + :use-module (srfi srfi-1) + ) + + + +;; (str) -> str +(define* (justify-line-helper words #:key (width 70)) + (let* ((phrase-length (true-string-length (string-concatenate/shared words))) + (needed-spaces (- width phrase-length)) + (slots (1- (length words))) + (space-list + (let loop ((n needed-spaces) (d slots)) + (unless (zero? d) + (let ((v (round (/ n d)))) + (cons v (loop (- n v) + (1- d)))))))) + (string-concatenate/shared + (merge words (map (lambda (n) (make-string n #\space)) + space-list) + (let ((f #t)) (lambda _ (mod/r! f not))))))) + + + +;; Splits and justifies the given line to @var{#:width}. +;; Returns a list of justified strings. +;; str -> (str) +(define* (justify-line line #:key (width 70)) + (let recur ((lst (words line))) + (let* ((head tail (span + (let ((w 0)) + (lambda (word) ; Take words until we are above the limit. + (< (mod/r! w = (+ 1 (true-string-length word))) + width))) + lst))) + (cond ((null? tail) (list (unwords head))) ; Don't justify last line. + ((null? head) + ;; an empty head implies that we found a word longer + ;; than our max width. Add it as is and continue + ;; (while crying). + (cons (car tail) (recur (cdr tail)))) + (else (cons (justify-line-helper head #:width width) + (recur tail))))))) + +;; str -> (str) +(define*-public (flow-text str #:key (width 70)) + (flatten + (map (lambda (line) (justify-line line #:width width)) + (lines str)))) -- cgit v1.2.3