Skip to content

Commit 8b60c3f

Browse files
authored
fix: allow empty newlines between in multiline messages (#125)
* fix: allow empty newlines between in multiline messages Only works in websocket clients. TCP clients doesnt seems to work, at least with emacs client. Closes #109 * tests: add unit test for split with :empty-seqs t * tests: check if formatted message is split with empty newlines
1 parent 55002dd commit 8b60c3f

2 files changed

Lines changed: 47 additions & 18 deletions

File tree

src/server/base.lisp

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,29 @@
135135
(push (copy-seq token) tokens))
136136
(nreverse tokens)))
137137

138-
(defun split (string &key (delimiterp #'spacep) quotation-aware)
138+
(defun split-with-empty-seqs (string delimiterp)
139+
"Slit a string maintaing empty strings when there is multiple consecutive delimiters"
140+
(loop for start = 0 then (1+ pos)
141+
for pos = (position-if delimiterp string :start start)
142+
collect (subseq string start pos)
143+
while pos))
144+
145+
(defun split-trivial (string delimiterp)
146+
(loop for beg = (position-if-not delimiterp string)
147+
then (position-if-not delimiterp string :start (1+ end))
148+
for end = (and beg (position-if delimiterp string :start beg))
149+
when beg
150+
collect (subseq string beg end)
151+
while end))
152+
153+
(defun split (string &key (delimiterp #'spacep) quotation-aware empty-seqs)
139154
"Split a string by a delimiterp function character checking"
140-
(if (not quotation-aware)
141-
(loop for beg = (position-if-not delimiterp string)
142-
then (position-if-not delimiterp string :start (1+ end))
143-
for end = (and beg (position-if delimiterp string :start beg))
144-
when beg
145-
collect (subseq string beg end)
146-
while end)
147-
(split-quotation-aware string delimiterp)))
155+
(cond
156+
((and quotation-aware empty-seqs)
157+
(error "QUOTATION-AWARE and WITH-EMTPY-SEQS cannot be used together"))
158+
(quotation-aware (split-quotation-aware string delimiterp))
159+
(empty-seqs (split-with-empty-seqs string delimiterp))
160+
(t (split-trivial string delimiterp))))
148161

149162
(defun startswith (string substring)
150163
"Check if STRING starts with SUBSTRING."
@@ -166,7 +179,7 @@
166179
(message-time-hour-format message)))
167180
(from-str (message-from message))
168181
(content-str (message-content message))
169-
(lines (split content-str :delimiterp (lambda (c) (char= c #\Newline)))))
182+
(lines (split content-str :empty-seqs t :delimiterp (lambda (c) (char= c #\Newline)))))
170183
(format nil "~{~a~^~%~}"
171184
(mapcar (lambda (line)
172185
(format-message-line time-str from-str line))

tests/unit.lisp

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
:parent unit-tests
88
(let ((time '(0 30 12 11 2 2026 2 nil 0))) ;; 2026-02-11 12:30:00 Wednesday GMT+0
99
(is string= "12:30:00 of Wednesday, 2026-02-11 (GMT+0)"
10-
(lisp-chat/server:format-time time))
11-
(let ((msg (lisp-chat/server:make-message :from "test" :content "hi" :time time)))
12-
(is string= "12:30:00" (lisp-chat/server:message-time-hour-format msg))
13-
(is string= "2026-02-11 12:30:00" (lisp-chat/server:message-time-date-format msg)))))
10+
(server:format-time time))
11+
(let ((msg (server:make-message :from "test" :content "hi" :time time)))
12+
(is string= "12:30:00" (server:message-time-hour-format msg))
13+
(is string= "2026-02-11 12:30:00" (server:message-time-date-format msg)))))
1414

1515
(define-test system-version-parsing
1616
:parent unit-tests
@@ -24,8 +24,24 @@
2424

2525
(define-test commands-string-utils
2626
:parent unit-tests
27-
(is equal '("x" "y" "z") (server:split "x.y.z"
28-
:delimiterp (lambda (c) (eql c #\.))))
29-
(is equal '("foo" "bar zoo") (server:split "foo 'bar zoo'"
30-
:quotation-aware t))
27+
(is equal
28+
'("x" "y" "z")
29+
(server:split "x.y.z"
30+
:delimiterp (lambda (c) (eql c #\.))))
31+
(is equal
32+
'("foo" "bar zoo")
33+
(server:split "foo 'bar zoo'" :quotation-aware t))
34+
(is equal
35+
'("foo" "" "bar")
36+
(server:split "foo bar" :empty-seqs t))
3137
(true (server:startswith "/command" "/")))
38+
39+
(define-test message-formatting
40+
:parent unit-tests
41+
(let* ((message (server:make-message :from "@server"
42+
:content (format nil "line1~%~%xline2")
43+
:time (server:get-time)))
44+
(message-string (server:formatted-message message)))
45+
(is equal
46+
3
47+
(count #\@ message-string :test #'char-equal))))

0 commit comments

Comments
 (0)