浏览代码

enhance: search cmd highlights search term and

allows for user specified limit of results.
Also enabled nbb-logseq tests for cli since first
test was introduced
Gabriel Horner 2 月之前
父节点
当前提交
c67e254b4a

+ 1 - 0
.clj-kondo/config.edn

@@ -166,6 +166,7 @@
              frontend.worker.util worker-util
              lambdaisland.glogi log
              logseq.cli.common.graph cli-common-graph
+             logseq.cli.text-util cli-text-util
              logseq.common.config common-config
              logseq.common.date-time-util date-time-util
              logseq.common.graph common-graph

+ 4 - 1
.github/workflows/cli.yml

@@ -69,6 +69,9 @@ jobs:
       - name: Fetch yarn deps
         run: yarn install --frozen-lockfile
 
+      - name: Run nbb-logseq tests
+        run: yarn test
+
       # In this job because it depends on an npm package
       - name: Load namespaces into nbb-logseq
         run: bb test:load-all-namespaces-with-nbb .
@@ -93,7 +96,7 @@ jobs:
           bb: ${{ env.BABASHKA_VERSION }}
 
       - name: Run clj-kondo lint
-        run: clojure -M:clj-kondo --lint src
+        run: clojure -M:clj-kondo --lint src test
 
       - name: Carve lint for unused vars
         run: bb lint:carve

+ 1 - 0
deps/cli/.clj-kondo/config.edn

@@ -13,6 +13,7 @@
              logseq.cli.commands.graph cli-graph
              logseq.cli.common.graph cli-common-graph
              logseq.cli.util cli-util
+             logseq.cli.text-util cli-text-util
              logseq.common.config common-config
              logseq.common.graph common-graph
              logseq.common.util.date-time date-time-util

+ 3 - 0
deps/cli/package.json

@@ -10,5 +10,8 @@
     "@logseq/nbb-logseq": "logseq/nbb-logseq#feat-db-v24",
     "better-sqlite3": "11.10.0",
     "fs-extra": "^11.3.0"
+  },
+  "scripts": {
+    "test": "yarn nbb-logseq -cp test -m nextjournal.test-runner"
   }
 }

+ 28 - 4
deps/cli/src/logseq/cli/commands/search.cljs

