♻️ Use new fn for token parsing

This commit is contained in:
Eva Marco
2026-03-11 12:47:15 +01:00
parent 977f504cde
commit 0d2c880883
3 changed files with 62 additions and 76 deletions

View File

@@ -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))}))))

View File

@@ -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)))
(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)))

View File

@@ -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)))
(cto/insert-ref value cursor name)))