From 0d2c880883e44998b8f4a27f795f2f4aa28195bd Mon Sep 17 00:00:00 2001 From: Eva Marco Date: Wed, 11 Mar 2026 12:47:15 +0100 Subject: [PATCH] :recycle: Use new fn for token parsing --- common/src/app/common/types/token.cljc | 39 +++++++++----- .../test/common_tests/types/token_test.cljc | 52 +++++++++++++------ .../forms/controls/token_parsing.cljs | 47 +---------------- 3 files changed, 62 insertions(+), 76 deletions(-) diff --git a/common/src/app/common/types/token.cljc b/common/src/app/common/types/token.cljc index 512be8c570..14da5a23b0 100644 --- a/common/src/app/common/types/token.cljc +++ b/common/src/app/common/types/token.cljc @@ -678,10 +678,21 @@ (+ offset index 1) (inc count)))))) +(defn block-open-start + [value position] + (let [left (str/slice value 0 position) + last-open (str/last-index-of left "{")] + (loop [i last-open] + (if (and i + (> i 0) + (= (nth left (dec i)) \{)) + (recur (dec i)) + i)))) + (defn start-ref-position [value position] (let [left-part (str/slice value 0 position) - open-pos (str/last-index-of left-part "{") + open-pos (block-open-start value position) space-pos (str/last-index-of left-part " ") space-pos (when space-pos (+ 1 space-pos)) first-position (->> [open-pos space-pos] @@ -711,13 +722,13 @@ close-pos (nth-index-of right-part "}" 1) spaces-pos-after (nth-index-of right-part " " 1) open-after-space? (or (nil? spaces-pos-before) - (> open-pos spaces-pos-before)) - close-before-space? (or (nil? spaces-pos-after) - (< close-pos spaces-pos-after))] - (and open-pos - close-pos - open-after-space? - close-before-space?))) + (> open-pos spaces-pos-before)) + close-before-space? (or (nil? spaces-pos-after) + (< close-pos spaces-pos-after))] + (and open-pos + close-pos + open-after-space? + close-before-space?))) (defn insert-ref [value position name] @@ -727,15 +738,15 @@ (let [first-part (str/slice value 0 (start-ref-position-inside-ref value position)) end-position (+ position (end-ref-position-inside-ref value position) 1) second-part (str/slice value end-position)] - {:result (str first-part reference second-part) - :position (+ (count first-part) (count reference))}) + {:value (str first-part reference second-part) + :cursor (+ (count first-part) (count reference))}) (let [first-part (str/slice value 0 (start-ref-position value position)) second-part (str/slice value position)] - {:result (str first-part reference second-part) - :position (+ (count first-part) (count reference))})) + {:value (str first-part reference second-part) + :cursor (+ (count first-part) (count reference))})) (let [first-part (str/slice value 0 position) second-part (str/slice value position)] - {:result (str first-part reference second-part) - :position (+ position (count reference))})))) + {:value (str first-part reference second-part) + :cursor (+ position (count reference))})))) diff --git a/common/test/common_tests/types/token_test.cljc b/common/test/common_tests/types/token_test.cljc index 48e8e58d65..bbd240078e 100644 --- a/common/test/common_tests/types/token_test.cljc +++ b/common/test/common_tests/types/token_test.cljc @@ -29,45 +29,47 @@ (t/deftest token-value-with-refs (t/testing "empty value" (t/is (= (cto/insert-ref "" 0 "token1") - {:result "{token1}" :position 8}))) + {:value "{token1}" :cursor 8}))) (t/testing "value without references" (t/is (= (cto/insert-ref "ABC" 0 "token1") - {:result "{token1}ABC" :position 8})) + {:value "{token1}ABC" :cursor 8})) (t/is (= (cto/insert-ref "23 + " 5 "token1") - {:result "23 + {token1}" :position 13})) + {:value "23 + {token1}" :cursor 13})) (t/is (= (cto/insert-ref "23 + " 5 "token1") - {:result "23 + {token1}" :position 13}))) + {:value "23 + {token1}" :cursor 13}))) (t/testing "value with closed references" (t/is (= (cto/insert-ref "{token2}" 8 "token1") - {:result "{token2}{token1}" :position 16})) + {:value "{token2}{token1}" :cursor 16})) (t/is (= (cto/insert-ref "{token2}" 6 "token1") - {:result "{token1}" :position 8})) + {:value "{token1}" :cursor 8})) (t/is (= (cto/insert-ref "{token2} + + {token3}" 10 "token1") - {:result "{token2} +{token1} + {token3}" :position 18})) + {:value "{token2} +{token1} + {token3}" :cursor 18})) (t/is (= (cto/insert-ref "{token2} + {token3}" 16 "token1") - {:result "{token2} + {token1}" :position 19}))) + {:value "{token2} + {token1}" :cursor 19}))) (t/testing "value with open references" (t/is (= (cto/insert-ref "{tok" 4 "token1") - {:result "{token1}" :position 8})) + {:value "{token1}" :cursor 8})) (t/is (= (cto/insert-ref "{tok" 2 "token1") - {:result "{token1}ok" :position 8})) + {:value "{token1}ok" :cursor 8})) (t/is (= (cto/insert-ref "{token2}{" 9 "token1") - {:result "{token2}{token1}" :position 16})) + {:value "{token2}{token1}" :cursor 16})) (t/is (= (cto/insert-ref "{token2{}" 8 "token1") - {:result "{token2{token1}" :position 15})) + {:value "{token2{token1}" :cursor 15})) (t/is (= (cto/insert-ref "{token2} + { + token3}" 12 "token1") - {:result "{token2} + {token1} + token3}" :position 19})) + {:value "{token2} + {token1} + token3}" :cursor 19})) (t/is (= (cto/insert-ref "{token2{}" 8 "token1") - {:result "{token2{token1}" :position 15}))) + {:value "{token2{token1}" :cursor 15})) + (t/is (= (cto/insert-ref "{token2} + {{{{{{{{{{ + {token3}" 21 "token1") + {:value "{token2} + {token1} + {token3}" :cursor 19}))) (t/testing "value with broken references" (t/is (= (cto/insert-ref "{tok {en2}" 6 "token1") - {:result "{tok {token1}" :position 13})) + {:value "{tok {token1}" :cursor 13})) (t/is (= (cto/insert-ref "{tok en2}" 5 "token1") - {:result "{tok {token1}en2}" :position 13})))) + {:value "{tok {token1}en2}" :cursor 13})))) ;; TODO: pasar a common data (t/deftest nth-last-index-of-test @@ -87,4 +89,20 @@ (t/is (= (cto/nth-index-of "abc*" "*" 2) nil)) (t/is (= (cto/nth-index-of "*abc[*" "*" 1) 0)) (t/is (= (cto/nth-index-of "abc*def*ghi" "*" 1) 3)) - (t/is (= (cto/nth-index-of "abc*def*ghi" "*" 2) 7))) \ No newline at end of file + (t/is (= (cto/nth-index-of "abc*def*ghi" "*" 2) 7))) + +(t/deftest inside-ref + (t/is (= (cto/inside-ref? "" 1) false)) + (t/is (= (cto/inside-ref? "AAA " 4) false)) + (t/is (= (cto/inside-ref? "abc{" 4) true)) + (t/is (= (cto/inside-ref? "abc}" 4) false)) + (t/is (= (cto/inside-ref? "{abc[}" 1) true)) + (t/is (= (cto/inside-ref? "abc {def}ghi" 5) true)) + (t/is (= (cto/inside-ref? "abc {def]ghi" 8) true))) + +(t/deftest inside-closed-ref + (t/is (= (cto/inside-closed-ref? "" 1) nil)) + (t/is (= (cto/inside-closed-ref? "{abc}" 1) true)) + (t/is (= (cto/inside-closed-ref? "abc {def}ghi" 5) true)) + (t/is (= (cto/inside-closed-ref? "abc {def}ghi" 8) true)) + (t/is (= (cto/inside-closed-ref? "abc {def}ghi" 10) nil))) \ No newline at end of file diff --git a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/token_parsing.cljs b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/token_parsing.cljs index d4c8057008..2308bef9c7 100644 --- a/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/token_parsing.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/management/forms/controls/token_parsing.cljs @@ -6,6 +6,7 @@ (ns app.main.ui.workspace.tokens.management.forms.controls.token-parsing (:require + [app.common.types.token :as cto] [app.main.ui.ds.controls.select :refer [get-option]] [app.util.dom :as dom] [cuerdas.core :as str] @@ -21,50 +22,6 @@ :end (or (str/index-of value "}" last-open) cursor) :partial (subs text-before (inc last-open))}))) -(defn find-active-token-range - "Returns {:start :end} for the token surrounding the cursor. - A token starts with '{', contains no spaces, and may be incomplete. - Returns nil if no valid token is active." - [value cursor] - (let [start (.lastIndexOf value "{" (dec cursor))] - (when (>= start 0) - (let [between (subs value (inc start) cursor)] - (when-not (re-find #"\s" between) - (let [after (subs value (inc start)) - close-index (.indexOf after "}") - close-pos (when (>= close-index 0) - (+ (inc start) close-index)) - space-index (.indexOf after " ") - space-pos (when (>= space-index 0) - (+ (inc start) space-index)) - open-index (.indexOf after "{") - open-pos (when (>= open-index 0) - (+ (inc start) open-index)) - candidates (->> [space-pos open-pos close-pos] - (remove nil?) - (sort)) - end (or (first candidates) cursor) - inside-token? (and (>= cursor start) (< cursor end))] - - {:start start - :end (if inside-token? - (inc end) - end)})))))) - -(defn replace-active-token - "Replaces the token at the cursor with `{new-name}`. - Returns {:value :cursor} with the updated value and new cursor position." - [value cursor new-name] - (let [new-token (str "{" new-name "}")] - (if-let [{:keys [start end]} (find-active-token-range value cursor)] - {:value (str (subs value 0 start) - new-token - (subs value end)) - :cursor (+ start (count new-token))} - {:value (str (subs value 0 cursor) - new-token - (subs value cursor)) - :cursor (+ cursor (count new-token))}))) (defn active-token [value input-node] (let [cursor (dom/selection-start input-node)] @@ -86,4 +43,4 @@ option (get-option options id) name (:name option)] - (replace-active-token value cursor name))) \ No newline at end of file + (cto/insert-ref value cursor name))) \ No newline at end of file