summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Uko Kokņevičs2025-10-18 08:42:44 +0300
committerGravatar Uko Kokņevičs2025-10-18 08:42:44 +0300
commit9e7c8dfab25da9beb86fd4ed4115895eedb4c8ab (patch)
treed05cf25dc5aeed47f8b2585ecc5a81ab80cbdbaf
parentBunch more tiny improvements (diff)
downloadukkoclot-9e7c8dfab25da9beb86fd4ed4115895eedb4c8ab.tar.gz
ukkoclot-9e7c8dfab25da9beb86fd4ed4115895eedb4c8ab.tar.xz
ukkoclot-9e7c8dfab25da9beb86fd4ed4115895eedb4c8ab.zip
Replace bunch of our string utilities with str library
-rw-r--r--ocicl.csv3
-rw-r--r--src/hash-tables.lisp2
-rw-r--r--src/main.lisp14
-rw-r--r--src/serializing.lisp6
-rw-r--r--src/strings.lisp55
-rw-r--r--src/tg/method-macros.lisp6
-rw-r--r--src/tg/type-macros.lisp4
7 files changed, 28 insertions, 62 deletions
diff --git a/ocicl.csv b/ocicl.csv
index 3918f74..ecc65f6 100644
--- a/ocicl.csv
+++ b/ocicl.csv
@@ -14,6 +14,7 @@ chipz, ghcr.io/ocicl/chipz@sha256:fae0fae0c93199ba57c92d9102245a55c8a2c12af4442e
14chunga, ghcr.io/ocicl/chunga@sha256:a2558d54ac5d4ccdbf49d7b51fcb074762d77e263ec67245f6d2928477b6d19a, chunga-20250814-1310e96/chunga.asd 14chunga, ghcr.io/ocicl/chunga@sha256:a2558d54ac5d4ccdbf49d7b51fcb074762d77e263ec67245f6d2928477b6d19a, chunga-20250814-1310e96/chunga.asd
15cl-base64, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64.asd 15cl-base64, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64.asd
16cl-base64-tests, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64-tests.asd 16cl-base64-tests, ghcr.io/ocicl/cl-base64@sha256:702412dbc1ed825e275fb23e22c29527eb786bf644e47c7621bf0dbb34e17c7e, cl-base64-20240503-80496b7/cl-base64-tests.asd
17cl-change-case, ghcr.io/ocicl/cl-change-case@sha256:07b51346796724d063c8d2515dd7c63f5e8a3a9c0017bc429b0d1313e257fd78, cl-change-case-1.0/cl-change-case.asd
17cl-cookie, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie.asd 18cl-cookie, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie.asd
18cl-cookie-test, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie-test.asd 19cl-cookie-test, ghcr.io/ocicl/cl-cookie@sha256:85cd8aa7f1379d041fae9530609cd68d5214fb978bc87faa7fd9ad5ad7e08a83, cl-cookie-20240703-6bcb74a/cl-cookie-test.asd
19cl-postgres_plus_local-time, ghcr.io/ocicl/local-time@sha256:15dc0e56d0ff55bd2a3c597e67be1c26bd0677c230a15ad5098c5207a9df5554, local-time-20250808-c28f38e/cl-postgres+local-time.asd 20cl-postgres_plus_local-time, ghcr.io/ocicl/local-time@sha256:15dc0e56d0ff55bd2a3c597e67be1c26bd0677c230a15ad5098c5207a9df5554, local-time-20250808-c28f38e/cl-postgres+local-time.asd
@@ -72,6 +73,8 @@ split-sequence, ghcr.io/ocicl/split-sequence@sha256:3a37662eedd99c42995587b9d443
72sqlite, ghcr.io/ocicl/sqlite@sha256:a7f80757e6ee13af06e2eeaeff1e079dba439d85ea5c7f68e262bccc40dcbd5c, cl-sqlite-0.2.1/sqlite.asd 73sqlite, ghcr.io/ocicl/sqlite@sha256:a7f80757e6ee13af06e2eeaeff1e079dba439d85ea5c7f68e262bccc40dcbd5c, cl-sqlite-0.2.1/sqlite.asd
73sqlite-tests, ghcr.io/ocicl/sqlite@sha256:a7f80757e6ee13af06e2eeaeff1e079dba439d85ea5c7f68e262bccc40dcbd5c, cl-sqlite-0.2.1/sqlite-tests.asd 74sqlite-tests, ghcr.io/ocicl/sqlite@sha256:a7f80757e6ee13af06e2eeaeff1e079dba439d85ea5c7f68e262bccc40dcbd5c, cl-sqlite-0.2.1/sqlite-tests.asd
74static-vectors, ghcr.io/ocicl/static-vectors@sha256:53e11e5689c3dbea6a3017760b55f052588003d774913539930ddc4330a69970, static-vectors-20240624-3d9d89b/static-vectors.asd 75static-vectors, ghcr.io/ocicl/static-vectors@sha256:53e11e5689c3dbea6a3017760b55f052588003d774913539930ddc4330a69970, static-vectors-20240624-3d9d89b/static-vectors.asd
76str, ghcr.io/ocicl/str@sha256:685078f7554071268bca9e933392904940d6751077718a4aafaf3d0424003f26, cl-str-20250905-69ef8b4/str.asd
77str.test, ghcr.io/ocicl/str@sha256:685078f7554071268bca9e933392904940d6751077718a4aafaf3d0424003f26, cl-str-20250905-69ef8b4/str.test.asd
75string-case, ghcr.io/ocicl/string-case@sha256:9db2d4160b76ce1ed9f754d12f679c665593a9a436177d36380a1a8a176ec16a, string-case-20240503-718c761/string-case.asd 78string-case, ghcr.io/ocicl/string-case@sha256:9db2d4160b76ce1ed9f754d12f679c665593a9a436177d36380a1a8a176ec16a, string-case-20240503-718c761/string-case.asd
76swap-bytes, ghcr.io/ocicl/swap-bytes@sha256:06edc17deb0f27cdf6290689711ece670a8282dfd07b732a9adc541af1ce7ed6, swap-bytes-20240503-43ab141/swap-bytes.asd 79swap-bytes, ghcr.io/ocicl/swap-bytes@sha256:06edc17deb0f27cdf6290689711ece670a8282dfd07b732a9adc541af1ce7ed6, swap-bytes-20240503-43ab141/swap-bytes.asd
77trivia, ghcr.io/ocicl/trivia@sha256:51db74757bc31ceaf3a643914a8ffa87825799097dea4912650e6ac62bed5209, trivia-20240904-4383dd8/trivia.asd 80trivia, ghcr.io/ocicl/trivia@sha256:51db74757bc31ceaf3a643914a8ffa87825799097dea4912650e6ac62bed5209, trivia-20240904-4383dd8/trivia.asd
diff --git a/src/hash-tables.lisp b/src/hash-tables.lisp
index d3b66dd..84ffbfe 100644
--- a/src/hash-tables.lisp
+++ b/src/hash-tables.lisp
@@ -1,7 +1,7 @@
1;; SPDX-License-Identifier: EUPL-1.2 1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com> 2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/hash-tables 3(defpackage :ukkoclot/hash-tables
4 (:documentation "Utilities for dealing with hash tables.") 4 (:documentation "Hash-table-oriented utilities.")
5 (:use :c2cl) 5 (:use :c2cl)
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:export :alist->hash-table :gethash-lazy :plist->hash-table)) 7 (:export :alist->hash-table :gethash-lazy :plist->hash-table))
diff --git a/src/main.lisp b/src/main.lisp
index 28c3801..5d3cf76 100644
--- a/src/main.lisp
+++ b/src/main.lisp
@@ -7,11 +7,11 @@
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :log) 8 (:import-from :log)
9 (:import-from :serapeum :drop) 9 (:import-from :serapeum :drop)
10 (:import-from :str)
10 (:import-from :ukkoclot/db :with-db) 11 (:import-from :ukkoclot/db :with-db)
11 (:import-from :ukkoclot/serializing :fixup-value) 12 (:import-from :ukkoclot/serializing :fixup-value)
12 (:import-from :ukkoclot/state :make-bot :bot-config :bot-power-on) 13 (:import-from :ukkoclot/state :make-bot :bot-config :bot-power-on)
13 (:import-from :ukkoclot/strings 14 (:import-from :ukkoclot/strings :escape-xml :is-tg-whitespace :is-tg-whitespace-str)
14 :escape-xml :is-tg-whitespace :is-tg-whitespace-str :starts-with :starts-with-ignore-case)
15 (:local-nicknames 15 (:local-nicknames
16 (:jzon :com.inuoe.jzon)) 16 (:jzon :com.inuoe.jzon))
17 (:export :main)) 17 (:export :main))
@@ -70,7 +70,7 @@
70(defun on-callback-query (bot cb) 70(defun on-callback-query (bot cb)
71 (let ((data (callback-query-data cb))) 71 (let ((data (callback-query-data cb)))
72 (cond ((and data 72 (cond ((and data
73 (starts-with data "bbl:") 73 (str:starts-with-p "bbl:" data :ignore-case nil)
74 (= (user-id (callback-query-from cb)) 74 (= (user-id (callback-query-from cb))
75 (config-owner (bot-config bot)))) 75 (config-owner (bot-config bot))))
76 (let ((bot-id (read-from-string data t nil :start 4))) 76 (let ((bot-id (read-from-string data t nil :start 4)))
@@ -83,7 +83,7 @@
83 :callback-query-id (callback-query-id cb) 83 :callback-query-id (callback-query-id cb)
84 :text "OK")) 84 :text "OK"))
85 ((and data 85 ((and data
86 (starts-with data "bwl:") 86 (str:starts-with-p "bwl:" data :ignore-case nil)
87 (= (user-id (callback-query-from cb)) 87 (= (user-id (callback-query-from cb))
88 (config-owner (bot-config bot)))) 88 (config-owner (bot-config bot))))
89 (let ((bot-id (read-from-string data t nil :start 4))) 89 (let ((bot-id (read-from-string data t nil :start 4)))
@@ -161,7 +161,7 @@
161 ((equal text ">:3") 161 ((equal text ">:3")
162 (reply-message bot msg "<b>&gt;:3</b>" :parse-mode html)) 162 (reply-message bot msg "<b>&gt;:3</b>" :parse-mode html))
163 163
164 ((starts-with-ignore-case text "big ") 164 ((str:starts-with-p "big " text)
165 (let ((the-text (drop 4 text))) 165 (let ((the-text (drop 4 text)))
166 (unless (is-tg-whitespace-str the-text) 166 (unless (is-tg-whitespace-str the-text)
167 (reply-message bot msg 167 (reply-message bot msg
@@ -190,12 +190,12 @@
190 (or (message-reply-to-message msg) msg) 190 (or (message-reply-to-message msg) msg)
191 "dio cane")) 191 "dio cane"))
192 192
193 ((starts-with-ignore-case text "say ") 193 ((str:starts-with-p "say " text)
194 (let ((the-text (drop 4 text))) 194 (let ((the-text (drop 4 text)))
195 (unless (is-tg-whitespace-str the-text) 195 (unless (is-tg-whitespace-str the-text)
196 (reply-message bot msg the-text)))) 196 (reply-message bot msg the-text))))
197 197
198 ((starts-with-ignore-case text "tiny ") 198 ((str:starts-with-p "tiny " text)
199 (let ((the-text (drop 5 text))) 199 (let ((the-text (drop 5 text)))
200 (unless (is-tg-whitespace-str the-text) 200 (unless (is-tg-whitespace-str the-text)
201 (reply-message bot msg 201 (reply-message bot msg
diff --git a/src/serializing.lisp b/src/serializing.lisp
index 205190f..71b0fb2 100644
--- a/src/serializing.lisp
+++ b/src/serializing.lisp
@@ -3,7 +3,7 @@
3(defpackage :ukkoclot/serializing 3(defpackage :ukkoclot/serializing
4 (:use :c2cl :iterate) 4 (:use :c2cl :iterate)
5 (:import-from :log) 5 (:import-from :log)
6 (:import-from :ukkoclot/strings :lisp->snake-case) 6 (:import-from :str)
7 (:local-nicknames 7 (:local-nicknames
8 (:jzon :com.inuoe.jzon)) 8 (:jzon :com.inuoe.jzon))
9 (:export :fixup-args :fixup-value :parse-value :try-parse-value)) 9 (:export :fixup-args :fixup-value :parse-value :try-parse-value))
@@ -11,9 +11,7 @@
11 11
12(defun fixup-args (args) 12(defun fixup-args (args)
13 (iter (for (key . value) in args) 13 (iter (for (key . value) in args)
14 (collect 14 (collect (cons (str:snake-case key) (fixup-value value)))))
15 (cons (string-downcase (lisp->snake-case (symbol-name key)))
16 (fixup-value value)))))
17 15
18(defgeneric fixup-value (value) 16(defgeneric fixup-value (value)
19 (:documentation "Fixup outgoing *top-level* `value' before passing it to telegram.") 17 (:documentation "Fixup outgoing *top-level* `value' before passing it to telegram.")
diff --git a/src/strings.lisp b/src/strings.lisp
index b1b4f00..eae8ec0 100644
--- a/src/strings.lisp
+++ b/src/strings.lisp
@@ -1,33 +1,30 @@
1;; SPDX-License-Identifier: EUPL-1.2 1;; SPDX-License-Identifier: EUPL-1.2
2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com> 2;; SPDX-FileCopyrightText: 2025 Uko Kokņevičs <perkontevs@gmail.com>
3(defpackage :ukkoclot/strings 3(defpackage :ukkoclot/strings
4 (:documentation "String-oriented utilities.")
4 (:use :c2cl :iterate) 5 (:use :c2cl :iterate)
5 (:import-from :cl-unicode :general-category) 6 (:import-from :cl-unicode :general-category)
6 (:export 7 (:export
7 :ends-with
8 :escape-xml 8 :escape-xml
9 :is-tg-whitespace 9 :is-tg-whitespace
10 :is-tg-whitespace-str 10 :is-tg-whitespace-str))
11 :lisp->camel-case
12 :lisp->snake-case
13 :snake->lisp-case
14 :starts-with
15 :starts-with-ignore-case))
16(in-package :ukkoclot/strings) 11(in-package :ukkoclot/strings)
17 12
18;; These are very inefficient but I don't care until I profile 13;; These are very inefficient but I don't care until I profile
19 14
20(defun ends-with (str suffix)
21 (and (> (length str) (length suffix))
22 (string= str suffix :start1 (- (length str) (length suffix)))))
23
24(defun escape-xml (str &optional out) 15(defun escape-xml (str &optional out)
16 "Escape special XML characters in the STR.
17
18OUT is the output stream or `nil' for outputting to a string."
25 (if out 19 (if out
26 (escape-xml% str out) 20 (escape-xml% str out)
27 (with-output-to-string (out) 21 (with-output-to-string (out)
28 (escape-xml% str out)))) 22 (escape-xml% str out))))
29 23
30(defun escape-xml% (str out) 24(defun escape-xml% (str out)
25 "See `escape-xml'.
26
27OUT is always the stream."
31 (loop for ch across str do 28 (loop for ch across str do
32 (case ch 29 (case ch
33 (#\< (write-string "&lt;" out)) 30 (#\< (write-string "&lt;" out))
@@ -37,6 +34,7 @@
37 (otherwise (write-char ch out))))) 34 (otherwise (write-char ch out)))))
38 35
39(defun is-tg-whitespace (ch) 36(defun is-tg-whitespace (ch)
37 "Checks if CH on its own would be considered whitespace by telegram."
40 (let ((gc (general-category ch))) 38 (let ((gc (general-category ch)))
41 (or (string= gc "Zs") ; Separator, space 39 (or (string= gc "Zs") ; Separator, space
42 (string= gc "Zl") ; Separator, line 40 (string= gc "Zl") ; Separator, line
@@ -45,39 +43,6 @@
45 (= (char-code ch) #x2800)))) ; BRAILLE PATTERN BLANK 43 (= (char-code ch) #x2800)))) ; BRAILLE PATTERN BLANK
46 44
47(defun is-tg-whitespace-str (str) 45(defun is-tg-whitespace-str (str)
46 "Checks if message containing just STR would be considered whitespace by telegram."
48 (iter (for ch in-string str) 47 (iter (for ch in-string str)
49 (always (is-tg-whitespace ch)))) 48 (always (is-tg-whitespace ch))))
50
51(defun lisp->camel-case (str)
52 (with-output-to-string (out)
53 (let ((should-caps nil))
54 (iter (for ch in-string str)
55 (cond ((char= ch #\-)
56 (setf should-caps t))
57 (should-caps
58 (write-char (char-upcase ch) out)
59 (setf should-caps nil))
60 (t
61 (write-char (char-downcase ch) out)))))))
62
63(defun lisp->snake-case (str)
64 (with-output-to-string (out)
65 (loop for ch across str do
66 (case ch
67 (#\- (write-char #\_ out))
68 (otherwise (write-char ch out))))))
69
70(defun snake->lisp-case (str)
71 (with-output-to-string (out)
72 (loop for ch across str do
73 (case ch
74 (#\_ (write-char #\- out))
75 (otherwise (write-char ch out))))))
76
77(defun starts-with (str prefix)
78 (and (> (length str) (length prefix))
79 (string= str prefix :end1 (length prefix))))
80
81(defun starts-with-ignore-case (str prefix)
82 (and (> (length str) (length prefix))
83 (string-equal str prefix :end1 (length prefix))))
diff --git a/src/tg/method-macros.lisp b/src/tg/method-macros.lisp
index b924e15..0be6f00 100644
--- a/src/tg/method-macros.lisp
+++ b/src/tg/method-macros.lisp
@@ -6,8 +6,8 @@
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :serapeum :take) 8 (:import-from :serapeum :take)
9 (:import-from :str)
9 (:import-from :ukkoclot/state :bot) 10 (:import-from :ukkoclot/state :bot)
10 (:import-from :ukkoclot/strings :ends-with :lisp->camel-case)
11 (:import-from :ukkoclot/transport :do-call) 11 (:import-from :ukkoclot/transport :do-call)
12 (:export :define-tg-method)) 12 (:export :define-tg-method))
13(in-package :ukkoclot/tg/method-macros) 13(in-package :ukkoclot/tg/method-macros)
@@ -36,8 +36,8 @@
36 (collect (apply #'make-param param-spec)))) 36 (collect (apply #'make-param param-spec))))
37 37
38 (defun path-from-name (name) 38 (defun path-from-name (name)
39 (let ((str (lisp->camel-case (symbol-name name)))) 39 (let ((str (str:camel-case name)))
40 (if (ends-with str "%") 40 (if (str:ends-with-p "%" str :ignore-case nil)
41 (take (- (length str) 1) str) 41 (take (- (length str) 1) str)
42 str))) 42 str)))
43 43
diff --git a/src/tg/type-macros.lisp b/src/tg/type-macros.lisp
index 5f99cba..75afab0 100644
--- a/src/tg/type-macros.lisp
+++ b/src/tg/type-macros.lisp
@@ -5,9 +5,9 @@
5 (:use :c2cl :iterate) 5 (:use :c2cl :iterate)
6 (:import-from :alexandria :with-gensyms) 6 (:import-from :alexandria :with-gensyms)
7 (:import-from :com.dieggsy.f-string :enable-f-strings) 7 (:import-from :com.dieggsy.f-string :enable-f-strings)
8 (:import-from :str)
8 (:import-from :ukkoclot/serializing :parse-value) 9 (:import-from :ukkoclot/serializing :parse-value)
9 (:import-from :ukkoclot/hash-tables :gethash-lazy) 10 (:import-from :ukkoclot/hash-tables :gethash-lazy)
10 (:import-from :ukkoclot/strings :lisp->snake-case)
11 (:local-nicknames 11 (:local-nicknames
12 (:jzon :com.inuoe.jzon)) 12 (:jzon :com.inuoe.jzon))
13 (:export :define-tg-type)) 13 (:export :define-tg-type))
@@ -39,7 +39,7 @@
39 (intern (concatenate 'string (symbol-name name) "-" (symbol-name (field-name field))))) 39 (intern (concatenate 'string (symbol-name name) "-" (symbol-name (field-name field)))))
40 40
41 (defun field-hash-key (field) 41 (defun field-hash-key (field)
42 (string-downcase (lisp->snake-case (symbol-name (field-name field))))) 42 (str:snake-case (field-name field)))
43 43
44 (defun field-keyword (field) 44 (defun field-keyword (field)
45 (intern (symbol-name (field-name field)) :keyword)) 45 (intern (symbol-name (field-name field)) :keyword))