@@ -3,17 +3,40 @@
   (:require [clojure.pprint :as pprint]
             [clojure.string :as string]
             [logseq.cli.util :as cli-util]
+            [logseq.cli.text-util :as cli-text-util]
             [promesa.core :as p]))
 
 (def spec {:api-query-token {:alias :a
                              :require true
                              :desc "Api server token"}
            :raw {:alias :r
-                 :desc "Print raw response"}})
+                 :desc "Print raw response"}
+           :limit {:alias :l
+                   :default 100
+                   :desc "Limit max number of results"}})
+
+(defn- highlight
+  "Shows up as soft red on terminals that support ANSI 24-bit color like iTerm"
+  [text]
+  (str "\u001b[38;2;" 242 ";" 101 ";" 106 "m" text "\u001b[0m"))
+
+(defn- highlight-content-query
+  "Return string with highlighted content FTS result. CLI version of cmdk/highlight-content-query"
+  [content]
+  (when-not (string/blank? content)
+    ;; why recur? because there might be multiple matches
+    (loop [content content]
+      (let [[b-cut hl-cut e-cut] (cli-text-util/cut-by content "$pfts_2lqh>$" "$<pfts_2lqh$")
+            new-result (str b-cut (highlight hl-cut) e-cut)]
+        (if-not (string/blank? e-cut)
+          (recur new-result)
+          new-result)))))
 
 (defn search
-  [{{:keys [search-terms api-query-token raw]} :opts}]
-  (-> (p/let [resp (cli-util/api-fetch api-query-token "logseq.app.search" [(string/join " " search-terms)])]
+  [{{:keys [search-terms api-query-token raw limit]} :opts}]
+  (-> (p/let [resp (cli-util/api-fetch api-query-token
+                                       "logseq.app.search"
+                                       [(string/join " " search-terms) {:limit limit}])]
         (if (= 200 (.-status resp))
           (p/let [body (.json resp)]
             (let [{:keys [blocks]} (js->clj body :keywordize-keys true)]
@@ -23,7 +46,8 @@
                 (println (string/join "\n"
                                       (->> blocks
                                            (map :block/title)
-                                           (map #(string/replace % "\n" "\\\\n"))))))))
+                                           (map #(string/replace % "\n" "\\\\n"))
+                                           (map highlight-content-query)))))))
           (cli-util/api-handle-error-response resp)))
       (p/catch (fn [err]
                  (js/console.error "Error:" err)

+ 23 - 0
deps/cli/src/logseq/cli/text_util.cljs

@@ -0,0 +1,23 @@
+(ns logseq.cli.text-util
+  "Text utils"
+  (:require [clojure.string :as string]))
+
+(defn cut-by
+  "Cut string by specified wrapping symbols, only match the first occurrence.
+     value - string to cut
+     before - cutting symbol (before)
+     end - cutting symbol (end)"
+  [value before end]
+  (let [b-pos (string/index-of value before)
+        b-len (count before)]
+    (if b-pos
+      (let [b-cut (subs value 0 b-pos)
+            m-cut (subs value (+ b-pos b-len))
+            e-len (count end)
+            e-pos (string/index-of m-cut end)]
+        (if e-pos
+          (let [e-cut (subs m-cut (+ e-pos e-len))
+                m-cut (subs m-cut 0 e-pos)]
+            [b-cut m-cut e-cut])
+          [b-cut m-cut nil]))
+      [value nil nil])))

+ 1 - 1
deps/cli/src/logseq/cli/util.cljs

@@ -1,4 +1,4 @@
-(ns logseq.cli.util
+(ns ^:node-only logseq.cli.util
   "Util fns"
   (:require ["path" :as node-path]
             [logseq.cli.common.graph :as cli-common-graph]

+ 35 - 0
deps/cli/test/logseq/cli/text_util_test.cljs

@@ -0,0 +1,35 @@
+(ns logseq.cli.text-util-test
+  (:require [cljs.test :refer [are deftest]]
+            [logseq.cli.text-util :as cli-text-util]))
+
+(deftest test-cut-by
+  (are [x y] (= x y)
+    ["" "" ""]
+    (cli-text-util/cut-by "[[]]" "[[" "]]")
+
+    ["" "abc" ""]
+    (cli-text-util/cut-by "[[abc]]" "[[" "]]")
+
+    ["012 " "6" " [[2]]"]
+    (cli-text-util/cut-by "012 [[6]] [[2]]" "[[" "]]")
+
+    ["" "prop" "value"]
+    (cli-text-util/cut-by "prop::value" "" "::")
+
+    ["prop" "" "value"]
+    (cli-text-util/cut-by "prop::value" "::" "")
+
+    ["some " "content" " here"]
+    (cli-text-util/cut-by "some $pfts>$content$pfts<$ here" "$pfts>$" "$pfts<$")
+
+    ["some " "content$pft" nil]
+    (cli-text-util/cut-by "some $pfts>$content$pft" "$pfts>$" "$pfts<$")
+
+    ["some $pf" nil nil]
+    (cli-text-util/cut-by "some $pf" "$pfts>$" "$pfts<$")
+
+    ["" "content" ""]
+    (cli-text-util/cut-by "$pfts>$content$pfts<$" "$pfts>$" "$pfts<$")
+
+    ["" "content$p" nil]
+    (cli-text-util/cut-by "$pfts>$content$p" "$pfts>$" "$pfts<$")))

+ 3 - 20
src/main/frontend/util/text.cljs

@@ -5,7 +5,8 @@
             [frontend.config :as config]
             [frontend.util :as util]
             [goog.string :as gstring]
-            [logseq.common.path :as path]))
+            [logseq.common.path :as path]
+            [logseq.cli.text-util :as cli-text-util]))
 
 (defonce between-re #"\(between ([^\)]+)\)")
 
@@ -121,25 +122,7 @@
              []
              ks))))
 
-(defn cut-by
-  "Cut string by specified wrapping symbols, only match the first occurrence.
-     value - string to cut
-     before - cutting symbol (before)
-     end - cutting symbol (end)"
-  [value before end]
-  (let [b-pos (string/index-of value before)
-        b-len (count before)]
-    (if b-pos
-      (let [b-cut (subs value 0 b-pos)
-            m-cut (subs value (+ b-pos b-len))
-            e-len (count end)
-            e-pos (string/index-of m-cut end)]
-        (if e-pos
-          (let [e-cut (subs m-cut (+ e-pos e-len))
-                m-cut (subs m-cut 0 e-pos)]
-            [b-cut m-cut e-cut])
-          [b-cut m-cut nil]))
-      [value nil nil])))
+(def cut-by cli-text-util/cut-by)
 
 (defn get-graph-name-from-path
   "Get `Dir/GraphName` style name for from repo-url.

+ 2 - 2
src/main/logseq/api.cljs

@@ -1233,8 +1233,8 @@
 
 ;; search
 (defn ^:export search
-  [q']
-  (-> (search-handler/search q')
+  [q' & [opts]]
+  (-> (search-handler/search (state/get-current-repo) q' (if opts (js->clj opts :keywordize-keys true) {}))
       (p/then #(bean/->js %))))
 
 ;; helpers

+ 1 - 34
src/test/frontend/util/text_test.cljs

@@ -53,37 +53,4 @@
 
     '(false false false false false false true true true true true true)
     (map #(text-util/wrapped-by? "prop::value" % "::" "") (take 12 (range)))
-    ))
-
-
-(deftest test-cut-by
-  (are [x y] (= x y)
-    ["" "" ""]
-    (text-util/cut-by "[[]]" "[[" "]]")
-
-    ["" "abc" ""]
-    (text-util/cut-by "[[abc]]" "[[" "]]")
-
-    ["012 " "6" " [[2]]"]
-    (text-util/cut-by "012 [[6]] [[2]]" "[[" "]]")
-
-    ["" "prop" "value"]
-    (text-util/cut-by "prop::value" "" "::")
-
-    ["prop" "" "value"]
-    (text-util/cut-by "prop::value" "::" "")
-
-    ["some " "content" " here"]
-    (text-util/cut-by "some $pfts>$content$pfts<$ here" "$pfts>$" "$pfts<$")
-
-    ["some " "content$pft" nil]
-    (text-util/cut-by "some $pfts>$content$pft" "$pfts>$" "$pfts<$")
-
-    ["some $pf" nil nil]
-    (text-util/cut-by "some $pf" "$pfts>$" "$pfts<$")
-
-    ["" "content" ""]
-    (text-util/cut-by "$pfts>$content$pfts<$" "$pfts>$" "$pfts<$")
-
-    ["" "content$p" nil]
-    (text-util/cut-by "$pfts>$content$p" "$pfts>$" "$pfts<$")))
+    ))